http://wiki.mistrzowiekodowania.pl/api.php?action=feedcontributions&user=M+Kelniarz&feedformat=atomWiki Mistrzowie Kodowania - Wkład użytkownika [pl]2024-03-28T19:34:53ZWkład użytkownikaMediaWiki 1.23.2http://wiki.mistrzowiekodowania.pl/index.php?title=Scenariusz_2_-_SquashScenariusz 2 - Squash2015-10-01T04:09:32Z<p>M Kelniarz: /* Scenariusz 2 */</p>
<hr />
<div>=Squash w dwóch wariantach=<br />
==Scenariusz 2==<br />
'''Cele:'''<br />
<br />
Stworzymy prostą grę Squash, polegającą na odbijaniu piłeczki paletką, w dwóch wariantach. W ten sposób poznamy m.in. podstawy definiowania interfejsu użytkownika oraz nauczymy się wykonywać proste animacje. Po wykonaniu ćwiczenia będziemy też potrafili sterować obiektami za pomocą przeciągania palcem (pierwszy wariant) po ekranie oraz poprzez przechylanie telefonu (drugi wariant).<br />
<br />
W tej wersji Squasha nie będzie systemu naliczania punktów, jak w tradycyjnej wersji tej gry. W naszej aplikacji na dole będzie umieszczona czerwona linia i jeśli piłka się z nią zderzy, to nastąpi przegrana. Co więcej, gdy nie odbijemy piłeczki i ta spadnie na czerwoną linię, boisko zmieni kolor na szary, co będzie oznaczało koniec gry.<br />
<br />
<ol>'''<li>Rozpoczęcie pracy</li>'''<br />
Wejdźmy na stronę [http://appinventor.mit.edu http://appinventor.mit.edu] i wybierzmy '''Create''', by uruchomić App Inventor. Następnie przejdźmy do zakładki '''My Projects''' (1), gdzie znajdziemy wszystkie nasze projekty - wystarczy tylko zalogować się na odpowiednie konto Google. W celu rozpoczęcia pracy nad nowym projektem kliknijmy na '''Start new project''' (2) i wpiszmy w oknie jego nazwę, np. Squash.<br />
<br />
[[Plik:s2-1.png|800px]]<br />
<br />
Nastąpi teraz automatyczne przejście do okna budowy aplikacji.<br />
<br />
Jak już wspomnieliśmy powyżej - w pierwszym wariancie naszej gry sterowanie paletką będzie odbywało się poprzez przeciąganie palcem po ekranie smartfona, natomiast w drugiej wersji będziemy sterować obracając nim. Obracanie ekranu zgodnie z pozycją telefonu czy tabletu jest domyślnym zachowaniem. Dlatego też w pierwszym wariancie musimy zablokować ekran po to, by ten nie zmieniał swojej orientacji. I od tego właśnie zaczniemy budowę naszej gry.<br />
<br />
Przejdźmy zatem do okna '''Properties''' i dla komponentu '''Screen1,''' w polu '''Screen Orientation''' (1) wybierzmy '''Portrait'''. Dzięki temu nasz ekran zawsze będzie wyświetlany pionowo, niezależnie od tego, w jakiej pozycji znajduje się urządzenie. Dodatkowo w polu '''Title''' wpiszmy tytuł naszego bieżącego komponentu (2). Nazwijmy go '''Squash'''.<br />
<br />
[[Plik:s2-2.png]]<br />
<br />
'''<li>Squash - projektowanie interfejsu</li>'''<br />
Po zablokowaniu obrotu ekranu przejdźmy do dodania komponentów. W naszej aplikacji wykorzystamy trzy elementy - wszystkie znajdziemy w grupie Drawing and Animation. Są to:<br />
<ol>'''<li>Canvas''' ''(zamknięty obszar)'' - jest to komponent ograniczający obszar animacji oraz rysowania. W obszarze tego komponentu poruszają się Ball oraz ImageSprite.</li><br />
'''<li>Ball''' ''(piłka)'' - w naszej aplikacji to po prostu piłka, którą będziemy odbijać za pomocą paletki.</li><br />
'''<li>ImageSprite''' ''(“duszek”)'' - znany ze Scratcha duszek. W naszej aplikacji będzie to paletka. '''Image Sprite''' jest podobny do komponentu '''Ball''', jednak duszek ma kształt prostokąta, a jego tłem może być dowolny plik graficzny, np. w formacie jpg.</li><br />
</ol><br />
<br />
[[Plik:s2-3.png]]<br />
<br />
Jako pierwszy komponent dodajmy '''Canvas''' (1).Przeciągnijmy go na nasz obszar roboczy, czyli '''Viewer'''.<br />
<br />
[[Plik:s2-4.png]]<br />
<br />
Po tym, jak wstawiliśmy komponent '''Canvas''', musimy zmienić jego cechy w oknie '''Properties'''. Zmodyfikujmy dwa atrybuty: '''Width''' ''(szerokość)'' oraz '''Height''' ''(wysokość)''. Dla większości komponentów zarówno szerokość, jak i wysokość można ustawić jako:<br />
<ol>'''<li>Automatic''' ''(automatyczna)'' - system samodzielnie dobierze odpowiednią wartość szerokości i wysokości lub pozostawi je<br />
w standardowym ustawieniu.</li><br />
'''<li>Fill parent''' ''(wypełnienie obiektu nadrzędnego)'' - sprawia, że komponent przejmuje wielkość komponentu nadrzędnego. W przypadku naszej aplikacji zaznaczenie tej opcji sprawiłoby, że obszar '''Canvas1''' przejąłby szerokość i wysokość od komponentu '''Screen1''', co możemy zauważyć na ilustracji powyżej, w oknie '''Components''' - '''Cavas1''' jest obiektem podrzędnym dla '''Screen1'''.</li><br />
<li>'''... pixels - szerokość/wysokość o podanej przez nas liczbie pikseli.</li></ol><br />
Ustawmy zatem dla komponentu '''Canvas1''' wartości '''Width''' jako '''Fill Parent''' (1) oraz '''Height''' jako 300 pikseli(2).<br />
<br />
Teraz czas na kolejne komponenty. Dodajmy '''Ball''' (1) oraz '''ImageSprite''' (2) w dowolne miejsca w obrębie komponentu '''Canvas1'''. Tak jak wspomnieliśmy wcześniej, komponenty '''Ball''' oraz '''ImageSprite''' mogą być umieszczone jedynie na komponencie '''Canvas'''. Nie można umieścić ich poza tym obszarem, bezpośrednio na ekranie telefonu.<br />
<br />
[[Plik:s2-5.png]]<br />
<br />
Po dodaniu dwóch następnych komponentów dostosujmy ich właściwości tak, by odpowiadały naszym założeniom. Zacznijmy od komponentu '''Ball''' - na początek zmieńmy nazwę tego obiektu, klikając '''Rename''' (1) i wpisując '''Piłka''' w polu '''New Name'''. Następnie zmieńmy kilka cech tego komponentu w oknie właściwości, czyli '''Properties''':<br />
<ul><li>'''Heading''' (''kierunek'')- wpiszmy wartość 50 (2)</li><br />
<li>'''Paint Color''' (''kolor'')- wybierzmy '''Blue''' (3)</li><br />
<li>'''Radius''' (''promień'')- promień, czyli po prostu wielkość piłki ustalmy na 5 (4)</li><br />
<li>'''Speed''' (''prędkość'') - tutaj wpiszmy wartość 100 (5)</li><br />
<li>'''Współrzędne X i Y''' - obu współrzędnym nadajmy wartość 100 (6)</li></ul><br />
Inaczej niż w Scratchu, w programie App Inventor komponenty Ball oraz ImageSprite mogą mieć nadaną własną prędkość. W Scratchu efekt ten osiągaliśmy poprzez wielokrotne przesuwanie obiektu. Tutaj wystarczy, że nadamy komponentowi kierunek (Heading) oraz prędkość (Speed), zaś resztę pracy wykona za nas komputer.<br />
<br />
[[Plik:info.png|left]]''Warto zwrócić uwagę na hierarchię komponentów w oknie '''Components'''. Jak pamiętamy, w poprzedniej aplikacji wszystkie komponenty były bezpośrednio podrzędne dla '''Screen1'''. Tutaj podrzędny dla '''Screen1''' jest tylko '''Canvas1''', natomiast pozostałe dwa komponenty ('''Piłka''' oraz '''ImageSprite''') są podrzędne dla komponentu '''Canvas1'''.''<br />
<br />
<br />
[[Plik:s2-6.png]]<br />
<br />
Zmieńmy jeszcze nazwy pozostałych komponentów. '''Canvas1''' przestawmy na '''Boisko''' (1), zaś '''ImageSprite1''' na '''Paletka''' (2).<br />
<br />
[[Plik:s2-7.png]]<br />
<br />
Teraz przejdziemy do następnego kroku, czyli do skonfigurowania paletki.<br />
<br />
[[Plik:s2-8.png]]<br />
<br />
Przejdźmy zatem do zmiany właściwości komponentu o nazwie Paletka. Na początek kliknijmy na paletkę w oknie Components, by ją zaznaczyć - dzięki temu w oknie Properties pojawią się opcje, które pozwolą nam skonfigurować naszą paletkę. Konfigurację jej cech podzielimy na dwa kroki. W pierwszym kroku zadbamy o jej wygląd, zaś w drugim zajmiemy się jej rozmiarem i pozycją.<br />
<ol><li>'''Ustawienie pliku graficznego''' - wygląd paletki będzie wczytany z pliku graficznego, który załadujemy do programu. Paletka bez załadowanej grafiki byłaby przezroczysta, a to zdecydowanie utrudniłoby nam grę. Musimy zatem przygotować dowolny plik graficzny, np. w formacie png i wczytać go do mediów aplikacji, by następnie przypisać do paletki. Kliknijmy więc na '''Upload File''' (1) w oknie '''Media''' i odszukajmy plik, który chcemy wczytać do programu. Następnie przechodzimy do okna '''Properties''' i tam w polu '''Picture''' z rozwijanej listy wybierzmy nasz plik. Plików multimedialnych nie możemy przypisać bezpośrednio do komponentów, stąd w pierwszej kolejności musieliśmy wczytać plik do biblioteki mediów.</li><br />
<li>'''Wielkość i pozycja''' - po tym, jak wczytaliśmy już plik graficzny, przejdźmy do ustawienia pozostałych parametrów. Współrzędną X ustawmy na 100 pikseli, zaś Y - na 270 (3). Następnie parametry '''Width''' (szerokość) na 70 pikseli, a '''Height''' (wysokość) na 20 pikseli.</li></ol><br />
<br />
'''<li>Squash - programowanie aplikacji</li>'''<br />
Po tym, jak zakończyliśmy projektowanie interfejsu aplikacji, możemy zająć się stworzeniem odpowiedniego programu. Tym razem zbudowanie poprawnego kodu będzie wymagało od nas większej pracy niż w przypadku poprzedniej aplikacji. Tam wystarczyła nam tylko jedna instrukcja zbudowana z bloków, natomiast tutaj potrzebujemy ich kilka. Przejdźmy więc teraz do zakładki '''Blocks''', a poniżej, krok po kroku, omówimy wszystkie instrukcje.<br />
<br />
'''Zderzenie piłki z paletką i odbicie piłki'''<br />
<br />
Podstawową interakcją w naszej grze jest zderzenie piłeczki z paletką. Gdy do tego dojdzie, piłka musi odbić się od paletki. Musimy zatem ustalić, w jaki sposób ma zachować się piłka i określić, w stosunku do jakiego obiektu to zachowanie ma wystąpić. <br />
<br />
Naszą instrukcję można opisać w następujący sposób: '''Kiedy piłka zderzy się z innym obiektem, to odbij piłkę tak, jakby dotknęła dolnej krawędzi.'''<br />
<br />
[[Plik:s2-9.png]]<br />
<br />
Jak to działa? Przede wszystkim pamiętajmy, że piłka ma swoją prędkość. Gdy poruszająca się '''Piłka''' uderza w krawędź '''Canvas''' (nasze '''Boisko'''), to wywołuje wydarzenie '''EdgeReached''' (''zetknięcie z krawędzią''), a gdy uderza w inny obiekt, to wywołuje wydarzenie '''CollidedWith''' (''zderzenie z...''). My na ekranie mamy tylko jeden obiekt inny niż piłka, czyli paletkę. Zatem gdy piłka uderzy w paletkę, to zostanie uruchomiona akcja '''call[Piłka].Bounce''' (“''odbij piłkę''”). Akcja odbicia musi jeszcze wiedzieć, w którą stronę ma piłkę odbić, gdy ta uderzy w krawędź boczną lub górną i właśnie do tego służy parametr '''edge''' (''krawędź''). Jego wartość ustawiona na -1 powoduje odbicie '''Piłki''' tak, jakby dotknęła dolnej krawędzi (oznaczenia wszystkich krawędzi znajdują<br />
się dalej).<br />
<br />
'''Other''' (''inny obiekt''), można wykorzystać do ustalenia, w który obiekt uderzyła '''Piłka'''. My na ekranie mamy tylko paletkę, więc nie musimy sprawdzać wartości '''other'''.<br />
<br />
Polecenia '''When[Piłka].CollidedWith''' oraz '''Call[Piłka].Bounce''' znajdziemy w grupie '''Piłka''' (1), zaś obiekt z wartością liczbową - w grupie '''Math''' (2).<br />
<br />
[[Plik:s2-10.png]]<br />
<br />
[[Plik:info.png]]''Wszystkie instrukcje, tak jak w Scratchu, podzielone są na kategorie oznaczone odpowiednimi kolorami, co ułatwia nawigację.''<br />
<br />
<br />
'''Numeracja krawędzi ekranu w App Inventorze.'''<br />
<br />
Przed momentem skonfigurowaliśmy uderzenie piłki w dolną krawędź ekranu, która jest oznaczona numerem -1. Skąd wziął się właśnie taki numer? Krawędzie w programie App Inventor mają takie oznaczenia, jakie zaprezentowano na poniższej ilustracji. Krawędź północna oznaczona jest numerem 1, północno-wschodnia numerem 2 i w ten sposób docieramy do krawędzi dolnej, która jest oznaczona numerem -1.<br />
<br />
[[Plik:s2-11.png]]<br />
<br />
'''Zderzenie piłki z krawędzią i odbicie piłki od krawędzi.'''<br />
<br />
Teraz zaprogramujemy wydarzenie zderzenia piłki z krawędzią. Tutaj musimy rozróżnić dwa rodzaje krawędzi - krawędź boczną i krawędź dolną. Jeśli piłka zderzy się z krawędzią boczną, to zostanie odbita, a wartość jej prędkości zwiększy się o 1. Natomiast jeśli zderzy się krawędzią dolną, to nastąpi ponowne rozpoczęcie gry poprzez wywołanie odrębnej procedury, którą przygotujemy.<br />
<br />
[[Plik:squash-9.png|600px]]<br />
<br />
Najpierw sprawdzamy, czy piłka uderzyła w krawędź dolną (wartość edge wynoszącą -1). Krawędź -1 oznacza, że gracz przepuścił piłkę (nie odbił jej) i powoduje to rozpoczęcie gry od początku – poprzez wywołanie procedury reset Call[reset], którą przygotujemy za chwilę.<br />
<br />
Jeśli piłka uderzy w krawędź boczną, to zostaną wykonane dwie akcje:<br />
<br />
1. Odbij Piłkę tak, jakby się zderzyła z odpowiednią krawędzią (identyfikator krawędzi uzyskujemy przy pomocy '''get[edge]''')<br />
<br />
2. Zwiększ prędkość piłki o jeden więcej '''(Set[Piłka].Speed to [Piłka].[Speed] + 1)'''.<br />
<br />
Na zakończenie dołóżmy jeszcze akcję '''set[Screen1].[Title]''' na „Squash - ”&[Piłka]. [Speed], czyli ustaw pasek tytułu na napis Squash oraz prędkość poruszania się Piłki.<br />
<br />
'''Wariant pierwszy - poruszanie paletką za pomocą ruchu palca.'''<br />
<br />
Kolejnym krokiem będzie zaprogramowanie mechanizmu poruszania paletki poprzez przeciągnięcie palcem. Tutaj wykorzystamy funkcję <b>when[Paletka].Dragged.</b><br />
<br />
[[Plik:squash-10.png|600px]]<br />
<br />
'''when[Paletka].Dragged''' ''(kiedy Paletka przeciągnięta)'', to ustaw współrzędną X Paletki na wartość '''currentX''' (czyli aktualna współrzędna X - miejsce, gdzie dotkniemy/przeciągniemy palcem ekranu) zmniejszona o połowę szerokości Paletki '''([Paletka].[Width] / 2)'''. Musimy więc wewnątrz działania matematycznego odejmowanie zawrzeć kolejne działanie - dzielenie.<br />
<br />
Dlaczego zmniejszyliśmy szerokość o połowę? Polecenie '''set[Paletka].[X]''' ustawia lewy górny róg Paletki w miejscu X. Z tego powodu musimy odjąć połowę jej szerokości, żeby palec wskazywał środek paletki, a nie jej lewą krawędź.<br />
<br />
'''Przygotowanie procedury reset'''<br />
<br />
Teraz przygotujmy procedurę własną reset. Będzie ona uruchamiana zawsze, gdy piłka dotknie dolnej krawędzi oraz zawsze na początku gry. Będą w niej zawarte wszystkie domyślne dla naszej gry parametry, takie jak kolor tła, czy wymiary boiska. Dzięki temu nasza gra po porażce i przy każdym wznowieniu oraz na początku zawsze będzie wyglądała i działała tak samo. W obszarze '''Blocks''' w grupie '''Procedures''' znajdźmy '''to[procedure] do''' i przeciągnijmy ten element do obszaru ''Viewer''. Następnie zmieńmy jego nazwę na ''reset'' i wstawmy poszczególne klocki, jak na poniższej ilustracji.<br />
<br />
[[Plik:squash-10a.png|600px]]<br />
<br />
1. Na początek ustawmy kolor tła naszego Boiska – jeżeli kolor jest szary (czyli jeśli przegraliśmy), to ustawiamy na biały. Dodajmy jeszcze warunek, że jeżeli boisko ma jakikolwiek inny kolor niż szary, to ustawiamy na biały - o tym za chwilę.<br />
<br />
2. Następnie ustawmy parametry początkowe Piłki – współrzędne X i Y, kierunek ('''Heading''') oraz prędkość piłki ('''Speed'''). Dzięki temu na początku gry piłka zawsze będzie w tej samej pozycji.<br />
<br />
3. Na samym dole, wzdłuż dolnej krawędzi Boiska (linia x1) rysujemy linię (w kolorze i szerokości ustawionej w procedurze '''when[Screen1].Initialize''', którą stworzymy za chwilę). Linia ta musi być za każdym razem rysowana ponownie, ponieważ ustawienie tła Boiska (na szare lub białe) powyżej powoduje jej usunięcie (wyczyszczenie całości Boiska).<br />
<br />
Przypomnijmy jeszcze raz, że procedura reset będzie uruchamiana za każdym razem, gdy Piłka dotknie dolnej krawędzi Boiska (czerwonej linii) oraz podczas uruchomienia aplikacji.<br />
<br />
'''Instrukcja when[Screen1].Initialize'''<br />
<br />
Została nam już ostatnia instrukcja, która będzie uruchamiana w momencie inicjowania komponentu Screen1, czyli w naszym przypadku po prostu przy każdym starcie aplikacji. W tej instrukcji zdefiniujemy parametry początkowe naszej aplikacji. <br />
<br />
[[Plik:squash-11.png|600px]]<br />
<br />
1. Szerokość Paletki ustawmy na ¼ szerokości Boiska.<br />
<br />
2. Ustalmy parametry rysowania Boiska (kolor czerwony, szerokość/grubość rysowania 9) – to wykorzystamy do rysowania czerwonej linii na dole Boiska.<br />
<br />
3. Na sam koniec uruchamiamy jeszcze procedurę reset. I tutaj znajdziemy odpowiedź, dlaczego w procedurze reset sprawdzane są również inne kolory boiska niż tylko szary. Program rozpoczyna od procedury '''when[Screen1].Initialize''' i ustawia obrys koloru boiska na czerwony o grubości linii 9. Procedura '''reset''' z kolei sprawdza, jaki jest kolor boiska i jeżeli jest szary lub inny niż szary, zmienia kolor na biały, rysując dodatkowo trzy linie - górną oraz boczne. W ten sposób dolna linia w czerwonym kolorze pozostaje na boisku, również po wykonaniu procedury reset. Musieliśmy rozwiązać to w taki sposób, ponieważ porażkę sygnalizujemy zmianą koloru tła, natomiast zamiana koloru tła spowodowałaby usunięcie tej linii.<br />
<br />
'''<li>Udostępnianie aplikacji</li>'''<br />
<br />
Nasza aplikacja działa teraz prawidłowo, zaś paletka przemieszcza się, kiedy przesuwamy palcem po ekranie. Korzystając z faktu, że mamy ciekawą, działającą aplikację, poświęćmy teraz chwilę na udostępnienie tej aplikacji dalej po to, by można było zainstalować ją na dowolnym smartfonie. W tym celu kliknijmy w menu Build (1), gdzie znajdziemy dwie funkcje (2):<br />
<br />
1.App (Provide QP code for .apk) - wybranie tej opcji spowoduje wyświetlenie kodu QR i da możliwość załadowania przy pomocy tego kodu samodzielnej aplikacji na telefonie, bez użycia MIT AI2 Companion.<br />
<br />
2.App (save .apk to my computer) - wybranie tego polecenia spowoduje zapisanie aplikacji na komputerze jako plik .apk. Dzięki temu możemy chociażby przesłać aplikację jako załącznik w e-mailu.<br />
<br />
[[Plik:squash-12.png|600px]]<br />
<br />
'''<li>Suqash, wariant drugi - sterowanie paletką poprzez wychylenia telefonu</li>'''<br />
<br />
Teraz przejdźmy do zaprogramowania drugiego wariantu, czyli sterowania paletką poprzez obracanie smartfonem czy tabletem. Chcemy oczywiście zachować pierwszy wariant gry, dlatego stworzymy teraz nowy zapis projektu i to na nim wprowadzimy odpowiednie zmiany.<br />
Wybierzmy zatem '''Projects (1)''' w menu głównym, a następnie '''Save projects as... (2)''' i w polu ''<b>New name:</b>'' wpiszmy nową nazwę: '''Squash_przechylanie.'''<br />
<br />
[[Plik:squash-12a.png|600px]]<br />
<br />
Z grupy '''Sensors <i>(czujniki</i>)''' wybierzmy komponent o nazwie '''AccelerometerSensor (1)''' i przeciągnijmy go na obszar projektowania interfejsu. Jako że '''AccelerometerSensor''' jest obiektem niewidocznym, to nie zajmuje on miejsca na ekranie, ale możemy zobaczyć go poniżej ekranu, w sekcji '''Non-visible components (2).'''<br />
Komponent '''AccelerometerSensor''' będzie przez nas wykorzystany do odczytywania przechylenia telefonu.<br />
<br />
[[Plik:info.png|left]]''Akcelerometr, czyli użyty przez nas komponent jest przyrządem służącym do pomiaru przyspieszeń liniowych lub kątowych. Akcelerometry są coraz częściej instalowane w telefonach komórkowych, umożliwiając automatyczne wykrywanie ułożenia przestrzennego (pochylenie, przekręcenie) urządzenia.''<br />
<br />
<br />
<br />
Zanim zaczniemy sterować paletką przy pomocy wychyleń telefonu musimy dezaktywować (lub usunąć całkowicie) sterowanie za pomocą przeciągania palcem, czyli instrukcję '''when[Paletka].Dragged.'''<br />
<br />
W celu zdezaktywowania tej instrukcji przejdźmy do '''Blocks''', najedźmy kursorem myszy na procedurę sterowania paletką, czyli '''when[Paletka].Dragged (1)''' i kliknijmy prawym przyciskiem myszy. W ten sposób wywołamy menu podręczne, z którego musimy wybrać polecenie '''Disable Block''', czyli ''dezaktywuj'' (2). Cała nasza instrukcja zmieni kolor na szary, co oznacza, że jest nieaktywna i nie będzie wykonywana podczas działania aplikacji.<br />
<br />
[[Plik:squash-13.png|600px]]<br />
<br />
Korzystając z okazji, omówmy teraz pozostałe polecenia z menu podręcznego bloków:<br />
1. '''Duplicate ''(powiel)''''' - tworzy kopię danego bloku bądź całej instrukcji złożonej z bloczków.<br />
2. '''Add Comment ''(dodaj komentarz)''''' - umożliwia dodanie komentarza do bloku bądź całej instrukcji. Komentarz wyświetla się w postaci ikony ze znakiem zapytania w lewym górnym rogu bloku. Kliknięcie na tę ikonę powoduje rozwinięcie pola tekstowego.<br />
3. '''Collapse Block ''(złóż klocek)''''' - minimalizuje klocek bądź całą instrukcję poprzez “zwinięcie” do elementu zawierającego tylko tytuł.<br />
4. '''Delete x Blocks ''(Skasuj x bloków)''''' - usuwa wszystkie bloczki w instrukcji, gdzie x oznacza liczbę bloków. W naszym przypadku jest to 7.<br />
5. '''Help ''(pomoc)''''' - kliknięcie na ten element powoduje przeniesienie nas na stronę, gdzie opisane jest działanie danego bloku<br />
<br />
Przejdźmy teraz do ułożenia kompletnej instrukcji, pozwalającej sterować paletką poprzez obracanie telefonem.<br />
<br />
[[Plik:info.png|left]]'''UWAGA:''' Zaprezentowany program został przygotowany na telefon, jednak w przypadku stosowania tabletu koniecznym może być skorzystanie ze zmiennej '''yAccel''' (przyspieszenie względem osi y) zamiast '''xAccel''' - (przyspieszenie względem osi x). Jest to związane z faktem, iż na części testowanych tabletów oś X była przypisana do szerszej krawędzi (środka) ekranu, co powodowało wychylenia w porządku góra-dół. Natomiast w przypadku telefonów oś X jest przypisana do krótszej krawędzi i prezentuje wychylenia na prawo i lewo.<br />
<br />
Na początek potrzebujemy blok '''when[AccelerometerSensor1].AccelerationChanged''' (czyli wydarzenie: gdy zmieniło się położenie telefonu). Procedura ta posiada trzy parametry, które reprezentują położenie telefonu w trzech wymiarach. Nas interesować będzie tylko '''xAccel''', czyli pochylenie telefonu w prawo lub w lewo. Leżący płasko telefon ma wartość '''xAccel''' równą 0. Gdy przechylamy go w prawo, to wartość rośnie, a gdy przechylamy w lewo, to wartość '''xAccel''' maleje, przyjmując wartości ujemne.<br />
<br />
[[Plik:squash-14.png|600px]]<br />
<br />
Następnym krokiem będzie wprowadzenie zmiennej lokalnej (czyli aktywnej w ramach niniejszego zbioru klocków) '''nachylenieX''' - nadajmy je wartość równą '''xAccel''' '''''(1)'''''. <br />
<br />
Dodajmy teraz dwa warunki '''''(2)''''':<br />
<br />
- jeżeli '''nachylenieX > 5''', to ustaw '''nachylenieX = 5'''<br />
<br />
- jeżeli '''nachylenieX < -5''', to ustaw '''nachylenieX = -5'''<br />
<br />
Te dwa warunku służą ograniczeniu zakresu przechylenia telefonu. Chodzi o to, żeby paletka przemieszczała się w kierunku krawędzi telefonu przy nieznacznych przechyleniach urządzenia.<br />
<br />
Po wykonaniu obu warunków zmienna reprezentująca nachylenie będzie przyjmować wartości od -5 do 5. Przeliczmy tę zmienną tak, żeby zmieniała wartość<br />
od 0 do 1 (a nie od -5 do 5) – to nam ułatwi kolejne obliczenia. W tym celu ustawmy wartość zmiennej poprzez odjęcie od 5 nachylenia X (otrzymujemy<br />
liczbę 0 lub 10), a następnie podzielenie tego wyniku przez 10, co ostatecznie da nam wartość z przedziału 0-1 '''''(3)'''''.<br />
<br />
'''Alternatywna, skrócona instrukcja przechylania'''<br />
<br />
Zamiast zmiany lokalizacji paletki przy pomocy akcelerometru, możemy wykorzystać akcelerometr do sterowania prędkością (i kierunkiem) poruszania się paletki. Inaczej mówiąc, pochylenie telefonu nie steruje tym, w którym miejscu ma ustawić się paletka, ale tym, z jaką prędkością przesuwa się w stronę krawędzi.<br />
<br />
Jeżeli chcemy skorzystać z takiego rozwiązania, musimy usunąć poprzednią wersję procedury '''when.[AccelerometerSensor1].AccelerationChanged''' i zamiast niej wprowadzić poniższą wersję (musimy pamiętać, że w przypadku tabletów zamiast '''xAccel''' musimy skorzystać z '''yAccel'''):<br />
<br />
[[Plik:squash-15.png|600px]]<br />
<br />
'''<li>Podsumowanie</li>'''<br />
Nauczyliśmy się wykonywać proste animacje oraz wiemy już, jak sterować obiektami poprzez przeciąganie palcem po ekranie, a także z wykorzystaniem akceleratora - obracając telefonem. Poznaliśmy też podstawy definiowania interfejsu użytkownika. To wszystko daje nam dobrą podstawę do tworzenia kolejnych, bardziej rozbudowanych aplikacji w systemie Android.</div>M Kelniarzhttp://wiki.mistrzowiekodowania.pl/index.php?title=Scenariusz_2_-_SquashScenariusz 2 - Squash2015-09-30T15:57:32Z<p>M Kelniarz: /* Scenariusz 2 */</p>
<hr />
<div>=Squash w dwóch wariantach=<br />
==Scenariusz 2==<br />
'''Cele:'''<br />
<br />
Stworzymy prostą grę Squash, polegającą na odbijaniu piłeczki paletką, w dwóch wariantach. W ten sposób poznamy m.in. podstawy definiowania interfejsu użytkownika oraz nauczymy się wykonywać proste animacje. Po wykonaniu ćwiczenia będziemy też potrafili sterować obiektami za pomocą przeciągania palcem (pierwszy wariant) po ekranie oraz poprzez przechylanie telefonu (drugi wariant).<br />
<br />
W tej wersji Squasha nie będzie systemu naliczania punktów, jak w tradycyjnej wersji tej gry. W naszej aplikacji na dole będzie umieszczona czerwona linia i jeśli piłka się z nią zderzy, to nastąpi przegrana. Co więcej, gdy nie odbijemy piłeczki i ta spadnie na czerwoną linię, boisko zmieni kolor na szary, co będzie oznaczało koniec gry.<br />
<br />
<ol>'''<li>Rozpoczęcie pracy</li>'''<br />
Wejdźmy na stronę [http://appinventor.mit.edu http://appinventor.mit.edu] i wybierzmy '''Create''', by uruchomić App Inventor. Następnie przejdźmy do zakładki '''My Projects''' (1), gdzie znajdziemy wszystkie nasze projekty - wystarczy tylko zalogować się na odpowiednie konto Google. W celu rozpoczęcia pracy nad nowym projektem kliknijmy na '''Start new project''' (2) i wpiszmy w oknie jego nazwę, np. Squash.<br />
<br />
[[Plik:s2-1.png|800px]]<br />
<br />
Nastąpi teraz automatyczne przejście do okna budowy aplikacji.<br />
<br />
Jak już wspomnieliśmy powyżej - w pierwszym wariancie naszej gry sterowanie paletką będzie odbywało się poprzez przeciąganie palcem po ekranie smartfona, natomiast w drugiej wersji będziemy sterować obracając nim. Obracanie ekranu zgodnie z pozycją telefonu czy tabletu jest domyślnym zachowaniem. Dlatego też w pierwszym wariancie musimy zablokować ekran po to, by ten nie zmieniał swojej orientacji. I od tego właśnie zaczniemy budowę naszej gry.<br />
<br />
Przejdźmy zatem do okna '''Properties''' i dla komponentu '''Screen1,''' w polu '''Screen Orientation''' (1) wybierzmy '''Portrait'''. Dzięki temu nasz ekran zawsze będzie wyświetlany pionowo, niezależnie od tego, w jakiej pozycji znajduje się urządzenie. Dodatkowo w polu '''Title''' wpiszmy tytuł naszego bieżącego komponentu (2). Nazwijmy go '''Squash'''.<br />
<br />
[[Plik:s2-2.png]]<br />
<br />
'''<li>Squash - projektowanie interfejsu</li>'''<br />
Po zablokowaniu obrotu ekranu przejdźmy do dodania komponentów. W naszej aplikacji wykorzystamy trzy elementy - wszystkie znajdziemy w grupie Drawing and Animation. Są to:<br />
<ol>'''<li>Canvas''' ''(zamknięty obszar)'' - jest to komponent ograniczający obszar animacji oraz rysowania. W obszarze tego komponentu poruszają się Ball oraz ImageSprite.</li><br />
'''<li>Ball''' ''(piłka)'' - w naszej aplikacji to po prostu piłka, którą będziemy odbijać za pomocą paletki.</li><br />
'''<li>ImageSprite''' ''(“duszek”)'' - znany ze Scratcha duszek. W naszej aplikacji będzie to paletka. '''Image Sprite''' jest podobny do komponentu '''Ball''', jednak duszek ma kształt prostokąta, a jego tłem może być dowolny plik graficzny, np. w formacie jpg.</li><br />
</ol><br />
<br />
[[Plik:s2-3.png]]<br />
<br />
Jako pierwszy komponent dodajmy '''Canvas''' (1).Przeciągnijmy go na nasz obszar roboczy, czyli '''Viewer'''.<br />
<br />
[[Plik:s2-4.png]]<br />
<br />
Po tym, jak wstawiliśmy komponent '''Canvas''', musimy zmienić jego cechy w oknie '''Properties'''. Zmodyfikujmy dwa atrybuty: '''Width''' ''(szerokość)'' oraz '''Height''' ''(wysokość)''. Dla większości komponentów zarówno szerokość, jak i wysokość można ustawić jako:<br />
<ol>'''<li>Automatic''' ''(automatyczna)'' - system samodzielnie dobierze odpowiednią wartość szerokości i wysokości lub pozostawi je<br />
w standardowym ustawieniu.</li><br />
'''<li>Fill parent''' ''(wypełnienie obiektu nadrzędnego)'' - sprawia, że komponent przejmuje wielkość komponentu nadrzędnego. W przypadku naszej aplikacji zaznaczenie tej opcji sprawiłoby, że obszar '''Canvas1''' przejąłby szerokość i wysokość od komponentu '''Screen1''', co możemy zauważyć na ilustracji powyżej, w oknie '''Components''' - '''Cavas1''' jest obiektem podrzędnym dla '''Screen1'''.</li><br />
<li>'''... pixels - szerokość/wysokość o podanej przez nas liczbie pikseli.</li></ol><br />
Ustawmy zatem dla komponentu '''Canvas1''' wartości '''Width''' jako '''Fill Parent''' (1) oraz '''Height''' jako 300 pikseli(2).<br />
<br />
Teraz czas na kolejne komponenty. Dodajmy '''Ball''' (1) oraz '''ImageSprite''' (2) w dowolne miejsca w obrębie komponentu '''Canvas1'''. Tak jak wspomnieliśmy wcześniej, komponenty '''Ball''' oraz '''ImageSprite''' mogą być umieszczone jedynie na komponencie '''Canvas'''. Nie można umieścić ich poza tym obszarem, bezpośrednio na ekranie telefonu.<br />
<br />
[[Plik:s2-5.png]]<br />
<br />
Po dodaniu dwóch następnych komponentów dostosujmy ich właściwości tak, by odpowiadały naszym założeniom. Zacznijmy od komponentu '''Ball''' - na początek zmieńmy nazwę tego obiektu, klikając '''Rename''' (1) i wpisując '''Piłka''' w polu '''New Name'''. Następnie zmieńmy kilka cech tego komponentu w oknie właściwości, czyli '''Properties''':<br />
<ul><li>'''Heading''' (''kierunek'')- wpiszmy wartość 50 (2)</li><br />
<li>'''Paint Color''' (''kolor'')- wybierzmy '''Blue''' (3)</li><br />
<li>'''Radius''' (''promień'')- promień, czyli po prostu wielkość piłki ustalmy na 5 (4)</li><br />
<li>'''Speed''' (''prędkość'') - tutaj wpiszmy wartość 100 (5)</li><br />
<li>'''Współrzędne X i Y''' - obu współrzędnym nadajmy wartość 100 (6)</li></ul><br />
Inaczej niż w Scratchu, w programie App Inventor komponenty Ball oraz ImageSprite mogą mieć nadaną własną prędkość. W Scratchu efekt ten osiągaliśmy poprzez wielokrotne przesuwanie obiektu. Tutaj wystarczy, że nadamy komponentowi kierunek (Heading) oraz prędkość (Speed), zaś resztę pracy wykona za nas komputer.<br />
<br />
[[Plik:info.png|left]]''Warto zwrócić uwagę na hierarchię komponentów w oknie '''Components'''. Jak pamiętamy, w poprzedniej aplikacji wszystkie komponenty były bezpośrednio podrzędne dla '''Screen1'''. Tutaj podrzędny dla '''Screen1''' jest tylko '''Canvas1''', natomiast pozostałe dwa komponenty ('''Piłka''' oraz '''ImageSprite''') są podrzędne dla komponentu '''Canvas1'''.''<br />
<br />
<br />
[[Plik:s2-6.png]]<br />
<br />
Zmieńmy jeszcze nazwy pozostałych komponentów. '''Canvas1''' przestawmy na '''Boisko''' (1), zaś '''ImageSprite1''' na '''Paletka''' (2).<br />
<br />
[[Plik:s2-7.png]]<br />
<br />
Teraz przejdziemy do następnego kroku, czyli do skonfigurowania paletki.<br />
<br />
[[Plik:s2-8.png]]<br />
<br />
Przejdźmy zatem do zmiany właściwości komponentu o nazwie Paletka. Na początek kliknijmy na paletkę w oknie Components, by ją zaznaczyć - dzięki temu w oknie Properties pojawią się opcje, które pozwolą nam skonfigurować naszą paletkę. Konfigurację jej cech podzielimy na dwa kroki. W pierwszym kroku zadbamy o jej wygląd, zaś w drugim zajmiemy się jej rozmiarem i pozycją.<br />
<ol><li>'''Ustawienie pliku graficznego''' - wygląd paletki będzie wczytany z pliku graficznego, który załadujemy do programu. Paletka bez załadowanej grafiki byłaby przezroczysta, a to zdecydowanie utrudniłoby nam grę. Musimy zatem przygotować dowolny plik graficzny, np. w formacie png i wczytać go do mediów aplikacji, by następnie przypisać do paletki. Kliknijmy więc na '''Upload File''' (1) w oknie '''Media''' i odszukajmy plik, który chcemy wczytać do programu. Następnie przechodzimy do okna '''Properties''' i tam w polu '''Picture''' z rozwijanej listy wybierzmy nasz plik. Plików multimedialnych nie możemy przypisać bezpośrednio do komponentów, stąd w pierwszej kolejności musieliśmy wczytać plik do biblioteki mediów.</li><br />
<li>'''Wielkość i pozycja''' - po tym, jak wczytaliśmy już plik graficzny, przejdźmy do ustawienia pozostałych parametrów. Współrzędną X ustawmy na 100 pikseli, zaś Y - na 270 (3). Następnie parametry '''Width''' (szerokość) na 70 pikseli, a '''Height''' (wysokość) na 20 pikseli.</li></ol><br />
'''<li>Squash - programowanie aplikacji</li>'''<br />
Po tym, jak zakończyliśmy projektowanie interfejsu aplikacji, możemy zająć się stworzeniem odpowiedniego programu. Tym razem zbudowanie poprawnego kodu będzie wymagało od nas większej pracy niż w przypadku poprzedniej aplikacji. Tam wystarczyła nam tylko jedna instrukcja zbudowana z bloków, natomiast tutaj potrzebujemy ich kilka. Przejdźmy więc teraz do zakładki '''Blocks''', a poniżej, krok po kroku, omówimy wszystkie instrukcje.<br />
<br />
'''Zderzenie piłki z paletką i odbicie piłki'''<br />
<br />
Podstawową interakcją w naszej grze jest zderzenie piłeczki z paletką. Gdy do tego dojdzie, piłka musi odbić się od paletki. Musimy zatem ustalić, w jaki sposób ma zachować się piłka i określić, w stosunku do jakiego obiektu to zachowanie ma wystąpić. <br />
<br />
Naszą instrukcję można opisać w następujący sposób: '''Kiedy piłka zderzy się z innym obiektem, to odbij piłkę tak, jakby dotknęła dolnej krawędzi.'''<br />
<br />
[[Plik:s2-9.png]]<br />
<br />
Jak to działa? Przede wszystkim pamiętajmy, że piłka ma swoją prędkość. Gdy poruszająca się '''Piłka''' uderza w krawędź '''Canvas''' (nasze '''Boisko'''), to wywołuje wydarzenie '''EdgeReached''' (''zetknięcie z krawędzią''), a gdy uderza w inny obiekt, to wywołuje wydarzenie '''CollidedWith''' (''zderzenie z...''). My na ekranie mamy tylko jeden obiekt inny niż piłka, czyli paletkę. Zatem gdy piłka uderzy w paletkę, to zostanie uruchomiona akcja '''call[Piłka].Bounce''' (“''odbij piłkę''”). Akcja odbicia musi jeszcze wiedzieć, w którą stronę ma piłkę odbić, gdy ta uderzy w krawędź boczną lub górną i właśnie do tego służy parametr '''edge''' (''krawędź''). Jego wartość ustawiona na -1 powoduje odbicie '''Piłki''' tak, jakby dotknęła dolnej krawędzi (oznaczenia wszystkich krawędzi znajdują<br />
się dalej).<br />
<br />
'''Other''' (''inny obiekt''), można wykorzystać do ustalenia, w który obiekt uderzyła '''Piłka'''. My na ekranie mamy tylko paletkę, więc nie musimy sprawdzać wartości '''other'''.<br />
<br />
Polecenia '''When[Piłka].CollidedWith''' oraz '''Call[Piłka].Bounce''' znajdziemy w grupie '''Piłka''' (1), zaś obiekt z wartością liczbową - w grupie '''Math''' (2).<br />
<br />
[[Plik:s2-10.png]]<br />
<br />
[[Plik:info.png]]''Wszystkie instrukcje, tak jak w Scratchu, podzielone są na kategorie oznaczone odpowiednimi kolorami, co ułatwia nawigację.''<br />
<br />
<br />
'''Numeracja krawędzi ekranu w App Inventorze.'''<br />
<br />
Przed momentem skonfigurowaliśmy uderzenie piłki w dolną krawędź ekranu, która jest oznaczona numerem -1. Skąd wziął się właśnie taki numer? Krawędzie w programie App Inventor mają takie oznaczenia, jakie zaprezentowano na poniższej ilustracji. Krawędź północna oznaczona jest numerem 1, północno-wschodnia numerem 2 i w ten sposób docieramy do krawędzi dolnej, która jest oznaczona numerem -1.<br />
<br />
[[Plik:s2-11.png]]<br />
<br />
'''Zderzenie piłki z krawędzią i odbicie piłki od krawędzi.'''<br />
<br />
Teraz zaprogramujemy wydarzenie zderzenia piłki z krawędzią. Tutaj musimy rozróżnić dwa rodzaje krawędzi - krawędź boczną i krawędź dolną. Jeśli piłka zderzy się z krawędzią boczną, to zostanie odbita, a wartość jej prędkości zwiększy się o 1. Natomiast jeśli zderzy się krawędzią dolną, to nastąpi ponowne rozpoczęcie gry poprzez wywołanie odrębnej procedury, którą przygotujemy.<br />
<br />
[[Plik:squash-9.png|600px]]<br />
<br />
Najpierw sprawdzamy, czy piłka uderzyła w krawędź dolną (wartość edge wynoszącą -1). Krawędź -1 oznacza, że gracz przepuścił piłkę (nie odbił jej) i powoduje to rozpoczęcie gry od początku – poprzez wywołanie procedury reset Call[reset], którą przygotujemy za chwilę.<br />
<br />
Jeśli piłka uderzy w krawędź boczną, to zostaną wykonane dwie akcje:<br />
<br />
1. Odbij Piłkę tak, jakby się zderzyła z odpowiednią krawędzią (identyfikator krawędzi uzyskujemy przy pomocy '''get[edge]''')<br />
<br />
2. Zwiększ prędkość piłki o jeden więcej '''(Set[Piłka].Speed to [Piłka].[Speed] + 1)'''.<br />
<br />
Na zakończenie dołóżmy jeszcze akcję '''set[Screen1].[Title]''' na „Squash - ”&[Piłka]. [Speed], czyli ustaw pasek tytułu na napis Squash oraz prędkość poruszania się Piłki.<br />
<br />
'''Wariant pierwszy - poruszanie paletką za pomocą ruchu palca.'''<br />
<br />
Kolejnym krokiem będzie zaprogramowanie mechanizmu poruszania paletki poprzez przeciągnięcie palcem. Tutaj wykorzystamy funkcję <b>when[Paletka].Dragged.</b><br />
<br />
[[Plik:squash-10.png|600px]]<br />
<br />
'''when[Paletka].Dragged''' ''(kiedy Paletka przeciągnięta)'', to ustaw współrzędną X Paletki na wartość '''currentX''' (czyli aktualna współrzędna X - miejsce, gdzie dotkniemy/przeciągniemy palcem ekranu) zmniejszona o połowę szerokości Paletki '''([Paletka].[Width] / 2)'''. Musimy więc wewnątrz działania matematycznego odejmowanie zawrzeć kolejne działanie - dzielenie.<br />
<br />
Dlaczego zmniejszyliśmy szerokość o połowę? Polecenie '''set[Paletka].[X]''' ustawia lewy górny róg Paletki w miejscu X. Z tego powodu musimy odjąć połowę jej szerokości, żeby palec wskazywał środek paletki, a nie jej lewą krawędź.<br />
<br />
'''Przygotowanie procedury reset'''<br />
<br />
Teraz przygotujmy procedurę własną reset. Będzie ona uruchamiana zawsze, gdy piłka dotknie dolnej krawędzi oraz zawsze na początku gry. Będą w niej zawarte wszystkie domyślne dla naszej gry parametry, takie jak kolor tła, czy wymiary boiska. Dzięki temu nasza gra po porażce i przy każdym wznowieniu oraz na początku zawsze będzie wyglądała i działała tak samo. W obszarze '''Blocks''' w grupie '''Procedures''' znajdźmy '''to[procedure] do''' i przeciągnijmy ten element do obszaru ''Viewer''. Następnie zmieńmy jego nazwę na ''reset'' i wstawmy poszczególne klocki, jak na poniższej ilustracji.<br />
<br />
[[Plik:squash-10a.png|600px]]<br />
<br />
1. Na początek ustawmy kolor tła naszego Boiska – jeżeli kolor jest szary (czyli jeśli przegraliśmy), to ustawiamy na biały. Dodajmy jeszcze warunek, że jeżeli boisko ma jakikolwiek inny kolor niż szary, to ustawiamy na biały - o tym za chwilę.<br />
<br />
2. Następnie ustawmy parametry początkowe Piłki – współrzędne X i Y, kierunek ('''Heading''') oraz prędkość piłki ('''Speed'''). Dzięki temu na początku gry piłka zawsze będzie w tej samej pozycji.<br />
<br />
3. Na samym dole, wzdłuż dolnej krawędzi Boiska (linia x1) rysujemy linię (w kolorze i szerokości ustawionej w procedurze '''when[Screen1].Initialize''', którą stworzymy za chwilę). Linia ta musi być za każdym razem rysowana ponownie, ponieważ ustawienie tła Boiska (na szare lub białe) powyżej powoduje jej usunięcie (wyczyszczenie całości Boiska).<br />
<br />
Przypomnijmy jeszcze raz, że procedura reset będzie uruchamiana za każdym razem, gdy Piłka dotknie dolnej krawędzi Boiska (czerwonej linii) oraz podczas uruchomienia aplikacji.<br />
<br />
'''Instrukcja when[Screen1].Initialize'''<br />
<br />
Została nam już ostatnia instrukcja, która będzie uruchamiana w momencie inicjowania komponentu Screen1, czyli w naszym przypadku po prostu przy każdym starcie aplikacji. W tej instrukcji zdefiniujemy parametry początkowe naszej aplikacji. <br />
<br />
[[Plik:squash-11.png|600px]]<br />
<br />
1. Szerokość Paletki ustawmy na ¼ szerokości Boiska.<br />
<br />
2. Ustalmy parametry rysowania Boiska (kolor czerwony, szerokość/grubość rysowania 9) – to wykorzystamy do rysowania czerwonej linii na dole Boiska.<br />
<br />
3. Na sam koniec uruchamiamy jeszcze procedurę reset. I tutaj znajdziemy odpowiedź, dlaczego w procedurze reset sprawdzane są również inne kolory boiska niż tylko szary. Program rozpoczyna od procedury '''when[Screen1].Initialize''' i ustawia obrys koloru boiska na czerwony o grubości linii 9. Procedura '''reset''' z kolei sprawdza, jaki jest kolor boiska i jeżeli jest szary lub inny niż szary, zmienia kolor na biały, rysując dodatkowo trzy linie - górną oraz boczne. W ten sposób dolna linia w czerwonym kolorze pozostaje na boisku, również po wykonaniu procedury reset. Musieliśmy rozwiązać to w taki sposób, ponieważ porażkę sygnalizujemy zmianą koloru tła, natomiast zamiana koloru tła spowodowałaby usunięcie tej linii.<br />
<br />
'''<li>Udostępnianie aplikacji</li>'''<br />
<br />
Nasza aplikacja działa teraz prawidłowo, zaś paletka przemieszcza się, kiedy przesuwamy palcem po ekranie. Korzystając z faktu, że mamy ciekawą, działającą aplikację, poświęćmy teraz chwilę na udostępnienie tej aplikacji dalej po to, by można było zainstalować ją na dowolnym smartfonie. W tym celu kliknijmy w menu Build (1), gdzie znajdziemy dwie funkcje (2):<br />
<br />
1.App (Provide QP code for .apk) - wybranie tej opcji spowoduje wyświetlenie kodu QR i da możliwość załadowania przy pomocy tego kodu samodzielnej aplikacji na telefonie, bez użycia MIT AI2 Companion.<br />
<br />
2.App (save .apk to my computer) - wybranie tego polecenia spowoduje zapisanie aplikacji na komputerze jako plik .apk. Dzięki temu możemy chociażby przesłać aplikację jako załącznik w e-mailu.<br />
<br />
[[Plik:squash-12.png|600px]]<br />
<br />
'''<li>Suqash, wariant drugi - sterowanie paletką poprzez wychylenia telefonu</li>'''<br />
<br />
Teraz przejdźmy do zaprogramowania drugiego wariantu, czyli sterowania paletką poprzez obracanie smartfonem czy tabletem. Chcemy oczywiście zachować pierwszy wariant gry, dlatego stworzymy teraz nowy zapis projektu i to na nim wprowadzimy odpowiednie zmiany.<br />
Wybierzmy zatem '''Projects (1)''' w menu głównym, a następnie '''Save projects as... (2)''' i w polu ''<b>New name:</b>'' wpiszmy nową nazwę: '''Squash_przechylanie.'''<br />
<br />
[[Plik:squash-12a.png|600px]]<br />
<br />
Z grupy '''Sensors <i>(czujniki</i>)''' wybierzmy komponent o nazwie '''AccelerometerSensor (1)''' i przeciągnijmy go na obszar projektowania interfejsu. Jako że '''AccelerometerSensor''' jest obiektem niewidocznym, to nie zajmuje on miejsca na ekranie, ale możemy zobaczyć go poniżej ekranu, w sekcji '''Non-visible components (2).'''<br />
Komponent '''AccelerometerSensor''' będzie przez nas wykorzystany do odczytywania przechylenia telefonu.<br />
<br />
[[Plik:info.png|left]]''Akcelerometr, czyli użyty przez nas komponent jest przyrządem służącym do pomiaru przyspieszeń liniowych lub kątowych. Akcelerometry są coraz częściej instalowane w telefonach komórkowych, umożliwiając automatyczne wykrywanie ułożenia przestrzennego (pochylenie, przekręcenie) urządzenia.''<br />
<br />
<br />
Zanim zaczniemy sterować paletką przy pomocy wychyleń telefonu musimy dezaktywować (lub usunąć całkowicie) sterowanie za pomocą przeciągania palcem, czyli instrukcję '''when[Paletka].Dragged.'''<br />
<br />
W celu zdezaktywowania tej instrukcji przejdźmy do '''Blocks''', najedźmy kursorem myszy na procedurę sterowania paletką, czyli '''when[Paletka].Dragged (1)''' i kliknijmy prawym przyciskiem myszy. W ten sposób wywołamy menu podręczne, z którego musimy wybrać polecenie '''Disable Block''', czyli ''dezaktywuj'' (2). Cała nasza instrukcja zmieni kolor na szary, co oznacza, że jest nieaktywna i nie będzie wykonywana podczas działania aplikacji.<br />
<br />
[[Plik:squash-13.png|600px]]</div>M Kelniarzhttp://wiki.mistrzowiekodowania.pl/index.php?title=Scenariusz_2_-_SquashScenariusz 2 - Squash2015-09-30T15:44:42Z<p>M Kelniarz: /* Scenariusz 2 */</p>
<hr />
<div>=Squash w dwóch wariantach=<br />
==Scenariusz 2==<br />
'''Cele:'''<br />
<br />
Stworzymy prostą grę Squash, polegającą na odbijaniu piłeczki paletką, w dwóch wariantach. W ten sposób poznamy m.in. podstawy definiowania interfejsu użytkownika oraz nauczymy się wykonywać proste animacje. Po wykonaniu ćwiczenia będziemy też potrafili sterować obiektami za pomocą przeciągania palcem (pierwszy wariant) po ekranie oraz poprzez przechylanie telefonu (drugi wariant).<br />
<br />
W tej wersji Squasha nie będzie systemu naliczania punktów, jak w tradycyjnej wersji tej gry. W naszej aplikacji na dole będzie umieszczona czerwona linia i jeśli piłka się z nią zderzy, to nastąpi przegrana. Co więcej, gdy nie odbijemy piłeczki i ta spadnie na czerwoną linię, boisko zmieni kolor na szary, co będzie oznaczało koniec gry.<br />
<br />
<ol>'''<li>Rozpoczęcie pracy</li>'''<br />
Wejdźmy na stronę [http://appinventor.mit.edu http://appinventor.mit.edu] i wybierzmy '''Create''', by uruchomić App Inventor. Następnie przejdźmy do zakładki '''My Projects''' (1), gdzie znajdziemy wszystkie nasze projekty - wystarczy tylko zalogować się na odpowiednie konto Google. W celu rozpoczęcia pracy nad nowym projektem kliknijmy na '''Start new project''' (2) i wpiszmy w oknie jego nazwę, np. Squash.<br />
<br />
[[Plik:s2-1.png|800px]]<br />
<br />
Nastąpi teraz automatyczne przejście do okna budowy aplikacji.<br />
<br />
Jak już wspomnieliśmy powyżej - w pierwszym wariancie naszej gry sterowanie paletką będzie odbywało się poprzez przeciąganie palcem po ekranie smartfona, natomiast w drugiej wersji będziemy sterować obracając nim. Obracanie ekranu zgodnie z pozycją telefonu czy tabletu jest domyślnym zachowaniem. Dlatego też w pierwszym wariancie musimy zablokować ekran po to, by ten nie zmieniał swojej orientacji. I od tego właśnie zaczniemy budowę naszej gry.<br />
<br />
Przejdźmy zatem do okna '''Properties''' i dla komponentu '''Screen1,''' w polu '''Screen Orientation''' (1) wybierzmy '''Portrait'''. Dzięki temu nasz ekran zawsze będzie wyświetlany pionowo, niezależnie od tego, w jakiej pozycji znajduje się urządzenie. Dodatkowo w polu '''Title''' wpiszmy tytuł naszego bieżącego komponentu (2). Nazwijmy go '''Squash'''.<br />
<br />
[[Plik:s2-2.png]]<br />
<br />
'''<li>Squash - projektowanie interfejsu</li>'''<br />
Po zablokowaniu obrotu ekranu przejdźmy do dodania komponentów. W naszej aplikacji wykorzystamy trzy elementy - wszystkie znajdziemy w grupie Drawing and Animation. Są to:<br />
<ol>'''<li>Canvas''' ''(zamknięty obszar)'' - jest to komponent ograniczający obszar animacji oraz rysowania. W obszarze tego komponentu poruszają się Ball oraz ImageSprite.</li><br />
'''<li>Ball''' ''(piłka)'' - w naszej aplikacji to po prostu piłka, którą będziemy odbijać za pomocą paletki.</li><br />
'''<li>ImageSprite''' ''(“duszek”)'' - znany ze Scratcha duszek. W naszej aplikacji będzie to paletka. '''Image Sprite''' jest podobny do komponentu '''Ball''', jednak duszek ma kształt prostokąta, a jego tłem może być dowolny plik graficzny, np. w formacie jpg.</li><br />
</ol><br />
<br />
[[Plik:s2-3.png]]<br />
<br />
Jako pierwszy komponent dodajmy '''Canvas''' (1).Przeciągnijmy go na nasz obszar roboczy, czyli '''Viewer'''.<br />
<br />
[[Plik:s2-4.png]]<br />
<br />
Po tym, jak wstawiliśmy komponent '''Canvas''', musimy zmienić jego cechy w oknie '''Properties'''. Zmodyfikujmy dwa atrybuty: '''Width''' ''(szerokość)'' oraz '''Height''' ''(wysokość)''. Dla większości komponentów zarówno szerokość, jak i wysokość można ustawić jako:<br />
<ol>'''<li>Automatic''' ''(automatyczna)'' - system samodzielnie dobierze odpowiednią wartość szerokości i wysokości lub pozostawi je<br />
w standardowym ustawieniu.</li><br />
'''<li>Fill parent''' ''(wypełnienie obiektu nadrzędnego)'' - sprawia, że komponent przejmuje wielkość komponentu nadrzędnego. W przypadku naszej aplikacji zaznaczenie tej opcji sprawiłoby, że obszar '''Canvas1''' przejąłby szerokość i wysokość od komponentu '''Screen1''', co możemy zauważyć na ilustracji powyżej, w oknie '''Components''' - '''Cavas1''' jest obiektem podrzędnym dla '''Screen1'''.</li><br />
<li>'''... pixels - szerokość/wysokość o podanej przez nas liczbie pikseli.</li></ol><br />
Ustawmy zatem dla komponentu '''Canvas1''' wartości '''Width''' jako '''Fill Parent''' (1) oraz '''Height''' jako 300 pikseli(2).<br />
<br />
Teraz czas na kolejne komponenty. Dodajmy '''Ball''' (1) oraz '''ImageSprite''' (2) w dowolne miejsca w obrębie komponentu '''Canvas1'''. Tak jak wspomnieliśmy wcześniej, komponenty '''Ball''' oraz '''ImageSprite''' mogą być umieszczone jedynie na komponencie '''Canvas'''. Nie można umieścić ich poza tym obszarem, bezpośrednio na ekranie telefonu.<br />
<br />
[[Plik:s2-5.png]]<br />
<br />
Po dodaniu dwóch następnych komponentów dostosujmy ich właściwości tak, by odpowiadały naszym założeniom. Zacznijmy od komponentu '''Ball''' - na początek zmieńmy nazwę tego obiektu, klikając '''Rename''' (1) i wpisując '''Piłka''' w polu '''New Name'''. Następnie zmieńmy kilka cech tego komponentu w oknie właściwości, czyli '''Properties''':<br />
<ul><li>'''Heading''' (''kierunek'')- wpiszmy wartość 50 (2)</li><br />
<li>'''Paint Color''' (''kolor'')- wybierzmy '''Blue''' (3)</li><br />
<li>'''Radius''' (''promień'')- promień, czyli po prostu wielkość piłki ustalmy na 5 (4)</li><br />
<li>'''Speed''' (''prędkość'') - tutaj wpiszmy wartość 100 (5)</li><br />
<li>'''Współrzędne X i Y''' - obu współrzędnym nadajmy wartość 100 (6)</li></ul><br />
Inaczej niż w Scratchu, w programie App Inventor komponenty Ball oraz ImageSprite mogą mieć nadaną własną prędkość. W Scratchu efekt ten osiągaliśmy poprzez wielokrotne przesuwanie obiektu. Tutaj wystarczy, że nadamy komponentowi kierunek (Heading) oraz prędkość (Speed), zaś resztę pracy wykona za nas komputer.<br />
<br />
[[Plik:info.png|left]]''Warto zwrócić uwagę na hierarchię komponentów w oknie '''Components'''. Jak pamiętamy, w poprzedniej aplikacji wszystkie komponenty były bezpośrednio podrzędne dla '''Screen1'''. Tutaj podrzędny dla '''Screen1''' jest tylko '''Canvas1''', natomiast pozostałe dwa komponenty ('''Piłka''' oraz '''ImageSprite''') są podrzędne dla komponentu '''Canvas1'''.''<br />
<br />
<br />
[[Plik:s2-6.png]]<br />
<br />
Zmieńmy jeszcze nazwy pozostałych komponentów. '''Canvas1''' przestawmy na '''Boisko''' (1), zaś '''ImageSprite1''' na '''Paletka''' (2).<br />
<br />
[[Plik:s2-7.png]]<br />
<br />
Teraz przejdziemy do następnego kroku, czyli do skonfigurowania paletki.<br />
<br />
[[Plik:s2-8.png]]<br />
<br />
Przejdźmy zatem do zmiany właściwości komponentu o nazwie Paletka. Na początek kliknijmy na paletkę w oknie Components, by ją zaznaczyć - dzięki temu w oknie Properties pojawią się opcje, które pozwolą nam skonfigurować naszą paletkę. Konfigurację jej cech podzielimy na dwa kroki. W pierwszym kroku zadbamy o jej wygląd, zaś w drugim zajmiemy się jej rozmiarem i pozycją.<br />
<ol><li>'''Ustawienie pliku graficznego''' - wygląd paletki będzie wczytany z pliku graficznego, który załadujemy do programu. Paletka bez załadowanej grafiki byłaby przezroczysta, a to zdecydowanie utrudniłoby nam grę. Musimy zatem przygotować dowolny plik graficzny, np. w formacie png i wczytać go do mediów aplikacji, by następnie przypisać do paletki. Kliknijmy więc na '''Upload File''' (1) w oknie '''Media''' i odszukajmy plik, który chcemy wczytać do programu. Następnie przechodzimy do okna '''Properties''' i tam w polu '''Picture''' z rozwijanej listy wybierzmy nasz plik. Plików multimedialnych nie możemy przypisać bezpośrednio do komponentów, stąd w pierwszej kolejności musieliśmy wczytać plik do biblioteki mediów.</li><br />
<li>'''Wielkość i pozycja''' - po tym, jak wczytaliśmy już plik graficzny, przejdźmy do ustawienia pozostałych parametrów. Współrzędną X ustawmy na 100 pikseli, zaś Y - na 270 (3). Następnie parametry '''Width''' (szerokość) na 70 pikseli, a '''Height''' (wysokość) na 20 pikseli.</li></ol><br />
'''<li>Squash - programowanie aplikacji</li>'''<br />
Po tym, jak zakończyliśmy projektowanie interfejsu aplikacji, możemy zająć się stworzeniem odpowiedniego programu. Tym razem zbudowanie poprawnego kodu będzie wymagało od nas większej pracy niż w przypadku poprzedniej aplikacji. Tam wystarczyła nam tylko jedna instrukcja zbudowana z bloków, natomiast tutaj potrzebujemy ich kilka. Przejdźmy więc teraz do zakładki '''Blocks''', a poniżej, krok po kroku, omówimy wszystkie instrukcje.<br />
<br />
'''Zderzenie piłki z paletką i odbicie piłki'''<br />
<br />
Podstawową interakcją w naszej grze jest zderzenie piłeczki z paletką. Gdy do tego dojdzie, piłka musi odbić się od paletki. Musimy zatem ustalić, w jaki sposób ma zachować się piłka i określić, w stosunku do jakiego obiektu to zachowanie ma wystąpić. <br />
<br />
Naszą instrukcję można opisać w następujący sposób: '''Kiedy piłka zderzy się z innym obiektem, to odbij piłkę tak, jakby dotknęła dolnej krawędzi.'''<br />
<br />
[[Plik:s2-9.png]]<br />
<br />
Jak to działa? Przede wszystkim pamiętajmy, że piłka ma swoją prędkość. Gdy poruszająca się '''Piłka''' uderza w krawędź '''Canvas''' (nasze '''Boisko'''), to wywołuje wydarzenie '''EdgeReached''' (''zetknięcie z krawędzią''), a gdy uderza w inny obiekt, to wywołuje wydarzenie '''CollidedWith''' (''zderzenie z...''). My na ekranie mamy tylko jeden obiekt inny niż piłka, czyli paletkę. Zatem gdy piłka uderzy w paletkę, to zostanie uruchomiona akcja '''call[Piłka].Bounce''' (“''odbij piłkę''”). Akcja odbicia musi jeszcze wiedzieć, w którą stronę ma piłkę odbić, gdy ta uderzy w krawędź boczną lub górną i właśnie do tego służy parametr '''edge''' (''krawędź''). Jego wartość ustawiona na -1 powoduje odbicie '''Piłki''' tak, jakby dotknęła dolnej krawędzi (oznaczenia wszystkich krawędzi znajdują<br />
się dalej).<br />
<br />
'''Other''' (''inny obiekt''), można wykorzystać do ustalenia, w który obiekt uderzyła '''Piłka'''. My na ekranie mamy tylko paletkę, więc nie musimy sprawdzać wartości '''other'''.<br />
<br />
Polecenia '''When[Piłka].CollidedWith''' oraz '''Call[Piłka].Bounce''' znajdziemy w grupie '''Piłka''' (1), zaś obiekt z wartością liczbową - w grupie '''Math''' (2).<br />
<br />
[[Plik:s2-10.png]]<br />
<br />
[[Plik:info.png]]''Wszystkie instrukcje, tak jak w Scratchu, podzielone są na kategorie oznaczone odpowiednimi kolorami, co ułatwia nawigację.''<br />
<br />
<br />
'''Numeracja krawędzi ekranu w App Inventorze.'''<br />
<br />
Przed momentem skonfigurowaliśmy uderzenie piłki w dolną krawędź ekranu, która jest oznaczona numerem -1. Skąd wziął się właśnie taki numer? Krawędzie w programie App Inventor mają takie oznaczenia, jakie zaprezentowano na poniższej ilustracji. Krawędź północna oznaczona jest numerem 1, północno-wschodnia numerem 2 i w ten sposób docieramy do krawędzi dolnej, która jest oznaczona numerem -1.<br />
<br />
[[Plik:s2-11.png]]<br />
<br />
'''Zderzenie piłki z krawędzią i odbicie piłki od krawędzi.'''<br />
<br />
Teraz zaprogramujemy wydarzenie zderzenia piłki z krawędzią. Tutaj musimy rozróżnić dwa rodzaje krawędzi - krawędź boczną i krawędź dolną. Jeśli piłka zderzy się z krawędzią boczną, to zostanie odbita, a wartość jej prędkości zwiększy się o 1. Natomiast jeśli zderzy się krawędzią dolną, to nastąpi ponowne rozpoczęcie gry poprzez wywołanie odrębnej procedury, którą przygotujemy.<br />
<br />
[[Plik:squash-9.png|600px]]<br />
<br />
Najpierw sprawdzamy, czy piłka uderzyła w krawędź dolną (wartość edge wynoszącą -1). Krawędź -1 oznacza, że gracz przepuścił piłkę (nie odbił jej) i powoduje to rozpoczęcie gry od początku – poprzez wywołanie procedury reset Call[reset], którą przygotujemy za chwilę.<br />
<br />
Jeśli piłka uderzy w krawędź boczną, to zostaną wykonane dwie akcje:<br />
<br />
1. Odbij Piłkę tak, jakby się zderzyła z odpowiednią krawędzią (identyfikator krawędzi uzyskujemy przy pomocy '''get[edge]''')<br />
<br />
2. Zwiększ prędkość piłki o jeden więcej '''(Set[Piłka].Speed to [Piłka].[Speed] + 1)'''.<br />
<br />
Na zakończenie dołóżmy jeszcze akcję '''set[Screen1].[Title]''' na „Squash - ”&[Piłka]. [Speed], czyli ustaw pasek tytułu na napis Squash oraz prędkość poruszania się Piłki.<br />
<br />
'''Wariant pierwszy - poruszanie paletką za pomocą ruchu palca.'''<br />
<br />
Kolejnym krokiem będzie zaprogramowanie mechanizmu poruszania paletki poprzez przeciągnięcie palcem. Tutaj wykorzystamy funkcję <b>when[Paletka].Dragged.</b><br />
<br />
[[Plik:squash-10.png|600px]]<br />
<br />
'''when[Paletka].Dragged''' ''(kiedy Paletka przeciągnięta)'', to ustaw współrzędną X Paletki na wartość '''currentX''' (czyli aktualna współrzędna X - miejsce, gdzie dotkniemy/przeciągniemy palcem ekranu) zmniejszona o połowę szerokości Paletki '''([Paletka].[Width] / 2)'''. Musimy więc wewnątrz działania matematycznego odejmowanie zawrzeć kolejne działanie - dzielenie.<br />
<br />
Dlaczego zmniejszyliśmy szerokość o połowę? Polecenie '''set[Paletka].[X]''' ustawia lewy górny róg Paletki w miejscu X. Z tego powodu musimy odjąć połowę jej szerokości, żeby palec wskazywał środek paletki, a nie jej lewą krawędź.<br />
<br />
'''Przygotowanie procedury reset'''<br />
<br />
Teraz przygotujmy procedurę własną reset. Będzie ona uruchamiana zawsze, gdy piłka dotknie dolnej krawędzi oraz zawsze na początku gry. Będą w niej zawarte wszystkie domyślne dla naszej gry parametry, takie jak kolor tła, czy wymiary boiska. Dzięki temu nasza gra po porażce i przy każdym wznowieniu oraz na początku zawsze będzie wyglądała i działała tak samo. W obszarze '''Blocks''' w grupie '''Procedures''' znajdźmy '''to[procedure] do''' i przeciągnijmy ten element do obszaru ''Viewer''. Następnie zmieńmy jego nazwę na ''reset'' i wstawmy poszczególne klocki, jak na poniższej ilustracji.<br />
<br />
[[Plik:squash-11.png|600px]]<br />
<br />
1. Na początek ustawmy kolor tła naszego Boiska – jeżeli kolor jest szary (czyli jeśli przegraliśmy), to ustawiamy na biały. Dodajmy jeszcze warunek, że jeżeli boisko ma jakikolwiek inny kolor niż szary, to ustawiamy na biały - o tym za chwilę.<br />
<br />
2. Następnie ustawmy parametry początkowe Piłki – współrzędne X i Y, kierunek ('''Heading''') oraz prędkość piłki ('''Speed'''). Dzięki temu na początku gry piłka zawsze będzie w tej samej pozycji.<br />
<br />
3. Na samym dole, wzdłuż dolnej krawędzi Boiska (linia x1) rysujemy linię (w kolorze i szerokości ustawionej w procedurze '''when[Screen1].Initialize''', którą stworzymy za chwilę). Linia ta musi być za każdym razem rysowana ponownie, ponieważ ustawienie tła Boiska (na szare lub białe) powyżej powoduje jej usunięcie (wyczyszczenie całości Boiska).<br />
<br />
Przypomnijmy jeszcze raz, że procedura reset będzie uruchamiana za każdym razem, gdy Piłka dotknie dolnej krawędzi Boiska (czerwonej linii) oraz podczas uruchomienia aplikacji.<br />
<br />
'''Instrukcja when[Screen1].Initialize'''<br />
<br />
Została nam już ostatnia instrukcja, która będzie uruchamiana w momencie inicjowania komponentu Screen1, czyli w naszym przypadku po prostu przy każdym starcie aplikacji. W tej instrukcji zdefiniujemy parametry początkowe naszej aplikacji. <br />
<br />
[[Plik:squash-12.png|600px]]<br />
<br />
1. Szerokość Paletki ustawmy na ¼ szerokości Boiska.<br />
<br />
2. Ustalmy parametry rysowania Boiska (kolor czerwony, szerokość/grubość rysowania 9) – to wykorzystamy do rysowania czerwonej linii na dole Boiska.<br />
<br />
3. Na sam koniec uruchamiamy jeszcze procedurę reset. I tutaj znajdziemy odpowiedź, dlaczego w procedurze reset sprawdzane są również inne kolory boiska niż tylko szary. Program rozpoczyna od procedury '''when[Screen1].Initialize''' i ustawia obrys koloru boiska na czerwony o grubości linii 9. Procedura '''reset''' z kolei sprawdza, jaki jest kolor boiska i jeżeli jest szary lub inny niż szary, zmienia kolor na biały, rysując dodatkowo trzy linie - górną oraz boczne. W ten sposób dolna linia w czerwonym kolorze pozostaje na boisku, również po wykonaniu procedury reset. Musieliśmy rozwiązać to w taki sposób, ponieważ porażkę sygnalizujemy zmianą koloru tła, natomiast zamiana koloru tła spowodowałaby usunięcie tej linii.<br />
<br />
'''<li>Udostępnianie aplikacji</li>'''<br />
<br />
Nasza aplikacja działa teraz prawidłowo, zaś paletka przemieszcza się, kiedy przesuwamy palcem po ekranie. Korzystając z faktu, że mamy ciekawą, działającą aplikację, poświęćmy teraz chwilę na udostępnienie tej aplikacji dalej po to, by można było zainstalować ją na dowolnym smartfonie. W tym celu kliknijmy w menu Build (1), gdzie znajdziemy dwie funkcje (2):<br />
<br />
1.App (Provide QP code for .apk) - wybranie tej opcji spowoduje wyświetlenie kodu QR i da możliwość załadowania przy pomocy tego kodu samodzielnej aplikacji na telefonie, bez użycia MIT AI2 Companion.<br />
<br />
2.App (save .apk to my computer) - wybranie tego polecenia spowoduje zapisanie aplikacji na komputerze jako plik .apk. Dzięki temu możemy chociażby przesłać aplikację jako załącznik w e-mailu.<br />
<br />
[[Plik:squash-12a.png|600px]]<br />
<br />
'''<li>Suqash, wariant drugi - sterowanie paletką poprzez wychylenia telefonu</li>'''<br />
<br />
Teraz przejdźmy do zaprogramowania drugiego wariantu, czyli sterowania paletką poprzez obracanie smartfonem czy tabletem. Chcemy oczywiście zachować pierwszy wariant gry, dlatego stworzymy teraz nowy zapis projektu i to na nim wprowadzimy odpowiednie zmiany.<br />
Wybierzmy zatem '''Projects (1)''' w menu głównym, a następnie '''Save projects as... (2)''' i w polu ''<b>New name:</b>'' wpiszmy nową nazwę: '''Squash_przechylanie.'''<br />
Z grupy '''Sensors <i>(czujniki</i>)''' wybierzmy komponent o nazwie '''AccelerometerSensor (1)''' i przeciągnijmy go na obszar projektowania interfejsu. Jako że '''AccelerometerSensor''' jest obiektem niewidocznym, to nie zajmuje on miejsca na ekranie, ale możemy zobaczyć go poniżej ekranu, w sekcji '''Non-visible components (2).'''<br />
Komponent '''AccelerometerSensor''' będzie przez nas wykorzystany do odczytywania przechylenia telefonu.</div>M Kelniarzhttp://wiki.mistrzowiekodowania.pl/index.php?title=Scenariusz_2_-_SquashScenariusz 2 - Squash2015-09-30T12:57:25Z<p>M Kelniarz: /* Scenariusz 2 */</p>
<hr />
<div>=Squash w dwóch wariantach=<br />
==Scenariusz 2==<br />
'''Cele:'''<br />
<br />
Stworzymy prostą grę Squash, polegającą na odbijaniu piłeczki paletką, w dwóch wariantach. W ten sposób poznamy m.in. podstawy definiowania interfejsu użytkownika oraz nauczymy się wykonywać proste animacje. Po wykonaniu ćwiczenia będziemy też potrafili sterować obiektami za pomocą przeciągania palcem (pierwszy wariant) po ekranie oraz poprzez przechylanie telefonu (drugi wariant).<br />
<br />
W tej wersji Squasha nie będzie systemu naliczania punktów, jak w tradycyjnej wersji tej gry. W naszej aplikacji na dole będzie umieszczona czerwona linia i jeśli piłka się z nią zderzy, to nastąpi przegrana. Co więcej, gdy nie odbijemy piłeczki i ta spadnie na czerwoną linię, boisko zmieni kolor na szary, co będzie oznaczało koniec gry.<br />
<br />
<ol>'''<li>Rozpoczęcie pracy</li>'''<br />
Wejdźmy na stronę [http://appinventor.mit.edu http://appinventor.mit.edu] i wybierzmy '''Create''', by uruchomić App Inventor. Następnie przejdźmy do zakładki '''My Projects''' (1), gdzie znajdziemy wszystkie nasze projekty - wystarczy tylko zalogować się na odpowiednie konto Google. W celu rozpoczęcia pracy nad nowym projektem kliknijmy na '''Start new project''' (2) i wpiszmy w oknie jego nazwę, np. Squash.<br />
<br />
[[Plik:s2-1.png|800px]]<br />
<br />
Nastąpi teraz automatyczne przejście do okna budowy aplikacji.<br />
<br />
Jak już wspomnieliśmy powyżej - w pierwszym wariancie naszej gry sterowanie paletką będzie odbywało się poprzez przeciąganie palcem po ekranie smartfona, natomiast w drugiej wersji będziemy sterować obracając nim. Obracanie ekranu zgodnie z pozycją telefonu czy tabletu jest domyślnym zachowaniem. Dlatego też w pierwszym wariancie musimy zablokować ekran po to, by ten nie zmieniał swojej orientacji. I od tego właśnie zaczniemy budowę naszej gry.<br />
<br />
Przejdźmy zatem do okna '''Properties''' i dla komponentu '''Screen1,''' w polu '''Screen Orientation''' (1) wybierzmy '''Portrait'''. Dzięki temu nasz ekran zawsze będzie wyświetlany pionowo, niezależnie od tego, w jakiej pozycji znajduje się urządzenie. Dodatkowo w polu '''Title''' wpiszmy tytuł naszego bieżącego komponentu (2). Nazwijmy go '''Squash'''.<br />
<br />
[[Plik:s2-2.png]]<br />
<br />
'''<li>Squash - projektowanie interfejsu</li>'''<br />
Po zablokowaniu obrotu ekranu przejdźmy do dodania komponentów. W naszej aplikacji wykorzystamy trzy elementy - wszystkie znajdziemy w grupie Drawing and Animation. Są to:<br />
<ol>'''<li>Canvas''' ''(zamknięty obszar)'' - jest to komponent ograniczający obszar animacji oraz rysowania. W obszarze tego komponentu poruszają się Ball oraz ImageSprite.</li><br />
'''<li>Ball''' ''(piłka)'' - w naszej aplikacji to po prostu piłka, którą będziemy odbijać za pomocą paletki.</li><br />
'''<li>ImageSprite''' ''(“duszek”)'' - znany ze Scratcha duszek. W naszej aplikacji będzie to paletka. '''Image Sprite''' jest podobny do komponentu '''Ball''', jednak duszek ma kształt prostokąta, a jego tłem może być dowolny plik graficzny, np. w formacie jpg.</li><br />
</ol><br />
<br />
[[Plik:s2-3.png]]<br />
<br />
Jako pierwszy komponent dodajmy '''Canvas''' (1).Przeciągnijmy go na nasz obszar roboczy, czyli '''Viewer'''.<br />
<br />
[[Plik:s2-4.png]]<br />
<br />
Po tym, jak wstawiliśmy komponent '''Canvas''', musimy zmienić jego cechy w oknie '''Properties'''. Zmodyfikujmy dwa atrybuty: '''Width''' ''(szerokość)'' oraz '''Height''' ''(wysokość)''. Dla większości komponentów zarówno szerokość, jak i wysokość można ustawić jako:<br />
<ol>'''<li>Automatic''' ''(automatyczna)'' - system samodzielnie dobierze odpowiednią wartość szerokości i wysokości lub pozostawi je<br />
w standardowym ustawieniu.</li><br />
'''<li>Fill parent''' ''(wypełnienie obiektu nadrzędnego)'' - sprawia, że komponent przejmuje wielkość komponentu nadrzędnego. W przypadku naszej aplikacji zaznaczenie tej opcji sprawiłoby, że obszar '''Canvas1''' przejąłby szerokość i wysokość od komponentu '''Screen1''', co możemy zauważyć na ilustracji powyżej, w oknie '''Components''' - '''Cavas1''' jest obiektem podrzędnym dla '''Screen1'''.</li><br />
<li>'''... pixels - szerokość/wysokość o podanej przez nas liczbie pikseli.</li></ol><br />
Ustawmy zatem dla komponentu '''Canvas1''' wartości '''Width''' jako '''Fill Parent''' (1) oraz '''Height''' jako 300 pikseli(2).<br />
<br />
Teraz czas na kolejne komponenty. Dodajmy '''Ball''' (1) oraz '''ImageSprite''' (2) w dowolne miejsca w obrębie komponentu '''Canvas1'''. Tak jak wspomnieliśmy wcześniej, komponenty '''Ball''' oraz '''ImageSprite''' mogą być umieszczone jedynie na komponencie '''Canvas'''. Nie można umieścić ich poza tym obszarem, bezpośrednio na ekranie telefonu.<br />
<br />
[[Plik:s2-5.png]]<br />
<br />
Po dodaniu dwóch następnych komponentów dostosujmy ich właściwości tak, by odpowiadały naszym założeniom. Zacznijmy od komponentu '''Ball''' - na początek zmieńmy nazwę tego obiektu, klikając '''Rename''' (1) i wpisując '''Piłka''' w polu '''New Name'''. Następnie zmieńmy kilka cech tego komponentu w oknie właściwości, czyli '''Properties''':<br />
<ul><li>'''Heading''' (''kierunek'')- wpiszmy wartość 50 (2)</li><br />
<li>'''Paint Color''' (''kolor'')- wybierzmy '''Blue''' (3)</li><br />
<li>'''Radius''' (''promień'')- promień, czyli po prostu wielkość piłki ustalmy na 5 (4)</li><br />
<li>'''Speed''' (''prędkość'') - tutaj wpiszmy wartość 100 (5)</li><br />
<li>'''Współrzędne X i Y''' - obu współrzędnym nadajmy wartość 100 (6)</li></ul><br />
Inaczej niż w Scratchu, w programie App Inventor komponenty Ball oraz ImageSprite mogą mieć nadaną własną prędkość. W Scratchu efekt ten osiągaliśmy poprzez wielokrotne przesuwanie obiektu. Tutaj wystarczy, że nadamy komponentowi kierunek (Heading) oraz prędkość (Speed), zaś resztę pracy wykona za nas komputer.<br />
<br />
[[Plik:info.png|left]]''Warto zwrócić uwagę na hierarchię komponentów w oknie '''Components'''. Jak pamiętamy, w poprzedniej aplikacji wszystkie komponenty były bezpośrednio podrzędne dla '''Screen1'''. Tutaj podrzędny dla '''Screen1''' jest tylko '''Canvas1''', natomiast pozostałe dwa komponenty ('''Piłka''' oraz '''ImageSprite''') są podrzędne dla komponentu '''Canvas1'''.''<br />
<br />
<br />
[[Plik:s2-6.png]]<br />
<br />
Zmieńmy jeszcze nazwy pozostałych komponentów. '''Canvas1''' przestawmy na '''Boisko''' (1), zaś '''ImageSprite1''' na '''Paletka''' (2).<br />
<br />
[[Plik:s2-7.png]]<br />
<br />
Teraz przejdziemy do następnego kroku, czyli do skonfigurowania paletki.<br />
<br />
[[Plik:s2-8.png]]<br />
<br />
Przejdźmy zatem do zmiany właściwości komponentu o nazwie Paletka. Na początek kliknijmy na paletkę w oknie Components, by ją zaznaczyć - dzięki temu w oknie Properties pojawią się opcje, które pozwolą nam skonfigurować naszą paletkę. Konfigurację jej cech podzielimy na dwa kroki. W pierwszym kroku zadbamy o jej wygląd, zaś w drugim zajmiemy się jej rozmiarem i pozycją.<br />
<ol><li>'''Ustawienie pliku graficznego''' - wygląd paletki będzie wczytany z pliku graficznego, który załadujemy do programu. Paletka bez załadowanej grafiki byłaby przezroczysta, a to zdecydowanie utrudniłoby nam grę. Musimy zatem przygotować dowolny plik graficzny, np. w formacie png i wczytać go do mediów aplikacji, by następnie przypisać do paletki. Kliknijmy więc na '''Upload File''' (1) w oknie '''Media''' i odszukajmy plik, który chcemy wczytać do programu. Następnie przechodzimy do okna '''Properties''' i tam w polu '''Picture''' z rozwijanej listy wybierzmy nasz plik. Plików multimedialnych nie możemy przypisać bezpośrednio do komponentów, stąd w pierwszej kolejności musieliśmy wczytać plik do biblioteki mediów.</li><br />
<li>'''Wielkość i pozycja''' - po tym, jak wczytaliśmy już plik graficzny, przejdźmy do ustawienia pozostałych parametrów. Współrzędną X ustawmy na 100 pikseli, zaś Y - na 270 (3). Następnie parametry '''Width''' (szerokość) na 70 pikseli, a '''Height''' (wysokość) na 20 pikseli.</li></ol><br />
'''<li>Squash - programowanie aplikacji</li>'''<br />
Po tym, jak zakończyliśmy projektowanie interfejsu aplikacji, możemy zająć się stworzeniem odpowiedniego programu. Tym razem zbudowanie poprawnego kodu będzie wymagało od nas większej pracy niż w przypadku poprzedniej aplikacji. Tam wystarczyła nam tylko jedna instrukcja zbudowana z bloków, natomiast tutaj potrzebujemy ich kilka. Przejdźmy więc teraz do zakładki '''Blocks''', a poniżej, krok po kroku, omówimy wszystkie instrukcje.<br />
<br />
'''Zderzenie piłki z paletką i odbicie piłki'''<br />
<br />
Podstawową interakcją w naszej grze jest zderzenie piłeczki z paletką. Gdy do tego dojdzie, piłka musi odbić się od paletki. Musimy zatem ustalić, w jaki sposób ma zachować się piłka i określić, w stosunku do jakiego obiektu to zachowanie ma wystąpić. <br />
<br />
Naszą instrukcję można opisać w następujący sposób: '''Kiedy piłka zderzy się z innym obiektem, to odbij piłkę tak, jakby dotknęła dolnej krawędzi.'''<br />
<br />
[[Plik:s2-9.png]]<br />
<br />
Jak to działa? Przede wszystkim pamiętajmy, że piłka ma swoją prędkość. Gdy poruszająca się '''Piłka''' uderza w krawędź '''Canvas''' (nasze '''Boisko'''), to wywołuje wydarzenie '''EdgeReached''' (''zetknięcie z krawędzią''), a gdy uderza w inny obiekt, to wywołuje wydarzenie '''CollidedWith''' (''zderzenie z...''). My na ekranie mamy tylko jeden obiekt inny niż piłka, czyli paletkę. Zatem gdy piłka uderzy w paletkę, to zostanie uruchomiona akcja '''call[Piłka].Bounce''' (“''odbij piłkę''”). Akcja odbicia musi jeszcze wiedzieć, w którą stronę ma piłkę odbić, gdy ta uderzy w krawędź boczną lub górną i właśnie do tego służy parametr '''edge''' (''krawędź''). Jego wartość ustawiona na -1 powoduje odbicie '''Piłki''' tak, jakby dotknęła dolnej krawędzi (oznaczenia wszystkich krawędzi znajdują<br />
się dalej).<br />
<br />
'''Other''' (''inny obiekt''), można wykorzystać do ustalenia, w który obiekt uderzyła '''Piłka'''. My na ekranie mamy tylko paletkę, więc nie musimy sprawdzać wartości '''other'''.<br />
<br />
Polecenia '''When[Piłka].CollidedWith''' oraz '''Call[Piłka].Bounce''' znajdziemy w grupie '''Piłka''' (1), zaś obiekt z wartością liczbową - w grupie '''Math''' (2).<br />
<br />
[[Plik:s2-10.png]]<br />
<br />
[[Plik:info.png]]''Wszystkie instrukcje, tak jak w Scratchu, podzielone są na kategorie oznaczone odpowiednimi kolorami, co ułatwia nawigację.''<br />
<br />
<br />
'''Numeracja krawędzi ekranu w App Inventorze.'''<br />
<br />
Przed momentem skonfigurowaliśmy uderzenie piłki w dolną krawędź ekranu, która jest oznaczona numerem -1. Skąd wziął się właśnie taki numer? Krawędzie w programie App Inventor mają takie oznaczenia, jakie zaprezentowano na poniższej ilustracji. Krawędź północna oznaczona jest numerem 1, północno-wschodnia numerem 2 i w ten sposób docieramy do krawędzi dolnej, która jest oznaczona numerem -1.<br />
<br />
[[Plik:s2-11.png]]<br />
<br />
'''Zderzenie piłki z krawędzią i odbicie piłki od krawędzi.'''<br />
<br />
Teraz zaprogramujemy wydarzenie zderzenia piłki z krawędzią. Tutaj musimy rozróżnić dwa rodzaje krawędzi - krawędź boczną i krawędź dolną. Jeśli piłka zderzy się z krawędzią boczną, to zostanie odbita, a wartość jej prędkości zwiększy się o 1. Natomiast jeśli zderzy się krawędzią dolną, to nastąpi ponowne rozpoczęcie gry poprzez wywołanie odrębnej procedury, którą przygotujemy.<br />
<br />
[[Plik:squash-9.png|800px]]<br />
<br />
Najpierw sprawdzamy, czy piłka uderzyła w krawędź dolną (wartość edge wynoszącą -1). Krawędź -1 oznacza, że gracz przepuścił piłkę (nie odbił jej) i powoduje to rozpoczęcie gry od początku – poprzez wywołanie procedury reset Call[reset], którą przygotujemy za chwilę.<br />
<br />
Jeśli piłka uderzy w krawędź boczną, to zostaną wykonane dwie akcje:<br />
1. Odbij Piłkę tak, jakby się zderzyła z odpowiednią krawędzią (identyfikator krawędzi uzyskujemy przy pomocy '''get[edge]''')<br />
2. Zwiększ prędkość piłki o jeden więcej '''(Set[Piłka].Speed to [Piłka].[Speed] + 1)'''.<br />
<br />
Na zakończenie dołóżmy jeszcze akcję '''set[Screen1].[Title]''' na „Squash - ”&[Piłka]. [Speed], czyli ustaw pasek tytułu na napis Squash oraz prędkość poruszania się Piłki.<br />
<br />
'''Wariant pierwszy - poruszanie paletką za pomocą ruchu palca.'''<br />
<br />
Kolejnym krokiem będzie zaprogramowanie mechanizmu poruszania paletki poprzez przeciągnięcie palcem. Tutaj wykorzystamy funkcję <b>when[Paletka].Dragged.</b><br />
<br />
'''Przygotowanie procedury reset'''<br />
<br />
Teraz przygotujmy procedurę własną reset. Będzie ona uruchamiana zawsze, gdy piłka dotknie dolnej krawędzi oraz zawsze na początku gry. Będą w niej zawarte wszystkie domyślne dla naszej gry parametry, takie jak kolor tła, czy wymiary boiska. Dzięki temu nasza gra po porażce i przy każdym wznowieniu oraz na początku zawsze będzie wyglądała i działała tak samo. W obszarze '''Blocks''' w grupie '''Procedures''' znajdźmy '''to[procedure] do''' i przeciągnijmy ten element do obszaru ''Viewer''. Następnie zmieńmy jego nazwę na ''reset'' i wstawmy poszczególne klocki, jak na poniższej ilustracji.<br />
<br />
[[Plik:Przykład.jpg]]Tu grafika!!!<br />
<br />
1. Na początek ustawmy kolor tła naszego Boiska – jeżeli kolor jest szary (czyli jeśli przegraliśmy), to ustawiamy na biały. Dodajmy jeszcze warunek, że jeżeli boisko ma jakikolwiek inny kolor niż szary, to ustawiamy na biały - o tym za chwilę.<br />
<br />
2. Następnie ustawmy parametry początkowe Piłki – współrzędne X i Y, kierunek ('''Heading''') oraz prędkość piłki ('''Speed'''). Dzięki temu na początku gry piłka zawsze będzie w tej samej pozycji.<br />
<br />
3. Na samym dole, wzdłuż dolnej krawędzi Boiska (linia x1) rysujemy linię (w kolorze i szerokości ustawionej w procedurze '''when[Screen1].Initialize''', którą stworzymy za chwilę). Linia ta musi być za każdym razem rysowana ponownie, ponieważ ustawienie tła Boiska (na szare lub białe) powyżej powoduje jej usunięcie (wyczyszczenie całości Boiska).<br />
<br />
Przypomnijmy jeszcze raz, że procedura reset będzie uruchamiana za każdym razem, gdy Piłka dotknie dolnej krawędzi Boiska (czerwonej linii) oraz podczas uruchomienia aplikacji.<br />
<br />
'''Instrukcja when[Screen1].Initialize'''<br />
<br />
Została nam już ostatnia instrukcja, która będzie uruchamiana w momencie inicjowania komponentu Screen1, czyli w naszym przypadku po prostu przy każdym starcie aplikacji. W tej instrukcji zdefiniujemy parametry początkowe naszej aplikacji. <br />
<br />
[[Plik:Przykład.jpg]]Tu grafika!!!<br />
<br />
1. Szerokość Paletki ustawmy na ¼ szerokości Boiska.<br />
<br />
2. Ustalmy parametry rysowania Boiska (kolor czerwony, szerokość/grubość rysowania 9) – to wykorzystamy do rysowania czerwonej linii na dole Boiska.<br />
<br />
3. Na sam koniec uruchamiamy jeszcze procedurę reset. I tutaj znajdziemy odpowiedź, dlaczego w procedurze reset sprawdzane są również inne kolory boiska niż tylko szary. Program rozpoczyna od procedury '''when[Screen1].Initialize''' i ustawia obrys koloru boiska na czerwony o grubości linii 9. Procedura '''reset''' z kolei sprawdza, jaki jest kolor boiska i jeżeli jest szary lub inny niż szary, zmienia kolor na biały, rysując dodatkowo trzy linie - górną oraz boczne. W ten sposób dolna linia w czerwonym kolorze pozostaje na boisku, również po wykonaniu procedury reset. Musieliśmy rozwiązać to w taki sposób, ponieważ porażkę sygnalizujemy zmianą koloru tła, natomiast zamiana koloru tła spowodowałaby usunięcie tej linii.<br />
<br />
'''<li>Udostępnianie aplikacji</li>'''<br />
<br />
Nasza aplikacja działa teraz prawidłowo, zaś paletka przemieszcza się, kiedy przesuwamy palcem po ekranie. Korzystając z faktu, że mamy ciekawą, działającą aplikację, poświęćmy teraz chwilę na udostępnienie tej aplikacji dalej po to, by można było zainstalować ją na dowolnym smartfonie. W tym celu kliknijmy w menu Build (1), gdzie znajdziemy dwie funkcje (2):<br />
<br />
1.App (Provide QP code for .apk) - wybranie tej opcji spowoduje wyświetlenie kodu QR i da możliwość załadowania przy pomocy tego kodu samodzielnej aplikacji na telefonie, bez użycia MIT AI2 Companion.<br />
<br />
2.App (save .apk to my computer) - wybranie tego polecenia spowoduje zapisanie aplikacji na komputerze jako plik .apk. Dzięki temu możemy chociażby przesłać aplikację jako załącznik w e-mailu.<br />
<br />
[[Plik:info.png]]Tu grafika!!!<br />
<br />
'''<li>Suqash, wariant drugi - sterowanie paletką poprzez wychylenia telefonu</li>'''<br />
<br />
Teraz przejdźmy do zaprogramowania drugiego wariantu, czyli sterowania paletką poprzez obracanie smartfonem czy tabletem. Chcemy oczywiście zachować pierwszy wariant gry, dlatego stworzymy teraz nowy zapis projektu i to na nim wprowadzimy odpowiednie zmiany.<br />
Wybierzmy zatem '''Projects (1)''' w menu głównym, a następnie '''Save projects as... (2)''' i w polu ''<b>New name:</b>'' wpiszmy nową nazwę: '''Squash_przechylanie.'''<br />
Z grupy '''Sensors <i>(czujniki</i>)''' wybierzmy komponent o nazwie '''AccelerometerSensor (1)''' i przeciągnijmy go na obszar projektowania interfejsu. Jako że '''AccelerometerSensor''' jest obiektem niewidocznym, to nie zajmuje on miejsca na ekranie, ale możemy zobaczyć go poniżej ekranu, w sekcji '''Non-visible components (2).'''<br />
Komponent '''AccelerometerSensor''' będzie przez nas wykorzystany do odczytywania przechylenia telefonu.</div>M Kelniarzhttp://wiki.mistrzowiekodowania.pl/index.php?title=Scenariusz_2_-_SquashScenariusz 2 - Squash2015-09-30T12:53:53Z<p>M Kelniarz: /* Scenariusz 2 */</p>
<hr />
<div>=Squash w dwóch wariantach=<br />
==Scenariusz 2==<br />
'''Cele:'''<br />
<br />
Stworzymy prostą grę Squash, polegającą na odbijaniu piłeczki paletką, w dwóch wariantach. W ten sposób poznamy m.in. podstawy definiowania interfejsu użytkownika oraz nauczymy się wykonywać proste animacje. Po wykonaniu ćwiczenia będziemy też potrafili sterować obiektami za pomocą przeciągania palcem (pierwszy wariant) po ekranie oraz poprzez przechylanie telefonu (drugi wariant).<br />
<br />
W tej wersji Squasha nie będzie systemu naliczania punktów, jak w tradycyjnej wersji tej gry. W naszej aplikacji na dole będzie umieszczona czerwona linia i jeśli piłka się z nią zderzy, to nastąpi przegrana. Co więcej, gdy nie odbijemy piłeczki i ta spadnie na czerwoną linię, boisko zmieni kolor na szary, co będzie oznaczało koniec gry.<br />
<br />
<ol>'''<li>Rozpoczęcie pracy</li>'''<br />
Wejdźmy na stronę [http://appinventor.mit.edu http://appinventor.mit.edu] i wybierzmy '''Create''', by uruchomić App Inventor. Następnie przejdźmy do zakładki '''My Projects''' (1), gdzie znajdziemy wszystkie nasze projekty - wystarczy tylko zalogować się na odpowiednie konto Google. W celu rozpoczęcia pracy nad nowym projektem kliknijmy na '''Start new project''' (2) i wpiszmy w oknie jego nazwę, np. Squash.<br />
<br />
[[Plik:s2-1.png|800px]]<br />
<br />
Nastąpi teraz automatyczne przejście do okna budowy aplikacji.<br />
<br />
Jak już wspomnieliśmy powyżej - w pierwszym wariancie naszej gry sterowanie paletką będzie odbywało się poprzez przeciąganie palcem po ekranie smartfona, natomiast w drugiej wersji będziemy sterować obracając nim. Obracanie ekranu zgodnie z pozycją telefonu czy tabletu jest domyślnym zachowaniem. Dlatego też w pierwszym wariancie musimy zablokować ekran po to, by ten nie zmieniał swojej orientacji. I od tego właśnie zaczniemy budowę naszej gry.<br />
<br />
Przejdźmy zatem do okna '''Properties''' i dla komponentu '''Screen1,''' w polu '''Screen Orientation''' (1) wybierzmy '''Portrait'''. Dzięki temu nasz ekran zawsze będzie wyświetlany pionowo, niezależnie od tego, w jakiej pozycji znajduje się urządzenie. Dodatkowo w polu '''Title''' wpiszmy tytuł naszego bieżącego komponentu (2). Nazwijmy go '''Squash'''.<br />
<br />
[[Plik:s2-2.png]]<br />
<br />
'''<li>Squash - projektowanie interfejsu</li>'''<br />
Po zablokowaniu obrotu ekranu przejdźmy do dodania komponentów. W naszej aplikacji wykorzystamy trzy elementy - wszystkie znajdziemy w grupie Drawing and Animation. Są to:<br />
<ol>'''<li>Canvas''' ''(zamknięty obszar)'' - jest to komponent ograniczający obszar animacji oraz rysowania. W obszarze tego komponentu poruszają się Ball oraz ImageSprite.</li><br />
'''<li>Ball''' ''(piłka)'' - w naszej aplikacji to po prostu piłka, którą będziemy odbijać za pomocą paletki.</li><br />
'''<li>ImageSprite''' ''(“duszek”)'' - znany ze Scratcha duszek. W naszej aplikacji będzie to paletka. '''Image Sprite''' jest podobny do komponentu '''Ball''', jednak duszek ma kształt prostokąta, a jego tłem może być dowolny plik graficzny, np. w formacie jpg.</li><br />
</ol><br />
<br />
[[Plik:s2-3.png]]<br />
<br />
Jako pierwszy komponent dodajmy '''Canvas''' (1).Przeciągnijmy go na nasz obszar roboczy, czyli '''Viewer'''.<br />
<br />
[[Plik:s2-4.png]]<br />
<br />
Po tym, jak wstawiliśmy komponent '''Canvas''', musimy zmienić jego cechy w oknie '''Properties'''. Zmodyfikujmy dwa atrybuty: '''Width''' ''(szerokość)'' oraz '''Height''' ''(wysokość)''. Dla większości komponentów zarówno szerokość, jak i wysokość można ustawić jako:<br />
<ol>'''<li>Automatic''' ''(automatyczna)'' - system samodzielnie dobierze odpowiednią wartość szerokości i wysokości lub pozostawi je<br />
w standardowym ustawieniu.</li><br />
'''<li>Fill parent''' ''(wypełnienie obiektu nadrzędnego)'' - sprawia, że komponent przejmuje wielkość komponentu nadrzędnego. W przypadku naszej aplikacji zaznaczenie tej opcji sprawiłoby, że obszar '''Canvas1''' przejąłby szerokość i wysokość od komponentu '''Screen1''', co możemy zauważyć na ilustracji powyżej, w oknie '''Components''' - '''Cavas1''' jest obiektem podrzędnym dla '''Screen1'''.</li><br />
<li>'''... pixels - szerokość/wysokość o podanej przez nas liczbie pikseli.</li></ol><br />
Ustawmy zatem dla komponentu '''Canvas1''' wartości '''Width''' jako '''Fill Parent''' (1) oraz '''Height''' jako 300 pikseli(2).<br />
<br />
Teraz czas na kolejne komponenty. Dodajmy '''Ball''' (1) oraz '''ImageSprite''' (2) w dowolne miejsca w obrębie komponentu '''Canvas1'''. Tak jak wspomnieliśmy wcześniej, komponenty '''Ball''' oraz '''ImageSprite''' mogą być umieszczone jedynie na komponencie '''Canvas'''. Nie można umieścić ich poza tym obszarem, bezpośrednio na ekranie telefonu.<br />
<br />
[[Plik:s2-5.png]]<br />
<br />
Po dodaniu dwóch następnych komponentów dostosujmy ich właściwości tak, by odpowiadały naszym założeniom. Zacznijmy od komponentu '''Ball''' - na początek zmieńmy nazwę tego obiektu, klikając '''Rename''' (1) i wpisując '''Piłka''' w polu '''New Name'''. Następnie zmieńmy kilka cech tego komponentu w oknie właściwości, czyli '''Properties''':<br />
<ul><li>'''Heading''' (''kierunek'')- wpiszmy wartość 50 (2)</li><br />
<li>'''Paint Color''' (''kolor'')- wybierzmy '''Blue''' (3)</li><br />
<li>'''Radius''' (''promień'')- promień, czyli po prostu wielkość piłki ustalmy na 5 (4)</li><br />
<li>'''Speed''' (''prędkość'') - tutaj wpiszmy wartość 100 (5)</li><br />
<li>'''Współrzędne X i Y''' - obu współrzędnym nadajmy wartość 100 (6)</li></ul><br />
Inaczej niż w Scratchu, w programie App Inventor komponenty Ball oraz ImageSprite mogą mieć nadaną własną prędkość. W Scratchu efekt ten osiągaliśmy poprzez wielokrotne przesuwanie obiektu. Tutaj wystarczy, że nadamy komponentowi kierunek (Heading) oraz prędkość (Speed), zaś resztę pracy wykona za nas komputer.<br />
<br />
[[Plik:info.png|left]]''Warto zwrócić uwagę na hierarchię komponentów w oknie '''Components'''. Jak pamiętamy, w poprzedniej aplikacji wszystkie komponenty były bezpośrednio podrzędne dla '''Screen1'''. Tutaj podrzędny dla '''Screen1''' jest tylko '''Canvas1''', natomiast pozostałe dwa komponenty ('''Piłka''' oraz '''ImageSprite''') są podrzędne dla komponentu '''Canvas1'''.''<br />
<br />
<br />
[[Plik:s2-6.png]]<br />
<br />
Zmieńmy jeszcze nazwy pozostałych komponentów. '''Canvas1''' przestawmy na '''Boisko''' (1), zaś '''ImageSprite1''' na '''Paletka''' (2).<br />
<br />
[[Plik:s2-7.png]]<br />
<br />
Teraz przejdziemy do następnego kroku, czyli do skonfigurowania paletki.<br />
<br />
[[Plik:s2-8.png]]<br />
<br />
Przejdźmy zatem do zmiany właściwości komponentu o nazwie Paletka. Na początek kliknijmy na paletkę w oknie Components, by ją zaznaczyć - dzięki temu w oknie Properties pojawią się opcje, które pozwolą nam skonfigurować naszą paletkę. Konfigurację jej cech podzielimy na dwa kroki. W pierwszym kroku zadbamy o jej wygląd, zaś w drugim zajmiemy się jej rozmiarem i pozycją.<br />
<ol><li>'''Ustawienie pliku graficznego''' - wygląd paletki będzie wczytany z pliku graficznego, który załadujemy do programu. Paletka bez załadowanej grafiki byłaby przezroczysta, a to zdecydowanie utrudniłoby nam grę. Musimy zatem przygotować dowolny plik graficzny, np. w formacie png i wczytać go do mediów aplikacji, by następnie przypisać do paletki. Kliknijmy więc na '''Upload File''' (1) w oknie '''Media''' i odszukajmy plik, który chcemy wczytać do programu. Następnie przechodzimy do okna '''Properties''' i tam w polu '''Picture''' z rozwijanej listy wybierzmy nasz plik. Plików multimedialnych nie możemy przypisać bezpośrednio do komponentów, stąd w pierwszej kolejności musieliśmy wczytać plik do biblioteki mediów.</li><br />
<li>'''Wielkość i pozycja''' - po tym, jak wczytaliśmy już plik graficzny, przejdźmy do ustawienia pozostałych parametrów. Współrzędną X ustawmy na 100 pikseli, zaś Y - na 270 (3). Następnie parametry '''Width''' (szerokość) na 70 pikseli, a '''Height''' (wysokość) na 20 pikseli.</li></ol><br />
'''<li>Squash - programowanie aplikacji</li>'''<br />
Po tym, jak zakończyliśmy projektowanie interfejsu aplikacji, możemy zająć się stworzeniem odpowiedniego programu. Tym razem zbudowanie poprawnego kodu będzie wymagało od nas większej pracy niż w przypadku poprzedniej aplikacji. Tam wystarczyła nam tylko jedna instrukcja zbudowana z bloków, natomiast tutaj potrzebujemy ich kilka. Przejdźmy więc teraz do zakładki '''Blocks''', a poniżej, krok po kroku, omówimy wszystkie instrukcje.<br />
<br />
'''Zderzenie piłki z paletką i odbicie piłki'''<br />
<br />
Podstawową interakcją w naszej grze jest zderzenie piłeczki z paletką. Gdy do tego dojdzie, piłka musi odbić się od paletki. Musimy zatem ustalić, w jaki sposób ma zachować się piłka i określić, w stosunku do jakiego obiektu to zachowanie ma wystąpić. <br />
<br />
Naszą instrukcję można opisać w następujący sposób: '''Kiedy piłka zderzy się z innym obiektem, to odbij piłkę tak, jakby dotknęła dolnej krawędzi.'''<br />
<br />
[[Plik:s2-9.png]]<br />
<br />
Jak to działa? Przede wszystkim pamiętajmy, że piłka ma swoją prędkość. Gdy poruszająca się '''Piłka''' uderza w krawędź '''Canvas''' (nasze '''Boisko'''), to wywołuje wydarzenie '''EdgeReached''' (''zetknięcie z krawędzią''), a gdy uderza w inny obiekt, to wywołuje wydarzenie '''CollidedWith''' (''zderzenie z...''). My na ekranie mamy tylko jeden obiekt inny niż piłka, czyli paletkę. Zatem gdy piłka uderzy w paletkę, to zostanie uruchomiona akcja '''call[Piłka].Bounce''' (“''odbij piłkę''”). Akcja odbicia musi jeszcze wiedzieć, w którą stronę ma piłkę odbić, gdy ta uderzy w krawędź boczną lub górną i właśnie do tego służy parametr '''edge''' (''krawędź''). Jego wartość ustawiona na -1 powoduje odbicie '''Piłki''' tak, jakby dotknęła dolnej krawędzi (oznaczenia wszystkich krawędzi znajdują<br />
się dalej).<br />
<br />
'''Other''' (''inny obiekt''), można wykorzystać do ustalenia, w który obiekt uderzyła '''Piłka'''. My na ekranie mamy tylko paletkę, więc nie musimy sprawdzać wartości '''other'''.<br />
<br />
Polecenia '''When[Piłka].CollidedWith''' oraz '''Call[Piłka].Bounce''' znajdziemy w grupie '''Piłka''' (1), zaś obiekt z wartością liczbową - w grupie '''Math''' (2).<br />
<br />
[[Plik:s2-10.png]]<br />
<br />
[[Plik:info.png]]''Wszystkie instrukcje, tak jak w Scratchu, podzielone są na kategorie oznaczone odpowiednimi kolorami, co ułatwia nawigację.''<br />
<br />
<br />
'''Numeracja krawędzi ekranu w App Inventorze.'''<br />
Przed momentem skonfigurowaliśmy uderzenie piłki w dolną krawędź ekranu, która jest oznaczona numerem -1. Skąd wziął się właśnie taki numer? Krawędzie w programie App Inventor mają takie oznaczenia, jakie zaprezentowano na poniższej ilustracji. Krawędź północna oznaczona jest numerem 1, północno-wschodnia numerem 2 i w ten sposób docieramy do krawędzi dolnej, która jest oznaczona numerem -1.<br />
<br />
[[Plik:s2-11.png]]<br />
'''Zderzenie piłki z krawędzią i odbicie piłki od krawędzi.'''<br />
Teraz zaprogramujemy wydarzenie zderzenia piłki z krawędzią. Tutaj musimy rozróżnić dwa rodzaje krawędzi - krawędź boczną i krawędź dolną. Jeśli piłka zderzy się z krawędzią boczną, to zostanie odbita, a wartość jej prędkości zwiększy się o 1. Natomiast jeśli zderzy się krawędzią dolną, to nastąpi ponowne rozpoczęcie gry poprzez wywołanie odrębnej procedury, którą przygotujemy.<br />
<br />
[[Plik:squash-9.png|800px]]<br />
<br />
Najpierw sprawdzamy, czy piłka uderzyła w krawędź dolną (wartość edge wynoszącą -1). Krawędź -1 oznacza, że gracz przepuścił piłkę (nie odbił jej) i powoduje to rozpoczęcie gry od początku – poprzez wywołanie procedury reset Call[reset], którą przygotujemy za chwilę.<br />
<br />
Jeśli piłka uderzy w krawędź boczną, to zostaną wykonane dwie akcje:<br />
1. Odbij Piłkę tak, jakby się zderzyła z odpowiednią krawędzią (identyfikator krawędzi uzyskujemy przy pomocy '''get[edge]''')<br />
2. Zwiększ prędkość piłki o jeden więcej '''(Set[Piłka].Speed to [Piłka].[Speed] + 1)'''.<br />
<br />
Na zakończenie dołóżmy jeszcze akcję '''set[Screen1].[Title]''' na „Squash - ”&[Piłka]. [Speed], czyli ustaw pasek tytułu na napis Squash oraz prędkość poruszania się Piłki.<br />
<br />
'''Wariant pierwszy - poruszanie paletką za pomocą ruchu palca.'''<br />
<br />
Kolejnym krokiem będzie zaprogramowanie mechanizmu poruszania paletki poprzez przeciągnięcie palcem. Tutaj wykorzystamy funkcję <b>when[Paletka].Dragged.</b><br />
<br />
'''Przygotowanie procedury reset'''<br />
Teraz przygotujmy procedurę własną reset. Będzie ona uruchamiana zawsze, gdy piłka dotknie dolnej krawędzi oraz zawsze na początku gry. Będą w niej zawarte wszystkie domyślne dla naszej gry parametry, takie jak kolor tła, czy wymiary boiska. Dzięki temu nasza gra po porażce i przy każdym wznowieniu oraz na początku zawsze będzie wyglądała i działała tak samo. W obszarze '''Blocks''' w grupie '''Procedures''' znajdźmy '''to[procedure] do''' i przeciągnijmy ten element do obszaru ''Viewer''. Następnie zmieńmy jego nazwę na ''reset'' i wstawmy poszczególne klocki, jak na poniższej ilustracji.<br />
<br />
[[Plik:Przykład.jpg]]Tu grafika!!!<br />
<br />
1. Na początek ustawmy kolor tła naszego Boiska – jeżeli kolor jest szary (czyli jeśli przegraliśmy), to ustawiamy na biały. Dodajmy jeszcze warunek, że jeżeli boisko ma jakikolwiek inny kolor niż szary, to ustawiamy na biały - o tym za chwilę.<br />
<br />
2. Następnie ustawmy parametry początkowe Piłki – współrzędne X i Y, kierunek ('''Heading''') oraz prędkość piłki ('''Speed'''). Dzięki temu na początku gry piłka zawsze będzie w tej samej pozycji.<br />
<br />
3. Na samym dole, wzdłuż dolnej krawędzi Boiska (linia x1) rysujemy linię (w kolorze i szerokości ustawionej w procedurze '''when[Screen1].Initialize''', którą stworzymy za chwilę). Linia ta musi być za każdym razem rysowana ponownie, ponieważ ustawienie tła Boiska (na szare lub białe) powyżej powoduje jej usunięcie (wyczyszczenie całości Boiska).<br />
<br />
Przypomnijmy jeszcze raz, że procedura reset będzie uruchamiana za każdym razem, gdy Piłka dotknie dolnej krawędzi Boiska (czerwonej linii) oraz podczas uruchomienia aplikacji.<br />
<br />
'''Instrukcja when[Screen1].Initialize'''<br />
<br />
Została nam już ostatnia instrukcja, która będzie uruchamiana w momencie inicjowania komponentu Screen1, czyli w naszym przypadku po prostu przy każdym starcie aplikacji. W tej instrukcji zdefiniujemy parametry początkowe naszej aplikacji. <br />
<br />
[[Plik:Przykład.jpg]]Tu grafika!!!<br />
<br />
1. Szerokość Paletki ustawmy na ¼ szerokości Boiska.<br />
<br />
2. Ustalmy parametry rysowania Boiska (kolor czerwony, szerokość/grubość rysowania 9) – to wykorzystamy do rysowania czerwonej linii na dole Boiska.<br />
<br />
3. Na sam koniec uruchamiamy jeszcze procedurę reset. I tutaj znajdziemy odpowiedź, dlaczego w procedurze reset sprawdzane są również inne kolory boiska niż tylko szary. Program rozpoczyna od procedury '''when[Screen1].Initialize''' i ustawia obrys koloru boiska na czerwony o grubości linii 9. Procedura '''reset''' z kolei sprawdza, jaki jest kolor boiska i jeżeli jest szary lub inny niż szary, zmienia kolor na biały, rysując dodatkowo trzy linie - górną oraz boczne. W ten sposób dolna linia w czerwonym kolorze pozostaje na boisku, również po wykonaniu procedury reset. Musieliśmy rozwiązać to w taki sposób, ponieważ porażkę sygnalizujemy zmianą koloru tła, natomiast zamiana koloru tła spowodowałaby usunięcie tej linii.<br />
<br />
'''<li>Udostępnianie aplikacji</li>'''<br />
<br />
Nasza aplikacja działa teraz prawidłowo, zaś paletka przemieszcza się, kiedy przesuwamy palcem po ekranie. Korzystając z faktu, że mamy ciekawą, działającą aplikację, poświęćmy teraz chwilę na udostępnienie tej aplikacji dalej po to, by można było zainstalować ją na dowolnym smartfonie. W tym celu kliknijmy w menu Build (1), gdzie znajdziemy dwie funkcje (2):<br />
<br />
1.App (Provide QP code for .apk) - wybranie tej opcji spowoduje wyświetlenie kodu QR i da możliwość załadowania przy pomocy tego kodu samodzielnej aplikacji na telefonie, bez użycia MIT AI2 Companion.<br />
<br />
2.App (save .apk to my computer) - wybranie tego polecenia spowoduje zapisanie aplikacji na komputerze jako plik .apk. Dzięki temu możemy chociażby przesłać aplikację jako załącznik w e-mailu.<br />
<br />
[[Plik:info.png]]Tu grafika!!!<br />
<br />
'''<li>Suqash, wariant drugi - sterowanie paletką poprzez wychylenia telefonu</li>'''<br />
<br />
Teraz przejdźmy do zaprogramowania drugiego wariantu, czyli sterowania paletką poprzez obracanie smartfonem czy tabletem. Chcemy oczywiście zachować pierwszy wariant gry, dlatego stworzymy teraz nowy zapis projektu i to na nim wprowadzimy odpowiednie zmiany.<br />
Wybierzmy zatem '''Projects (1)''' w menu głównym, a następnie '''Save projects as... (2)''' i w polu ''<b>New name:</b>'' wpiszmy nową nazwę: '''Squash_przechylanie.'''<br />
Z grupy '''Sensors <i>(czujniki</i>)''' wybierzmy komponent o nazwie '''AccelerometerSensor (1)''' i przeciągnijmy go na obszar projektowania interfejsu. Jako że '''AccelerometerSensor''' jest obiektem niewidocznym, to nie zajmuje on miejsca na ekranie, ale możemy zobaczyć go poniżej ekranu, w sekcji '''Non-visible components (2).'''<br />
Komponent '''AccelerometerSensor''' będzie przez nas wykorzystany do odczytywania przechylenia telefonu.</div>M Kelniarzhttp://wiki.mistrzowiekodowania.pl/index.php?title=Plik:Squash-15.pngPlik:Squash-15.png2015-09-30T12:46:30Z<p>M Kelniarz: </p>
<hr />
<div></div>M Kelniarzhttp://wiki.mistrzowiekodowania.pl/index.php?title=Plik:Squash-14.pngPlik:Squash-14.png2015-09-30T12:46:15Z<p>M Kelniarz: </p>
<hr />
<div></div>M Kelniarzhttp://wiki.mistrzowiekodowania.pl/index.php?title=Plik:Squash-13.pngPlik:Squash-13.png2015-09-30T12:43:19Z<p>M Kelniarz: </p>
<hr />
<div></div>M Kelniarzhttp://wiki.mistrzowiekodowania.pl/index.php?title=Plik:Squash-12a.pngPlik:Squash-12a.png2015-09-30T12:42:59Z<p>M Kelniarz: </p>
<hr />
<div></div>M Kelniarzhttp://wiki.mistrzowiekodowania.pl/index.php?title=Plik:Squash-12.pngPlik:Squash-12.png2015-09-30T12:42:41Z<p>M Kelniarz: </p>
<hr />
<div></div>M Kelniarzhttp://wiki.mistrzowiekodowania.pl/index.php?title=Plik:Squash-11.pngPlik:Squash-11.png2015-09-30T12:42:24Z<p>M Kelniarz: </p>
<hr />
<div></div>M Kelniarzhttp://wiki.mistrzowiekodowania.pl/index.php?title=Plik:Squash-10a.pngPlik:Squash-10a.png2015-09-30T12:42:09Z<p>M Kelniarz: </p>
<hr />
<div></div>M Kelniarzhttp://wiki.mistrzowiekodowania.pl/index.php?title=Plik:Squash-10.pngPlik:Squash-10.png2015-09-30T12:41:53Z<p>M Kelniarz: </p>
<hr />
<div></div>M Kelniarzhttp://wiki.mistrzowiekodowania.pl/index.php?title=Plik:Squash-9.pngPlik:Squash-9.png2015-09-30T12:41:31Z<p>M Kelniarz: </p>
<hr />
<div></div>M Kelniarzhttp://wiki.mistrzowiekodowania.pl/index.php?title=Scenariusz_2_-_SquashScenariusz 2 - Squash2015-09-30T12:40:32Z<p>M Kelniarz: /* Scenariusz 2 */</p>
<hr />
<div>=Squash w dwóch wariantach=<br />
==Scenariusz 2==<br />
'''Cele:'''<br />
<br />
Stworzymy prostą grę Squash, polegającą na odbijaniu piłeczki paletką, w dwóch wariantach. W ten sposób poznamy m.in. podstawy definiowania interfejsu użytkownika oraz nauczymy się wykonywać proste animacje. Po wykonaniu ćwiczenia będziemy też potrafili sterować obiektami za pomocą przeciągania palcem (pierwszy wariant) po ekranie oraz poprzez przechylanie telefonu (drugi wariant).<br />
<br />
W tej wersji Squasha nie będzie systemu naliczania punktów, jak w tradycyjnej wersji tej gry. W naszej aplikacji na dole będzie umieszczona czerwona linia i jeśli piłka się z nią zderzy, to nastąpi przegrana. Co więcej, gdy nie odbijemy piłeczki i ta spadnie na czerwoną linię, boisko zmieni kolor na szary, co będzie oznaczało koniec gry.<br />
<br />
<ol>'''<li>Rozpoczęcie pracy</li>'''<br />
Wejdźmy na stronę [http://appinventor.mit.edu http://appinventor.mit.edu] i wybierzmy '''Create''', by uruchomić App Inventor. Następnie przejdźmy do zakładki '''My Projects''' (1), gdzie znajdziemy wszystkie nasze projekty - wystarczy tylko zalogować się na odpowiednie konto Google. W celu rozpoczęcia pracy nad nowym projektem kliknijmy na '''Start new project''' (2) i wpiszmy w oknie jego nazwę, np. Squash.<br />
<br />
[[Plik:s2-1.png|800px]]<br />
<br />
Nastąpi teraz automatyczne przejście do okna budowy aplikacji.<br />
<br />
Jak już wspomnieliśmy powyżej - w pierwszym wariancie naszej gry sterowanie paletką będzie odbywało się poprzez przeciąganie palcem po ekranie smartfona, natomiast w drugiej wersji będziemy sterować obracając nim. Obracanie ekranu zgodnie z pozycją telefonu czy tabletu jest domyślnym zachowaniem. Dlatego też w pierwszym wariancie musimy zablokować ekran po to, by ten nie zmieniał swojej orientacji. I od tego właśnie zaczniemy budowę naszej gry.<br />
<br />
Przejdźmy zatem do okna '''Properties''' i dla komponentu '''Screen1,''' w polu '''Screen Orientation''' (1) wybierzmy '''Portrait'''. Dzięki temu nasz ekran zawsze będzie wyświetlany pionowo, niezależnie od tego, w jakiej pozycji znajduje się urządzenie. Dodatkowo w polu '''Title''' wpiszmy tytuł naszego bieżącego komponentu (2). Nazwijmy go '''Squash'''.<br />
<br />
[[Plik:s2-2.png]]<br />
<br />
'''<li>Squash - projektowanie interfejsu</li>'''<br />
Po zablokowaniu obrotu ekranu przejdźmy do dodania komponentów. W naszej aplikacji wykorzystamy trzy elementy - wszystkie znajdziemy w grupie Drawing and Animation. Są to:<br />
<ol>'''<li>Canvas''' ''(zamknięty obszar)'' - jest to komponent ograniczający obszar animacji oraz rysowania. W obszarze tego komponentu poruszają się Ball oraz ImageSprite.</li><br />
'''<li>Ball''' ''(piłka)'' - w naszej aplikacji to po prostu piłka, którą będziemy odbijać za pomocą paletki.</li><br />
'''<li>ImageSprite''' ''(“duszek”)'' - znany ze Scratcha duszek. W naszej aplikacji będzie to paletka. '''Image Sprite''' jest podobny do komponentu '''Ball''', jednak duszek ma kształt prostokąta, a jego tłem może być dowolny plik graficzny, np. w formacie jpg.</li><br />
</ol><br />
<br />
[[Plik:s2-3.png]]<br />
<br />
Jako pierwszy komponent dodajmy '''Canvas''' (1).Przeciągnijmy go na nasz obszar roboczy, czyli '''Viewer'''.<br />
<br />
[[Plik:s2-4.png]]<br />
<br />
Po tym, jak wstawiliśmy komponent '''Canvas''', musimy zmienić jego cechy w oknie '''Properties'''. Zmodyfikujmy dwa atrybuty: '''Width''' ''(szerokość)'' oraz '''Height''' ''(wysokość)''. Dla większości komponentów zarówno szerokość, jak i wysokość można ustawić jako:<br />
<ol>'''<li>Automatic''' ''(automatyczna)'' - system samodzielnie dobierze odpowiednią wartość szerokości i wysokości lub pozostawi je<br />
w standardowym ustawieniu.</li><br />
'''<li>Fill parent''' ''(wypełnienie obiektu nadrzędnego)'' - sprawia, że komponent przejmuje wielkość komponentu nadrzędnego. W przypadku naszej aplikacji zaznaczenie tej opcji sprawiłoby, że obszar '''Canvas1''' przejąłby szerokość i wysokość od komponentu '''Screen1''', co możemy zauważyć na ilustracji powyżej, w oknie '''Components''' - '''Cavas1''' jest obiektem podrzędnym dla '''Screen1'''.</li><br />
<li>'''... pixels - szerokość/wysokość o podanej przez nas liczbie pikseli.</li></ol><br />
Ustawmy zatem dla komponentu '''Canvas1''' wartości '''Width''' jako '''Fill Parent''' (1) oraz '''Height''' jako 300 pikseli(2).<br />
<br />
Teraz czas na kolejne komponenty. Dodajmy '''Ball''' (1) oraz '''ImageSprite''' (2) w dowolne miejsca w obrębie komponentu '''Canvas1'''. Tak jak wspomnieliśmy wcześniej, komponenty '''Ball''' oraz '''ImageSprite''' mogą być umieszczone jedynie na komponencie '''Canvas'''. Nie można umieścić ich poza tym obszarem, bezpośrednio na ekranie telefonu.<br />
<br />
[[Plik:s2-5.png]]<br />
<br />
Po dodaniu dwóch następnych komponentów dostosujmy ich właściwości tak, by odpowiadały naszym założeniom. Zacznijmy od komponentu '''Ball''' - na początek zmieńmy nazwę tego obiektu, klikając '''Rename''' (1) i wpisując '''Piłka''' w polu '''New Name'''. Następnie zmieńmy kilka cech tego komponentu w oknie właściwości, czyli '''Properties''':<br />
<ul><li>'''Heading''' (''kierunek'')- wpiszmy wartość 50 (2)</li><br />
<li>'''Paint Color''' (''kolor'')- wybierzmy '''Blue''' (3)</li><br />
<li>'''Radius''' (''promień'')- promień, czyli po prostu wielkość piłki ustalmy na 5 (4)</li><br />
<li>'''Speed''' (''prędkość'') - tutaj wpiszmy wartość 100 (5)</li><br />
<li>'''Współrzędne X i Y''' - obu współrzędnym nadajmy wartość 100 (6)</li></ul><br />
Inaczej niż w Scratchu, w programie App Inventor komponenty Ball oraz ImageSprite mogą mieć nadaną własną prędkość. W Scratchu efekt ten osiągaliśmy poprzez wielokrotne przesuwanie obiektu. Tutaj wystarczy, że nadamy komponentowi kierunek (Heading) oraz prędkość (Speed), zaś resztę pracy wykona za nas komputer.<br />
<br />
[[Plik:info.png|left]]''Warto zwrócić uwagę na hierarchię komponentów w oknie '''Components'''. Jak pamiętamy, w poprzedniej aplikacji wszystkie komponenty były bezpośrednio podrzędne dla '''Screen1'''. Tutaj podrzędny dla '''Screen1''' jest tylko '''Canvas1''', natomiast pozostałe dwa komponenty ('''Piłka''' oraz '''ImageSprite''') są podrzędne dla komponentu '''Canvas1'''.''<br />
<br />
<br />
[[Plik:s2-6.png]]<br />
<br />
Zmieńmy jeszcze nazwy pozostałych komponentów. '''Canvas1''' przestawmy na '''Boisko''' (1), zaś '''ImageSprite1''' na '''Paletka''' (2).<br />
<br />
[[Plik:s2-7.png]]<br />
<br />
Teraz przejdziemy do następnego kroku, czyli do skonfigurowania paletki.<br />
<br />
[[Plik:s2-8.png]]<br />
<br />
Przejdźmy zatem do zmiany właściwości komponentu o nazwie Paletka. Na początek kliknijmy na paletkę w oknie Components, by ją zaznaczyć - dzięki temu w oknie Properties pojawią się opcje, które pozwolą nam skonfigurować naszą paletkę. Konfigurację jej cech podzielimy na dwa kroki. W pierwszym kroku zadbamy o jej wygląd, zaś w drugim zajmiemy się jej rozmiarem i pozycją.<br />
<ol><li>'''Ustawienie pliku graficznego''' - wygląd paletki będzie wczytany z pliku graficznego, który załadujemy do programu. Paletka bez załadowanej grafiki byłaby przezroczysta, a to zdecydowanie utrudniłoby nam grę. Musimy zatem przygotować dowolny plik graficzny, np. w formacie png i wczytać go do mediów aplikacji, by następnie przypisać do paletki. Kliknijmy więc na '''Upload File''' (1) w oknie '''Media''' i odszukajmy plik, który chcemy wczytać do programu. Następnie przechodzimy do okna '''Properties''' i tam w polu '''Picture''' z rozwijanej listy wybierzmy nasz plik. Plików multimedialnych nie możemy przypisać bezpośrednio do komponentów, stąd w pierwszej kolejności musieliśmy wczytać plik do biblioteki mediów.</li><br />
<li>'''Wielkość i pozycja''' - po tym, jak wczytaliśmy już plik graficzny, przejdźmy do ustawienia pozostałych parametrów. Współrzędną X ustawmy na 100 pikseli, zaś Y - na 270 (3). Następnie parametry '''Width''' (szerokość) na 70 pikseli, a '''Height''' (wysokość) na 20 pikseli.</li></ol><br />
'''<li>Squash - programowanie aplikacji</li>'''<br />
Po tym, jak zakończyliśmy projektowanie interfejsu aplikacji, możemy zająć się stworzeniem odpowiedniego programu. Tym razem zbudowanie poprawnego kodu będzie wymagało od nas większej pracy niż w przypadku poprzedniej aplikacji. Tam wystarczyła nam tylko jedna instrukcja zbudowana z bloków, natomiast tutaj potrzebujemy ich kilka. Przejdźmy więc teraz do zakładki '''Blocks''', a poniżej, krok po kroku, omówimy wszystkie instrukcje.<br />
<br />
'''Zderzenie piłki z paletką i odbicie piłki'''<br />
<br />
Podstawową interakcją w naszej grze jest zderzenie piłeczki z paletką. Gdy do tego dojdzie, piłka musi odbić się od paletki. Musimy zatem ustalić, w jaki sposób ma zachować się piłka i określić, w stosunku do jakiego obiektu to zachowanie ma wystąpić. <br />
<br />
Naszą instrukcję można opisać w następujący sposób: '''Kiedy piłka zderzy się z innym obiektem, to odbij piłkę tak, jakby dotknęła dolnej krawędzi.'''<br />
<br />
[[Plik:s2-9.png]]<br />
<br />
Jak to działa? Przede wszystkim pamiętajmy, że piłka ma swoją prędkość. Gdy poruszająca się '''Piłka''' uderza w krawędź '''Canvas''' (nasze '''Boisko'''), to wywołuje wydarzenie '''EdgeReached''' (''zetknięcie z krawędzią''), a gdy uderza w inny obiekt, to wywołuje wydarzenie '''CollidedWith''' (''zderzenie z...''). My na ekranie mamy tylko jeden obiekt inny niż piłka, czyli paletkę. Zatem gdy piłka uderzy w paletkę, to zostanie uruchomiona akcja '''call[Piłka].Bounce''' (“''odbij piłkę''”). Akcja odbicia musi jeszcze wiedzieć, w którą stronę ma piłkę odbić, gdy ta uderzy w krawędź boczną lub górną i właśnie do tego służy parametr '''edge''' (''krawędź''). Jego wartość ustawiona na -1 powoduje odbicie '''Piłki''' tak, jakby dotknęła dolnej krawędzi (oznaczenia wszystkich krawędzi znajdują<br />
się dalej).<br />
<br />
'''Other''' (''inny obiekt''), można wykorzystać do ustalenia, w który obiekt uderzyła '''Piłka'''. My na ekranie mamy tylko paletkę, więc nie musimy sprawdzać wartości '''other'''.<br />
<br />
Polecenia '''When[Piłka].CollidedWith''' oraz '''Call[Piłka].Bounce''' znajdziemy w grupie '''Piłka''' (1), zaś obiekt z wartością liczbową - w grupie '''Math''' (2).<br />
<br />
[[Plik:s2-10.png]]<br />
<br />
[[Plik:info.png]]''Wszystkie instrukcje, tak jak w Scratchu, podzielone są na kategorie oznaczone odpowiednimi kolorami, co ułatwia nawigację.''<br />
<br />
<br />
'''Numeracja krawędzi ekranu w App Inventorze.'''<br />
Przed momentem skonfigurowaliśmy uderzenie piłki w dolną krawędź ekranu, która jest oznaczona numerem -1. Skąd wziął się właśnie taki numer? Krawędzie w programie App Inventor mają takie oznaczenia, jakie zaprezentowano na poniższej ilustracji. Krawędź północna oznaczona jest numerem 1, północno-wschodnia numerem 2 i w ten sposób docieramy do krawędzi dolnej, która jest oznaczona numerem -1.<br />
<br />
[[Plik:s2-11.png]]<br />
'''Zderzenie piłki z krawędzią i odbicie piłki od krawędzi.'''<br />
Teraz zaprogramujemy wydarzenie zderzenia piłki z krawędzią. Tutaj musimy rozróżnić dwa rodzaje krawędzi - krawędź boczną i krawędź dolną. Jeśli piłka zderzy się z krawędzią boczną, to zostanie odbita, a wartość jej prędkości zwiększy się o 1. Natomiast jeśli zderzy się krawędzią dolną, to nastąpi ponowne rozpoczęcie gry poprzez wywołanie odrębnej procedury, którą przygotujemy.<br />
<br />
[[Plik:Pinfo.png]]Tu grafika!!!<br />
<br />
'''Wariant pierwszy - poruszanie paletką za pomocą ruchu palca.'''<br />
<br />
Kolejnym krokiem będzie zaprogramowanie mechanizmu poruszania paletki poprzez przeciągnięcie palcem. Tutaj wykorzystamy funkcję <b>when[Paletka].Dragged.</b><br />
<br />
'''Przygotowanie procedury reset'''<br />
Teraz przygotujmy procedurę własną reset. Będzie ona uruchamiana zawsze, gdy piłka dotknie dolnej krawędzi oraz zawsze na początku gry. Będą w niej zawarte wszystkie domyślne dla naszej gry parametry, takie jak kolor tła, czy wymiary boiska. Dzięki temu nasza gra po porażce i przy każdym wznowieniu oraz na początku zawsze będzie wyglądała i działała tak samo. W obszarze '''Blocks''' w grupie '''Procedures''' znajdźmy '''to[procedure] do''' i przeciągnijmy ten element do obszaru ''Viewer''. Następnie zmieńmy jego nazwę na ''reset'' i wstawmy poszczególne klocki, jak na poniższej ilustracji.<br />
<br />
[[Plik:Przykład.jpg]]Tu grafika!!!<br />
<br />
1. Na początek ustawmy kolor tła naszego Boiska – jeżeli kolor jest szary (czyli jeśli przegraliśmy), to ustawiamy na biały. Dodajmy jeszcze warunek, że jeżeli boisko ma jakikolwiek inny kolor niż szary, to ustawiamy na biały - o tym za chwilę.<br />
<br />
2. Następnie ustawmy parametry początkowe Piłki – współrzędne X i Y, kierunek ('''Heading''') oraz prędkość piłki ('''Speed'''). Dzięki temu na początku gry piłka zawsze będzie w tej samej pozycji.<br />
<br />
3. Na samym dole, wzdłuż dolnej krawędzi Boiska (linia x1) rysujemy linię (w kolorze i szerokości ustawionej w procedurze '''when[Screen1].Initialize''', którą stworzymy za chwilę). Linia ta musi być za każdym razem rysowana ponownie, ponieważ ustawienie tła Boiska (na szare lub białe) powyżej powoduje jej usunięcie (wyczyszczenie całości Boiska).<br />
<br />
Przypomnijmy jeszcze raz, że procedura reset będzie uruchamiana za każdym razem, gdy Piłka dotknie dolnej krawędzi Boiska (czerwonej linii) oraz podczas uruchomienia aplikacji.<br />
<br />
'''Instrukcja when[Screen1].Initialize'''<br />
<br />
Została nam już ostatnia instrukcja, która będzie uruchamiana w momencie inicjowania komponentu Screen1, czyli w naszym przypadku po prostu przy każdym starcie aplikacji. W tej instrukcji zdefiniujemy parametry początkowe naszej aplikacji. <br />
<br />
[[Plik:Przykład.jpg]]Tu grafika!!!<br />
<br />
1. Szerokość Paletki ustawmy na ¼ szerokości Boiska.<br />
<br />
2. Ustalmy parametry rysowania Boiska (kolor czerwony, szerokość/grubość rysowania 9) – to wykorzystamy do rysowania czerwonej linii na dole Boiska.<br />
<br />
3. Na sam koniec uruchamiamy jeszcze procedurę reset. I tutaj znajdziemy odpowiedź, dlaczego w procedurze reset sprawdzane są również inne kolory boiska niż tylko szary. Program rozpoczyna od procedury '''when[Screen1].Initialize''' i ustawia obrys koloru boiska na czerwony o grubości linii 9. Procedura '''reset''' z kolei sprawdza, jaki jest kolor boiska i jeżeli jest szary lub inny niż szary, zmienia kolor na biały, rysując dodatkowo trzy linie - górną oraz boczne. W ten sposób dolna linia w czerwonym kolorze pozostaje na boisku, również po wykonaniu procedury reset. Musieliśmy rozwiązać to w taki sposób, ponieważ porażkę sygnalizujemy zmianą koloru tła, natomiast zamiana koloru tła spowodowałaby usunięcie tej linii.<br />
<br />
'''<li>Udostępnianie aplikacji</li>'''<br />
<br />
Nasza aplikacja działa teraz prawidłowo, zaś paletka przemieszcza się, kiedy przesuwamy palcem po ekranie. Korzystając z faktu, że mamy ciekawą, działającą aplikację, poświęćmy teraz chwilę na udostępnienie tej aplikacji dalej po to, by można było zainstalować ją na dowolnym smartfonie. W tym celu kliknijmy w menu Build (1), gdzie znajdziemy dwie funkcje (2):<br />
<br />
1.App (Provide QP code for .apk) - wybranie tej opcji spowoduje wyświetlenie kodu QR i da możliwość załadowania przy pomocy tego kodu samodzielnej aplikacji na telefonie, bez użycia MIT AI2 Companion.<br />
<br />
2.App (save .apk to my computer) - wybranie tego polecenia spowoduje zapisanie aplikacji na komputerze jako plik .apk. Dzięki temu możemy chociażby przesłać aplikację jako załącznik w e-mailu.<br />
<br />
[[Plik:info.png]]Tu grafika!!!<br />
<br />
'''<li>Suqash, wariant drugi - sterowanie paletką poprzez wychylenia telefonu</li>'''<br />
<br />
Teraz przejdźmy do zaprogramowania drugiego wariantu, czyli sterowania paletką poprzez obracanie smartfonem czy tabletem. Chcemy oczywiście zachować pierwszy wariant gry, dlatego stworzymy teraz nowy zapis projektu i to na nim wprowadzimy odpowiednie zmiany.<br />
Wybierzmy zatem '''Projects (1)''' w menu głównym, a następnie '''Save projects as... (2)''' i w polu ''<b>New name:</b>'' wpiszmy nową nazwę: '''Squash_przechylanie.'''<br />
Z grupy '''Sensors <i>(czujniki</i>)''' wybierzmy komponent o nazwie '''AccelerometerSensor (1)''' i przeciągnijmy go na obszar projektowania interfejsu. Jako że '''AccelerometerSensor''' jest obiektem niewidocznym, to nie zajmuje on miejsca na ekranie, ale możemy zobaczyć go poniżej ekranu, w sekcji '''Non-visible components (2).'''<br />
Komponent '''AccelerometerSensor''' będzie przez nas wykorzystany do odczytywania przechylenia telefonu.</div>M Kelniarzhttp://wiki.mistrzowiekodowania.pl/index.php?title=Scenariusz_2_-_SquashScenariusz 2 - Squash2015-09-28T15:48:01Z<p>M Kelniarz: /* Scenariusz 2 */</p>
<hr />
<div>=Squash w dwóch wariantach=<br />
==Scenariusz 2==<br />
'''Cele:'''<br />
<br />
Stworzymy prostą grę Squash, polegającą na odbijaniu piłeczki paletką, w dwóch wariantach. W ten sposób poznamy m.in. podstawy definiowania interfejsu użytkownika oraz nauczymy się wykonywać proste animacje. Po wykonaniu ćwiczenia będziemy też potrafili sterować obiektami za pomocą przeciągania palcem (pierwszy wariant) po ekranie oraz poprzez przechylanie telefonu (drugi wariant).<br />
<br />
W tej wersji Squasha nie będzie systemu naliczania punktów, jak w tradycyjnej wersji tej gry. W naszej aplikacji na dole będzie umieszczona czerwona linia i jeśli piłka się z nią zderzy, to nastąpi przegrana. Co więcej, gdy nie odbijemy piłeczki i ta spadnie na czerwoną linię, boisko zmieni kolor na szary, co będzie oznaczało koniec gry.<br />
<br />
<ol>'''<li>Rozpoczęcie pracy</li>'''<br />
Wejdźmy na stronę [http://appinventor.mit.edu http://appinventor.mit.edu] i wybierzmy '''Create''', by uruchomić App Inventor. Następnie przejdźmy do zakładki '''My Projects''' (1), gdzie znajdziemy wszystkie nasze projekty - wystarczy tylko zalogować się na odpowiednie konto Google. W celu rozpoczęcia pracy nad nowym projektem kliknijmy na '''Start new project''' (2) i wpiszmy w oknie jego nazwę, np. Squash.<br />
<br />
[[Plik:s2-1.png|800px]]<br />
<br />
Nastąpi teraz automatyczne przejście do okna budowy aplikacji.<br />
<br />
Jak już wspomnieliśmy powyżej - w pierwszym wariancie naszej gry sterowanie paletką będzie odbywało się poprzez przeciąganie palcem po ekranie smartfona, natomiast w drugiej wersji będziemy sterować obracając nim. Obracanie ekranu zgodnie z pozycją telefonu czy tabletu jest domyślnym zachowaniem. Dlatego też w pierwszym wariancie musimy zablokować ekran po to, by ten nie zmieniał swojej orientacji. I od tego właśnie zaczniemy budowę naszej gry.<br />
<br />
Przejdźmy zatem do okna '''Properties''' i dla komponentu '''Screen1,''' w polu '''Screen Orientation''' (1) wybierzmy '''Portrait'''. Dzięki temu nasz ekran zawsze będzie wyświetlany pionowo, niezależnie od tego, w jakiej pozycji znajduje się urządzenie. Dodatkowo w polu '''Title''' wpiszmy tytuł naszego bieżącego komponentu (2). Nazwijmy go '''Squash'''.<br />
<br />
[[Plik:s2-2.png]]<br />
<br />
'''<li>Squash - projektowanie interfejsu</li>'''<br />
Po zablokowaniu obrotu ekranu przejdźmy do dodania komponentów. W naszej aplikacji wykorzystamy trzy elementy - wszystkie znajdziemy w grupie Drawing and Animation. Są to:<br />
<ol>'''<li>Canvas''' ''(zamknięty obszar)'' - jest to komponent ograniczający obszar animacji oraz rysowania. W obszarze tego komponentu poruszają się Ball oraz ImageSprite.</li><br />
'''<li>Ball''' ''(piłka)'' - w naszej aplikacji to po prostu piłka, którą będziemy odbijać za pomocą paletki.</li><br />
'''<li>ImageSprite''' ''(“duszek”)'' - znany ze Scratcha duszek. W naszej aplikacji będzie to paletka. '''Image Sprite''' jest podobny do komponentu '''Ball''', jednak duszek ma kształt prostokąta, a jego tłem może być dowolny plik graficzny, np. w formacie jpg.</li><br />
</ol><br />
<br />
[[Plik:s2-3.png]]<br />
<br />
Jako pierwszy komponent dodajmy '''Canvas''' (1).Przeciągnijmy go na nasz obszar roboczy, czyli '''Viewer'''.<br />
<br />
[[Plik:s2-4.png]]<br />
<br />
Po tym, jak wstawiliśmy komponent '''Canvas''', musimy zmienić jego cechy w oknie '''Properties'''. Zmodyfikujmy dwa atrybuty: '''Width''' ''(szerokość)'' oraz '''Height''' ''(wysokość)''. Dla większości komponentów zarówno szerokość, jak i wysokość można ustawić jako:<br />
<ol>'''<li>Automatic''' ''(automatyczna)'' - system samodzielnie dobierze odpowiednią wartość szerokości i wysokości lub pozostawi je<br />
w standardowym ustawieniu.</li><br />
'''<li>Fill parent''' ''(wypełnienie obiektu nadrzędnego)'' - sprawia, że komponent przejmuje wielkość komponentu nadrzędnego. W przypadku naszej aplikacji zaznaczenie tej opcji sprawiłoby, że obszar '''Canvas1''' przejąłby szerokość i wysokość od komponentu '''Screen1''', co możemy zauważyć na ilustracji powyżej, w oknie '''Components''' - '''Cavas1''' jest obiektem podrzędnym dla '''Screen1'''.</li><br />
<li>'''... pixels - szerokość/wysokość o podanej przez nas liczbie pikseli.</li></ol><br />
Ustawmy zatem dla komponentu '''Canvas1''' wartości '''Width''' jako '''Fill Parent''' (1) oraz '''Height''' jako 300 pikseli(2).<br />
<br />
Teraz czas na kolejne komponenty. Dodajmy '''Ball''' (1) oraz '''ImageSprite''' (2) w dowolne miejsca w obrębie komponentu '''Canvas1'''. Tak jak wspomnieliśmy wcześniej, komponenty '''Ball''' oraz '''ImageSprite''' mogą być umieszczone jedynie na komponencie '''Canvas'''. Nie można umieścić ich poza tym obszarem, bezpośrednio na ekranie telefonu.<br />
<br />
[[Plik:s2-5.png]]<br />
<br />
Po dodaniu dwóch następnych komponentów dostosujmy ich właściwości tak, by odpowiadały naszym założeniom. Zacznijmy od komponentu '''Ball''' - na początek zmieńmy nazwę tego obiektu, klikając '''Rename''' (1) i wpisując '''Piłka''' w polu '''New Name'''. Następnie zmieńmy kilka cech tego komponentu w oknie właściwości, czyli '''Properties''':<br />
<ul><li>'''Heading''' (''kierunek'')- wpiszmy wartość 50 (2)</li><br />
<li>'''Paint Color''' (''kolor'')- wybierzmy '''Blue''' (3)</li><br />
<li>'''Radius''' (''promień'')- promień, czyli po prostu wielkość piłki ustalmy na 5 (4)</li><br />
<li>'''Speed''' (''prędkość'') - tutaj wpiszmy wartość 100 (5)</li><br />
<li>'''Współrzędne X i Y''' - obu współrzędnym nadajmy wartość 100 (6)</li></ul><br />
Inaczej niż w Scratchu, w programie App Inventor komponenty Ball oraz ImageSprite mogą mieć nadaną własną prędkość. W Scratchu efekt ten osiągaliśmy poprzez wielokrotne przesuwanie obiektu. Tutaj wystarczy, że nadamy komponentowi kierunek (Heading) oraz prędkość (Speed), zaś resztę pracy wykona za nas komputer.<br />
<br />
[[Plik:info.png|left]]''Warto zwrócić uwagę na hierarchię komponentów w oknie '''Components'''. Jak pamiętamy, w poprzedniej aplikacji wszystkie komponenty były bezpośrednio podrzędne dla '''Screen1'''. Tutaj podrzędny dla '''Screen1''' jest tylko '''Canvas1''', natomiast pozostałe dwa komponenty ('''Piłka''' oraz '''ImageSprite''') są podrzędne dla komponentu '''Canvas1'''.''<br />
<br />
<br />
[[Plik:s2-6.png]]<br />
<br />
Zmieńmy jeszcze nazwy pozostałych komponentów. '''Canvas1''' przestawmy na '''Boisko''' (1), zaś '''ImageSprite1''' na '''Paletka''' (2).<br />
<br />
[[Plik:s2-7.png]]<br />
<br />
Teraz przejdziemy do następnego kroku, czyli do skonfigurowania paletki.<br />
<br />
[[Plik:s2-8.png]]<br />
<br />
Przejdźmy zatem do zmiany właściwości komponentu o nazwie Paletka. Na początek kliknijmy na paletkę w oknie Components, by ją zaznaczyć - dzięki temu w oknie Properties pojawią się opcje, które pozwolą nam skonfigurować naszą paletkę. Konfigurację jej cech podzielimy na dwa kroki. W pierwszym kroku zadbamy o jej wygląd, zaś w drugim zajmiemy się jej rozmiarem i pozycją.<br />
<ol><li>'''Ustawienie pliku graficznego''' - wygląd paletki będzie wczytany z pliku graficznego, który załadujemy do programu. Paletka bez załadowanej grafiki byłaby przezroczysta, a to zdecydowanie utrudniłoby nam grę. Musimy zatem przygotować dowolny plik graficzny, np. w formacie png i wczytać go do mediów aplikacji, by następnie przypisać do paletki. Kliknijmy więc na '''Upload File''' (1) w oknie '''Media''' i odszukajmy plik, który chcemy wczytać do programu. Następnie przechodzimy do okna '''Properties''' i tam w polu '''Picture''' z rozwijanej listy wybierzmy nasz plik. Plików multimedialnych nie możemy przypisać bezpośrednio do komponentów, stąd w pierwszej kolejności musieliśmy wczytać plik do biblioteki mediów.</li><br />
<li>'''Wielkość i pozycja''' - po tym, jak wczytaliśmy już plik graficzny, przejdźmy do ustawienia pozostałych parametrów. Współrzędną X ustawmy na 100 pikseli, zaś Y - na 270 (3). Następnie parametry '''Width''' (szerokość) na 70 pikseli, a '''Height''' (wysokość) na 20 pikseli.</li></ol><br />
'''<li>Squash - programowanie aplikacji</li>'''<br />
Po tym, jak zakończyliśmy projektowanie interfejsu aplikacji, możemy zająć się stworzeniem odpowiedniego programu. Tym razem zbudowanie poprawnego kodu będzie wymagało od nas większej pracy niż w przypadku poprzedniej aplikacji. Tam wystarczyła nam tylko jedna instrukcja zbudowana z bloków, natomiast tutaj potrzebujemy ich kilka. Przejdźmy więc teraz do zakładki '''Blocks''', a poniżej, krok po kroku, omówimy wszystkie instrukcje.<br />
<br />
'''Zderzenie piłki z paletką i odbicie piłki'''<br />
<br />
Podstawową interakcją w naszej grze jest zderzenie piłeczki z paletką. Gdy do tego dojdzie, piłka musi odbić się od paletki. Musimy zatem ustalić, w jaki sposób ma zachować się piłka i określić, w stosunku do jakiego obiektu to zachowanie ma wystąpić. <br />
<br />
Naszą instrukcję można opisać w następujący sposób: '''Kiedy piłka zderzy się z innym obiektem, to odbij piłkę tak, jakby dotknęła dolnej krawędzi.'''<br />
<br />
[[Plik:s2-9.png]]<br />
<br />
Jak to działa? Przede wszystkim pamiętajmy, że piłka ma swoją prędkość. Gdy poruszająca się '''Piłka''' uderza w krawędź '''Canvas''' (nasze '''Boisko'''), to wywołuje wydarzenie '''EdgeReached''' (''zetknięcie z krawędzią''), a gdy uderza w inny obiekt, to wywołuje wydarzenie '''CollidedWith''' (''zderzenie z...''). My na ekranie mamy tylko jeden obiekt inny niż piłka, czyli paletkę. Zatem gdy piłka uderzy w paletkę, to zostanie uruchomiona akcja '''call[Piłka].Bounce''' (“''odbij piłkę''”). Akcja odbicia musi jeszcze wiedzieć, w którą stronę ma piłkę odbić, gdy ta uderzy w krawędź boczną lub górną i właśnie do tego służy parametr '''edge''' (''krawędź''). Jego wartość ustawiona na -1 powoduje odbicie '''Piłki''' tak, jakby dotknęła dolnej krawędzi (oznaczenia wszystkich krawędzi znajdują<br />
się dalej).<br />
<br />
'''Other''' (''inny obiekt''), można wykorzystać do ustalenia, w który obiekt uderzyła '''Piłka'''. My na ekranie mamy tylko paletkę, więc nie musimy sprawdzać wartości '''other'''.<br />
<br />
Polecenia '''When[Piłka].CollidedWith''' oraz '''Call[Piłka].Bounce''' znajdziemy w grupie '''Piłka''' (1), zaś obiekt z wartością liczbową - w grupie '''Math''' (2).<br />
<br />
[[Plik:s2-10.png]]<br />
<br />
[[Plik:info.png]]''Wszystkie instrukcje, tak jak w Scratchu, podzielone są na kategorie oznaczone odpowiednimi kolorami, co ułatwia nawigację.''<br />
<br />
<br />
'''Numeracja krawędzi ekranu w App Inventorze.'''<br />
Przed momentem skonfigurowaliśmy uderzenie piłki w dolną krawędź ekranu, która jest oznaczona numerem -1. Skąd wziął się właśnie taki numer? Krawędzie w programie App Inventor mają takie oznaczenia, jakie zaprezentowano na poniższej ilustracji. Krawędź północna oznaczona jest numerem 1, północno-wschodnia numerem 2 i w ten sposób docieramy do krawędzi dolnej, która jest oznaczona numerem -1.<br />
<br />
[[Plik:s2-11.png]]<br />
'''Zderzenie piłki z krawędzią i odbicie piłki od krawędzi.'''<br />
Teraz zaprogramujemy wydarzenie zderzenia piłki z krawędzią. Tutaj musimy rozróżnić dwa rodzaje krawędzi - krawędź boczną i krawędź dolną. Jeśli piłka zderzy się z krawędzią boczną, to zostanie odbita, a wartość jej prędkości zwiększy się o 1. Natomiast jeśli zderzy się krawędzią dolną, to nastąpi ponowne rozpoczęcie gry poprzez wywołanie odrębnej procedury, którą przygotujemy.<br />
<br />
[[Plik:Pinfo.png]]Tu grafika!!!<br />
<br />
'''Wariant pierwszy - poruszanie paletką za pomocą ruchu palca.'''<br />
Kolejnym krokiem będzie zaprogramowanie mechanizmu poruszania paletki poprzez przeciągnięcie palcem. Tutaj wykorzystamy funkcję <b>when[Paletka].Dragged.</b><br />
<br />
'''Przygotowanie procedury reset'''<br />
Teraz przygotujmy procedurę własną reset. Będzie ona uruchamiana zawsze, gdy piłka dotknie dolnej krawędzi oraz zawsze na początku gry. Będą w niej zawarte wszystkie domyślne dla naszej gry parametry, takie jak kolor tła, czy wymiary boiska. Dzięki temu nasza gra po porażce i przy każdym wznowieniu oraz na początku zawsze będzie wyglądała i działała tak samo. W obszarze '''Blocks''' w grupie '''Procedures''' znajdźmy '''to[procedure] do''' i przeciągnijmy ten element do obszaru ''Viewer''. Następnie zmieńmy jego nazwę na ''reset'' i wstawmy poszczególne klocki, jak na poniższej ilustracji.<br />
<br />
Wariant pierwszy - poruszanie paletką za pomocą ruchu palcaKolejnym krokiem będzie zaprogramowanie mechanizmu poruszania paletki poprzez przeciągnięcie palcem. Tutaj wykorzystamy funkcję when[Paletka].Dragged.Przygotowanie procedury resetTeraz przygotujmy procedurę własną reset. Będzie ona uruchamiana zawsze, gdy piłka dotknie dolnej krawędzi oraz zawsze na początku gry. Będą w niej zawarte wszystkie domyślne dla naszej gry parametry, takie jak kolor tła, czy wymiary boiska. Dzięki temu nasza gra po porażce i przy każdym wznowieniu oraz na początku zawsze będzie wyglądała i działała tak samo. W obszarze Blocks w grupie Procedures znajdźmy to[procedure] do i przeciągnijmy ten element do obszaru Viewer. Następnie zmieńmy jego nazwę na reset i wstawmy poszczególne klocki, jak na poniższej ilustracji.<br />
<br />
[[Plik:Przykład.jpg]]Tu grafika!!!<br />
<br />
1. Na początek ustawmy kolor tła naszego Boiska – jeżeli kolor jest szary (czyli jeśli przegraliśmy), to ustawiamy na biały. Dodajmy jeszcze warunek, że jeżeli boisko ma jakikolwiek inny kolor niż szary, to ustawiamy na biały - o tym za chwilę.<br />
<br />
2. Następnie ustawmy parametry początkowe Piłki – współrzędne X i Y, kierunek ('''Heading''') oraz prędkość piłki ('''Speed'''). Dzięki temu na początku gry piłka zawsze będzie w tej samej pozycji.<br />
<br />
3. Na samym dole, wzdłuż dolnej krawędzi Boiska (linia x1) rysujemy linię (w kolorze i szerokości ustawionej w procedurze '''when[Screen1].Initialize''', którą stworzymy za chwilę). Linia ta musi być za każdym razem rysowana ponownie, ponieważ ustawienie tła Boiska (na szare lub białe) powyżej powoduje jej usunięcie (wyczyszczenie całości Boiska).<br />
<br />
Przypomnijmy jeszcze raz, że procedura reset będzie uruchamiana za każdym razem, gdy Piłka dotknie dolnej krawędzi Boiska (czerwonej linii) oraz podczas uruchomienia aplikacji.<br />
<br />
'''Instrukcja when[Screen1].Initialize'''<br />
<br />
Została nam już ostatnia instrukcja, która będzie uruchamiana w momencie inicjowania komponentu Screen1, czyli w naszym przypadku po prostu przy każdym starcie aplikacji. W tej instrukcji zdefiniujemy parametry początkowe naszej aplikacji. <br />
<br />
[[Plik:Przykład.jpg]]Tu grafika!!!<br />
<br />
1. Szerokość Paletki ustawmy na ¼ szerokości Boiska.<br />
<br />
2. Ustalmy parametry rysowania Boiska (kolor czerwony, szerokość/grubość rysowania 9) – to wykorzystamy do rysowania czerwonej linii na dole Boiska.<br />
<br />
3. Na sam koniec uruchamiamy jeszcze procedurę reset. I tutaj znajdziemy odpowiedź, dlaczego w procedurze reset sprawdzane są również inne kolory boiska niż tylko szary. Program rozpoczyna od procedury '''when[Screen1].Initialize''' i ustawia obrys koloru boiska na czerwony o grubości linii 9. Procedura '''reset''' z kolei sprawdza, jaki jest kolor boiska i jeżeli jest szary lub inny niż szary, zmienia kolor na biały, rysując dodatkowo trzy linie - górną oraz boczne. W ten sposób dolna linia w czerwonym kolorze pozostaje na boisku, również po wykonaniu procedury reset. Musieliśmy rozwiązać to w taki sposób, ponieważ porażkę sygnalizujemy zmianą koloru tła, natomiast zamiana koloru tła spowodowałaby usunięcie tej linii.<br />
<br />
'''<li>Udostępnianie aplikacji</li>'''<br />
<br />
Nasza aplikacja działa teraz prawidłowo, zaś paletka przemieszcza się, kiedy przesuwamy palcem po ekranie. Korzystając z faktu, że mamy ciekawą, działającą aplikację, poświęćmy teraz chwilę na udostępnienie tej aplikacji dalej po to, by można było zainstalować ją na dowolnym smartfonie. W tym celu kliknijmy w menu Build (1), gdzie znajdziemy dwie funkcje (2):<br />
<br />
1.App (Provide QP code for .apk) - wybranie tej opcji spowoduje wyświetlenie kodu QR i da możliwość załadowania przy pomocy tego kodu samodzielnej aplikacji na telefonie, bez użycia MIT AI2 Companion.<br />
<br />
2.App (save .apk to my computer) - wybranie tego polecenia spowoduje zapisanie aplikacji na komputerze jako plik .apk. Dzięki temu możemy chociażby przesłać aplikację jako załącznik w e-mailu.<br />
<br />
[[Plik:info.png]]Tu grafika!!!<br />
<br />
'''<li>Suqash, wariant drugi - sterowanie paletką poprzez wychylenia telefonu</li>'''<br />
<br />
Teraz przejdźmy do zaprogramowania drugiego wariantu, czyli sterowania paletką poprzez obracanie smartfonem czy tabletem. Chcemy oczywiście zachować pierwszy wariant gry, dlatego stworzymy teraz nowy zapis projektu i to na nim wprowadzimy odpowiednie zmiany.<br />
Wybierzmy zatem '''Projects (1)''' w menu głównym, a następnie '''Save projects as... (2)''' i w polu ''<b>New name:</b>'' wpiszmy nową nazwę: '''Squash_przechylanie.'''<br />
Z grupy '''Sensors <i>(czujniki</i>)''' wybierzmy komponent o nazwie '''AccelerometerSensor (1)''' i przeciągnijmy go na obszar projektowania interfejsu. Jako że '''AccelerometerSensor''' jest obiektem niewidocznym, to nie zajmuje on miejsca na ekranie, ale możemy zobaczyć go poniżej ekranu, w sekcji '''Non-visible components (2).'''<br />
Komponent '''AccelerometerSensor''' będzie przez nas wykorzystany do odczytywania przechylenia telefonu.</div>M Kelniarzhttp://wiki.mistrzowiekodowania.pl/index.php?title=Scenariusz_2_-_SquashScenariusz 2 - Squash2015-09-14T15:31:26Z<p>M Kelniarz: /* Scenariusz 2 */</p>
<hr />
<div>=Squash w dwóch wariantach=<br />
==Scenariusz 2==<br />
'''Cele:'''<br />
<br />
Stworzymy prostą grę Squash, polegającą na odbijaniu piłeczki paletką, w dwóch wariantach. W ten sposób poznamy m.in. podstawy definiowania interfejsu użytkownika oraz nauczymy się wykonywać proste animacje. Po wykonaniu ćwiczenia będziemy też potrafili sterować obiektami za pomocą przeciągania palcem (pierwszy wariant) po ekranie oraz poprzez przechylanie telefonu (drugi wariant).<br />
<br />
W tej wersji Squasha nie będzie systemu naliczania punktów, jak w tradycyjnej wersji tej gry. W naszej aplikacji na dole będzie umieszczona czerwona linia i jeśli piłka się z nią zderzy, to nastąpi przegrana. Co więcej, gdy nie odbijemy piłeczki i ta spadnie na czerwoną linię, boisko zmieni kolor na szary, co będzie oznaczało koniec gry.<br />
<br />
<ol>'''<li>Rozpoczęcie pracy</li>'''<br />
Wejdźmy na stronę [http://appinventor.mit.edu http://appinventor.mit.edu] i wybierzmy '''Create''', by uruchomić App Inventor. Następnie przejdźmy do zakładki '''My Projects''' (1), gdzie znajdziemy wszystkie nasze projekty - wystarczy tylko zalogować się na odpowiednie konto Google. W celu rozpoczęcia pracy nad nowym projektem kliknijmy na '''Start new project''' (2) i wpiszmy w oknie jego nazwę, np. Squash.<br />
<br />
[[Plik:s2-1.png|800px]]<br />
<br />
Nastąpi teraz automatyczne przejście do okna budowy aplikacji.<br />
<br />
Jak już wspomnieliśmy powyżej - w pierwszym wariancie naszej gry sterowanie paletką będzie odbywało się poprzez przeciąganie palcem po ekranie smartfona, natomiast w drugiej wersji będziemy sterować obracając nim. Obracanie ekranu zgodnie z pozycją telefonu czy tabletu jest domyślnym zachowaniem. Dlatego też w pierwszym wariancie musimy zablokować ekran po to, by ten nie zmieniał swojej orientacji. I od tego właśnie zaczniemy budowę naszej gry.<br />
<br />
Przejdźmy zatem do okna '''Properties''' i dla komponentu '''Screen1,''' w polu '''Screen Orientation''' (1) wybierzmy '''Portrait'''. Dzięki temu nasz ekran zawsze będzie wyświetlany pionowo, niezależnie od tego, w jakiej pozycji znajduje się urządzenie. Dodatkowo w polu '''Title''' wpiszmy tytuł naszego bieżącego komponentu (2). Nazwijmy go '''Squash'''.<br />
<br />
[[Plik:s2-2.png]]<br />
<br />
'''<li>Squash - projektowanie interfejsu</li>'''<br />
Po zablokowaniu obrotu ekranu przejdźmy do dodania komponentów. W naszej aplikacji wykorzystamy trzy elementy - wszystkie znajdziemy w grupie Drawing and Animation. Są to:<br />
<ol>'''<li>Canvas''' ''(zamknięty obszar)'' - jest to komponent ograniczający obszar animacji oraz rysowania. W obszarze tego komponentu poruszają się Ball oraz ImageSprite.</li><br />
'''<li>Ball''' ''(piłka)'' - w naszej aplikacji to po prostu piłka, którą będziemy odbijać za pomocą paletki.</li><br />
'''<li>ImageSprite''' ''(“duszek”)'' - znany ze Scratcha duszek. W naszej aplikacji będzie to paletka. '''Image Sprite''' jest podobny do komponentu '''Ball''', jednak duszek ma kształt prostokąta, a jego tłem może być dowolny plik graficzny, np. w formacie jpg.</li><br />
</ol><br />
<br />
[[Plik:s2-3.png]]<br />
<br />
Jako pierwszy komponent dodajmy '''Canvas''' (1).Przeciągnijmy go na nasz obszar roboczy, czyli '''Viewer'''.<br />
<br />
[[Plik:s2-4.png]]<br />
<br />
Po tym, jak wstawiliśmy komponent '''Canvas''', musimy zmienić jego cechy w oknie '''Properties'''. Zmodyfikujmy dwa atrybuty: '''Width''' ''(szerokość)'' oraz '''Height''' ''(wysokość)''. Dla większości komponentów zarówno szerokość, jak i wysokość można ustawić jako:<br />
<ol>'''<li>Automatic''' ''(automatyczna)'' - system samodzielnie dobierze odpowiednią wartość szerokości i wysokości lub pozostawi je<br />
w standardowym ustawieniu.</li><br />
'''<li>Fill parent''' ''(wypełnienie obiektu nadrzędnego)'' - sprawia, że komponent przejmuje wielkość komponentu nadrzędnego. W przypadku naszej aplikacji zaznaczenie tej opcji sprawiłoby, że obszar '''Canvas1''' przejąłby szerokość i wysokość od komponentu '''Screen1''', co możemy zauważyć na ilustracji powyżej, w oknie '''Components''' - '''Cavas1''' jest obiektem podrzędnym dla '''Screen1'''.</li><br />
<li>'''... pixels - szerokość/wysokość o podanej przez nas liczbie pikseli.</li></ol><br />
Ustawmy zatem dla komponentu '''Canvas1''' wartości '''Width''' jako '''Fill Parent''' (1) oraz '''Height''' jako 300 pikseli(2).<br />
<br />
Teraz czas na kolejne komponenty. Dodajmy '''Ball''' (1) oraz '''ImageSprite''' (2) w dowolne miejsca w obrębie komponentu '''Canvas1'''. Tak jak wspomnieliśmy wcześniej, komponenty '''Ball''' oraz '''ImageSprite''' mogą być umieszczone jedynie na komponencie '''Canvas'''. Nie można umieścić ich poza tym obszarem, bezpośrednio na ekranie telefonu.<br />
<br />
[[Plik:s2-5.png]]<br />
<br />
Po dodaniu dwóch następnych komponentów dostosujmy ich właściwości tak, by odpowiadały naszym założeniom. Zacznijmy od komponentu '''Ball''' - na początek zmieńmy nazwę tego obiektu, klikając '''Rename''' (1) i wpisując '''Piłka''' w polu '''New Name'''. Następnie zmieńmy kilka cech tego komponentu w oknie właściwości, czyli '''Properties''':<br />
<ul><li>'''Heading''' (''kierunek'')- wpiszmy wartość 50 (2)</li><br />
<li>'''Paint Color''' (''kolor'')- wybierzmy '''Blue''' (3)</li><br />
<li>'''Radius''' (''promień'')- promień, czyli po prostu wielkość piłki ustalmy na 5 (4)</li><br />
<li>'''Speed''' (''prędkość'') - tutaj wpiszmy wartość 100 (5)</li><br />
<li>'''Współrzędne X i Y''' - obu współrzędnym nadajmy wartość 100 (6)</li></ul><br />
Inaczej niż w Scratchu, w programie App Inventor komponenty Ball oraz ImageSprite mogą mieć nadaną własną prędkość. W Scratchu efekt ten osiągaliśmy poprzez wielokrotne przesuwanie obiektu. Tutaj wystarczy, że nadamy komponentowi kierunek (Heading) oraz prędkość (Speed), zaś resztę pracy wykona za nas komputer.<br />
<br />
[[Plik:info.png|left]]''Warto zwrócić uwagę na hierarchię komponentów w oknie '''Components'''. Jak pamiętamy, w poprzedniej aplikacji wszystkie komponenty były bezpośrednio podrzędne dla '''Screen1'''. Tutaj podrzędny dla '''Screen1''' jest tylko '''Canvas1''', natomiast pozostałe dwa komponenty ('''Piłka''' oraz '''ImageSprite''') są podrzędne dla komponentu '''Canvas1'''.''<br />
<br />
<br />
[[Plik:s2-6.png]]<br />
<br />
Zmieńmy jeszcze nazwy pozostałych komponentów. '''Canvas1''' przestawmy na '''Boisko''' (1), zaś '''ImageSprite1''' na '''Paletka''' (2).<br />
<br />
[[Plik:s2-7.png]]<br />
<br />
Teraz przejdziemy do następnego kroku, czyli do skonfigurowania paletki.<br />
<br />
[[Plik:s2-8.png]]<br />
<br />
Przejdźmy zatem do zmiany właściwości komponentu o nazwie Paletka. Na początek kliknijmy na paletkę w oknie Components, by ją zaznaczyć - dzięki temu w oknie Properties pojawią się opcje, które pozwolą nam skonfigurować naszą paletkę. Konfigurację jej cech podzielimy na dwa kroki. W pierwszym kroku zadbamy o jej wygląd, zaś w drugim zajmiemy się jej rozmiarem i pozycją.<br />
<ol><li>'''Ustawienie pliku graficznego''' - wygląd paletki będzie wczytany z pliku graficznego, który załadujemy do programu. Paletka bez załadowanej grafiki byłaby przezroczysta, a to zdecydowanie utrudniłoby nam grę. Musimy zatem przygotować dowolny plik graficzny, np. w formacie png i wczytać go do mediów aplikacji, by następnie przypisać do paletki. Kliknijmy więc na '''Upload File''' (1) w oknie '''Media''' i odszukajmy plik, który chcemy wczytać do programu. Następnie przechodzimy do okna '''Properties''' i tam w polu '''Picture''' z rozwijanej listy wybierzmy nasz plik. Plików multimedialnych nie możemy przypisać bezpośrednio do komponentów, stąd w pierwszej kolejności musieliśmy wczytać plik do biblioteki mediów.</li><br />
<li>'''Wielkość i pozycja''' - po tym, jak wczytaliśmy już plik graficzny, przejdźmy do ustawienia pozostałych parametrów. Współrzędną X ustawmy na 100 pikseli, zaś Y - na 270 (3). Następnie parametry '''Width''' (szerokość) na 70 pikseli, a '''Height''' (wysokość) na 20 pikseli.</li></ol><br />
'''<li>Squash - programowanie aplikacji</li>'''<br />
Po tym, jak zakończyliśmy projektowanie interfejsu aplikacji, możemy zająć się stworzeniem odpowiedniego programu. Tym razem zbudowanie poprawnego kodu będzie wymagało od nas większej pracy niż w przypadku poprzedniej aplikacji. Tam wystarczyła nam tylko jedna instrukcja zbudowana z bloków, natomiast tutaj potrzebujemy ich kilka. Przejdźmy więc teraz do zakładki '''Blocks''', a poniżej, krok po kroku, omówimy wszystkie instrukcje.<br />
<br />
'''Zderzenie piłki z paletką i odbicie piłki'''<br />
<br />
Podstawową interakcją w naszej grze jest zderzenie piłeczki z paletką. Gdy do tego dojdzie, piłka musi odbić się od paletki. Musimy zatem ustalić, w jaki sposób ma zachować się piłka i określić, w stosunku do jakiego obiektu to zachowanie ma wystąpić. <br />
<br />
Naszą instrukcję można opisać w następujący sposób: '''Kiedy piłka zderzy się z innym obiektem, to odbij piłkę tak, jakby dotknęła dolnej krawędzi.'''<br />
<br />
[[Plik:s2-9.png]]<br />
<br />
Jak to działa? Przede wszystkim pamiętajmy, że piłka ma swoją prędkość. Gdy poruszająca się '''Piłka''' uderza w krawędź '''Canvas''' (nasze '''Boisko'''), to wywołuje wydarzenie '''EdgeReached''' (''zetknięcie z krawędzią''), a gdy uderza w inny obiekt, to wywołuje wydarzenie '''CollidedWith''' (''zderzenie z...''). My na ekranie mamy tylko jeden obiekt inny niż piłka, czyli paletkę. Zatem gdy piłka uderzy w paletkę, to zostanie uruchomiona akcja '''call[Piłka].Bounce''' (“''odbij piłkę''”). Akcja odbicia musi jeszcze wiedzieć, w którą stronę ma piłkę odbić, gdy ta uderzy w krawędź boczną lub górną i właśnie do tego służy parametr '''edge''' (''krawędź''). Jego wartość ustawiona na -1 powoduje odbicie '''Piłki''' tak, jakby dotknęła dolnej krawędzi (oznaczenia wszystkich krawędzi znajdują<br />
się dalej).<br />
<br />
'''Other''' (''inny obiekt''), można wykorzystać do ustalenia, w który obiekt uderzyła '''Piłka'''. My na ekranie mamy tylko paletkę, więc nie musimy sprawdzać wartości '''other'''.<br />
<br />
Polecenia '''When[Piłka].CollidedWith''' oraz '''Call[Piłka].Bounce''' znajdziemy w grupie '''Piłka''' (1), zaś obiekt z wartością liczbową - w grupie '''Math''' (2).<br />
<br />
[[Plik:s2-10.png]]<br />
<br />
[[Plik:info.png]]''Wszystkie instrukcje, tak jak w Scratchu, podzielone są na kategorie oznaczone odpowiednimi kolorami, co ułatwia nawigację.''<br />
<br />
<br />
'''Numeracja krawędzi ekranu w App Inventorze.'''<br />
Przed momentem skonfigurowaliśmy uderzenie piłki w dolną krawędź ekranu, która jest oznaczona numerem -1. Skąd wziął się właśnie taki numer? Krawędzie w programie App Inventor mają takie oznaczenia, jakie zaprezentowano na poniższej ilustracji. Krawędź północna oznaczona jest numerem 1, północno-wschodnia numerem 2 i w ten sposób docieramy do krawędzi dolnej, która jest oznaczona numerem -1.<br />
<br />
[[Plik:s2-11.png]]<br />
'''Zderzenie piłki z krawędzią i odbicie piłki od krawędzi.'''<br />
Teraz zaprogramujemy wydarzenie zderzenia piłki z krawędzią. Tutaj musimy rozróżnić dwa rodzaje krawędzi - krawędź boczną i krawędź dolną. Jeśli piłka zderzy się z krawędzią boczną, to zostanie odbita, a wartość jej prędkości zwiększy się o 1. Natomiast jeśli zderzy się krawędzią dolną, to nastąpi ponowne rozpoczęcie gry poprzez wywołanie odrębnej procedury, którą przygotujemy.<br />
<br />
[[Plik:Pinfo.png]]Tu grafika!!!<br />
<br />
'''Wariant pierwszy - poruszanie paletką za pomocą ruchu palca.'''<br />
Kolejnym krokiem będzie zaprogramowanie mechanizmu poruszania paletki poprzez przeciągnięcie palcem. Tutaj wykorzystamy funkcję <b>when[Paletka].Dragged.</b><br />
<br />
'''Przygotowanie procedury reset'''<br />
Teraz przygotujmy procedurę własną reset. Będzie ona uruchamiana zawsze, gdy piłka dotknie dolnej krawędzi oraz zawsze na początku gry. Będą w niej zawarte wszystkie domyślne dla naszej gry parametry, takie jak kolor tła, czy wymiary boiska. Dzięki temu nasza gra po porażce i przy każdym wznowieniu oraz na początku zawsze będzie wyglądała i działała tak samo. W obszarze '''Blocks''' w grupie '''Procedures''' znajdźmy '''to[procedure] do''' i przeciągnijmy ten element do obszaru ''Viewer''. Następnie zmieńmy jego nazwę na ''reset'' i wstawmy poszczególne klocki, jak na poniższej ilustracji.<br />
<br />
Wariant pierwszy - poruszanie paletką za pomocą ruchu palcaKolejnym krokiem będzie zaprogramowanie mechanizmu poruszania paletki poprzez przeciągnięcie palcem. Tutaj wykorzystamy funkcję when[Paletka].Dragged.Przygotowanie procedury resetTeraz przygotujmy procedurę własną reset. Będzie ona uruchamiana zawsze, gdy piłka dotknie dolnej krawędzi oraz zawsze na początku gry. Będą w niej zawarte wszystkie domyślne dla naszej gry parametry, takie jak kolor tła, czy wymiary boiska. Dzięki temu nasza gra po porażce i przy każdym wznowieniu oraz na początku zawsze będzie wyglądała i działała tak samo. W obszarze Blocks w grupie Procedures znajdźmy to[procedure] do i przeciągnijmy ten element do obszaru Viewer. Następnie zmieńmy jego nazwę na reset i wstawmy poszczególne klocki, jak na poniższej ilustracji.<br />
<br />
[[Plik:Przykład.jpg]]Tu grafika!!!<br />
<br />
1. Na początek ustawmy kolor tła naszego Boiska – jeżeli kolor jest szary (czyli jeśli przegraliśmy), to ustawiamy na biały. Dodajmy jeszcze warunek, że jeżeli boisko ma jakikolwiek inny kolor niż szary, to ustawiamy na biały - o tym za chwilę.<br />
<br />
2. Następnie ustawmy parametry początkowe Piłki – współrzędne X i Y, kierunek ('''Heading''') oraz prędkość piłki ('''Speed'''). Dzięki temu na początku gry piłka zawsze będzie w tej samej pozycji.<br />
<br />
3. Na samym dole, wzdłuż dolnej krawędzi Boiska (linia x1) rysujemy linię (w kolorze i szerokości ustawionej w procedurze '''when[Screen1].Initialize''', którą stworzymy za chwilę). Linia ta musi być za każdym razem rysowana ponownie, ponieważ ustawienie tła Boiska (na szare lub białe) powyżej powoduje jej usunięcie (wyczyszczenie całości Boiska).<br />
<br />
Przypomnijmy jeszcze raz, że procedura reset będzie uruchamiana za każdym razem, gdy Piłka dotknie dolnej krawędzi Boiska (czerwonej linii) oraz podczas uruchomienia aplikacji.<br />
<br />
'''Instrukcja when[Screen1].Initialize'''<br />
<br />
Została nam już ostatnia instrukcja, która będzie uruchamiana w momencie inicjowania komponentu Screen1, czyli w naszym przypadku po prostu przy każdym starcie aplikacji. W tej instrukcji zdefiniujemy parametry początkowe naszej aplikacji. <br />
<br />
[[Plik:Przykład.jpg]]Tu grafika!!!<br />
<br />
1. Szerokość Paletki ustawmy na ¼ szerokości Boiska.<br />
<br />
2. Ustalmy parametry rysowania Boiska (kolor czerwony, szerokość/grubość rysowania 9) – to wykorzystamy do rysowania czerwonej linii na dole Boiska.<br />
<br />
3. Na sam koniec uruchamiamy jeszcze procedurę reset. I tutaj znajdziemy odpowiedź, dlaczego w procedurze reset sprawdzane są również inne kolory boiska niż tylko szary. Program rozpoczyna od procedury '''when[Screen1].Initialize''' i ustawia obrys koloru boiska na czerwony o grubości linii 9. Procedura '''reset''' z kolei sprawdza, jaki jest kolor boiska i jeżeli jest szary lub inny niż szary, zmienia kolor na biały, rysując dodatkowo trzy linie - górną oraz boczne. W ten sposób dolna linia w czerwonym kolorze pozostaje na boisku, również po wykonaniu procedury reset. Musieliśmy rozwiązać to w taki sposób, ponieważ porażkę sygnalizujemy zmianą koloru tła, natomiast zamiana koloru tła spowodowałaby usunięcie tej linii.<br />
<br />
'''<li>Udostępnianie aplikacji</li>'''<br />
<br />
Nasza aplikacja działa teraz prawidłowo, zaś paletka przemieszcza się, kiedy przesuwamy palcem po ekranie. Korzystając z faktu, że mamy ciekawą, działającą aplikację, poświęćmy teraz chwilę na udostępnienie tej aplikacji dalej po to, by można było zainstalować ją na dowolnym smartfonie. W tym celu kliknijmy w menu Build (1), gdzie znajdziemy dwie funkcje (2):<br />
<br />
1.App (Provide QP code for .apk) - wybranie tej opcji spowoduje wyświetlenie kodu QR i da możliwość załadowania przy pomocy tego kodu samodzielnej aplikacji na telefonie, bez użycia MIT AI2 Companion.<br />
<br />
2.App (save .apk to my computer) - wybranie tego polecenia spowoduje zapisanie aplikacji na komputerze jako plik .apk. Dzięki temu możemy chociażby przesłać aplikację jako załącznik w e-mailu.<br />
<br />
[[Plik:info.png]]Tu grafika!!!</div>M Kelniarzhttp://wiki.mistrzowiekodowania.pl/index.php?title=Scenariusz_2_-_SquashScenariusz 2 - Squash2015-09-14T15:20:16Z<p>M Kelniarz: /* Scenariusz 2 */</p>
<hr />
<div>=Squash w dwóch wariantach=<br />
==Scenariusz 2==<br />
'''Cele:'''<br />
<br />
Stworzymy prostą grę Squash, polegającą na odbijaniu piłeczki paletką, w dwóch wariantach. W ten sposób poznamy m.in. podstawy definiowania interfejsu użytkownika oraz nauczymy się wykonywać proste animacje. Po wykonaniu ćwiczenia będziemy też potrafili sterować obiektami za pomocą przeciągania palcem (pierwszy wariant) po ekranie oraz poprzez przechylanie telefonu (drugi wariant).<br />
<br />
W tej wersji Squasha nie będzie systemu naliczania punktów, jak w tradycyjnej wersji tej gry. W naszej aplikacji na dole będzie umieszczona czerwona linia i jeśli piłka się z nią zderzy, to nastąpi przegrana. Co więcej, gdy nie odbijemy piłeczki i ta spadnie na czerwoną linię, boisko zmieni kolor na szary, co będzie oznaczało koniec gry.<br />
<br />
<ol>'''<li>Rozpoczęcie pracy</li>'''<br />
Wejdźmy na stronę [http://appinventor.mit.edu http://appinventor.mit.edu] i wybierzmy '''Create''', by uruchomić App Inventor. Następnie przejdźmy do zakładki '''My Projects''' (1), gdzie znajdziemy wszystkie nasze projekty - wystarczy tylko zalogować się na odpowiednie konto Google. W celu rozpoczęcia pracy nad nowym projektem kliknijmy na '''Start new project''' (2) i wpiszmy w oknie jego nazwę, np. Squash.<br />
<br />
[[Plik:s2-1.png|800px]]<br />
<br />
Nastąpi teraz automatyczne przejście do okna budowy aplikacji.<br />
<br />
Jak już wspomnieliśmy powyżej - w pierwszym wariancie naszej gry sterowanie paletką będzie odbywało się poprzez przeciąganie palcem po ekranie smartfona, natomiast w drugiej wersji będziemy sterować obracając nim. Obracanie ekranu zgodnie z pozycją telefonu czy tabletu jest domyślnym zachowaniem. Dlatego też w pierwszym wariancie musimy zablokować ekran po to, by ten nie zmieniał swojej orientacji. I od tego właśnie zaczniemy budowę naszej gry.<br />
<br />
Przejdźmy zatem do okna '''Properties''' i dla komponentu '''Screen1,''' w polu '''Screen Orientation''' (1) wybierzmy '''Portrait'''. Dzięki temu nasz ekran zawsze będzie wyświetlany pionowo, niezależnie od tego, w jakiej pozycji znajduje się urządzenie. Dodatkowo w polu '''Title''' wpiszmy tytuł naszego bieżącego komponentu (2). Nazwijmy go '''Squash'''.<br />
<br />
[[Plik:s2-2.png]]<br />
<br />
'''<li>Squash - projektowanie interfejsu</li>'''<br />
Po zablokowaniu obrotu ekranu przejdźmy do dodania komponentów. W naszej aplikacji wykorzystamy trzy elementy - wszystkie znajdziemy w grupie Drawing and Animation. Są to:<br />
<ol>'''<li>Canvas''' ''(zamknięty obszar)'' - jest to komponent ograniczający obszar animacji oraz rysowania. W obszarze tego komponentu poruszają się Ball oraz ImageSprite.</li><br />
'''<li>Ball''' ''(piłka)'' - w naszej aplikacji to po prostu piłka, którą będziemy odbijać za pomocą paletki.</li><br />
'''<li>ImageSprite''' ''(“duszek”)'' - znany ze Scratcha duszek. W naszej aplikacji będzie to paletka. '''Image Sprite''' jest podobny do komponentu '''Ball''', jednak duszek ma kształt prostokąta, a jego tłem może być dowolny plik graficzny, np. w formacie jpg.</li><br />
</ol><br />
<br />
[[Plik:s2-3.png]]<br />
<br />
Jako pierwszy komponent dodajmy '''Canvas''' (1).Przeciągnijmy go na nasz obszar roboczy, czyli '''Viewer'''.<br />
<br />
[[Plik:s2-4.png]]<br />
<br />
Po tym, jak wstawiliśmy komponent '''Canvas''', musimy zmienić jego cechy w oknie '''Properties'''. Zmodyfikujmy dwa atrybuty: '''Width''' ''(szerokość)'' oraz '''Height''' ''(wysokość)''. Dla większości komponentów zarówno szerokość, jak i wysokość można ustawić jako:<br />
<ol>'''<li>Automatic''' ''(automatyczna)'' - system samodzielnie dobierze odpowiednią wartość szerokości i wysokości lub pozostawi je<br />
w standardowym ustawieniu.</li><br />
'''<li>Fill parent''' ''(wypełnienie obiektu nadrzędnego)'' - sprawia, że komponent przejmuje wielkość komponentu nadrzędnego. W przypadku naszej aplikacji zaznaczenie tej opcji sprawiłoby, że obszar '''Canvas1''' przejąłby szerokość i wysokość od komponentu '''Screen1''', co możemy zauważyć na ilustracji powyżej, w oknie '''Components''' - '''Cavas1''' jest obiektem podrzędnym dla '''Screen1'''.</li><br />
<li>'''... pixels - szerokość/wysokość o podanej przez nas liczbie pikseli.</li></ol><br />
Ustawmy zatem dla komponentu '''Canvas1''' wartości '''Width''' jako '''Fill Parent''' (1) oraz '''Height''' jako 300 pikseli(2).<br />
<br />
Teraz czas na kolejne komponenty. Dodajmy '''Ball''' (1) oraz '''ImageSprite''' (2) w dowolne miejsca w obrębie komponentu '''Canvas1'''. Tak jak wspomnieliśmy wcześniej, komponenty '''Ball''' oraz '''ImageSprite''' mogą być umieszczone jedynie na komponencie '''Canvas'''. Nie można umieścić ich poza tym obszarem, bezpośrednio na ekranie telefonu.<br />
<br />
[[Plik:s2-5.png]]<br />
<br />
Po dodaniu dwóch następnych komponentów dostosujmy ich właściwości tak, by odpowiadały naszym założeniom. Zacznijmy od komponentu '''Ball''' - na początek zmieńmy nazwę tego obiektu, klikając '''Rename''' (1) i wpisując '''Piłka''' w polu '''New Name'''. Następnie zmieńmy kilka cech tego komponentu w oknie właściwości, czyli '''Properties''':<br />
<ul><li>'''Heading''' (''kierunek'')- wpiszmy wartość 50 (2)</li><br />
<li>'''Paint Color''' (''kolor'')- wybierzmy '''Blue''' (3)</li><br />
<li>'''Radius''' (''promień'')- promień, czyli po prostu wielkość piłki ustalmy na 5 (4)</li><br />
<li>'''Speed''' (''prędkość'') - tutaj wpiszmy wartość 100 (5)</li><br />
<li>'''Współrzędne X i Y''' - obu współrzędnym nadajmy wartość 100 (6)</li></ul><br />
Inaczej niż w Scratchu, w programie App Inventor komponenty Ball oraz ImageSprite mogą mieć nadaną własną prędkość. W Scratchu efekt ten osiągaliśmy poprzez wielokrotne przesuwanie obiektu. Tutaj wystarczy, że nadamy komponentowi kierunek (Heading) oraz prędkość (Speed), zaś resztę pracy wykona za nas komputer.<br />
<br />
[[Plik:info.png|left]]''Warto zwrócić uwagę na hierarchię komponentów w oknie '''Components'''. Jak pamiętamy, w poprzedniej aplikacji wszystkie komponenty były bezpośrednio podrzędne dla '''Screen1'''. Tutaj podrzędny dla '''Screen1''' jest tylko '''Canvas1''', natomiast pozostałe dwa komponenty ('''Piłka''' oraz '''ImageSprite''') są podrzędne dla komponentu '''Canvas1'''.''<br />
<br />
<br />
[[Plik:s2-6.png]]<br />
<br />
Zmieńmy jeszcze nazwy pozostałych komponentów. '''Canvas1''' przestawmy na '''Boisko''' (1), zaś '''ImageSprite1''' na '''Paletka''' (2).<br />
<br />
[[Plik:s2-7.png]]<br />
<br />
Teraz przejdziemy do następnego kroku, czyli do skonfigurowania paletki.<br />
<br />
[[Plik:s2-8.png]]<br />
<br />
Przejdźmy zatem do zmiany właściwości komponentu o nazwie Paletka. Na początek kliknijmy na paletkę w oknie Components, by ją zaznaczyć - dzięki temu w oknie Properties pojawią się opcje, które pozwolą nam skonfigurować naszą paletkę. Konfigurację jej cech podzielimy na dwa kroki. W pierwszym kroku zadbamy o jej wygląd, zaś w drugim zajmiemy się jej rozmiarem i pozycją.<br />
<ol><li>'''Ustawienie pliku graficznego''' - wygląd paletki będzie wczytany z pliku graficznego, który załadujemy do programu. Paletka bez załadowanej grafiki byłaby przezroczysta, a to zdecydowanie utrudniłoby nam grę. Musimy zatem przygotować dowolny plik graficzny, np. w formacie png i wczytać go do mediów aplikacji, by następnie przypisać do paletki. Kliknijmy więc na '''Upload File''' (1) w oknie '''Media''' i odszukajmy plik, który chcemy wczytać do programu. Następnie przechodzimy do okna '''Properties''' i tam w polu '''Picture''' z rozwijanej listy wybierzmy nasz plik. Plików multimedialnych nie możemy przypisać bezpośrednio do komponentów, stąd w pierwszej kolejności musieliśmy wczytać plik do biblioteki mediów.</li><br />
<li>'''Wielkość i pozycja''' - po tym, jak wczytaliśmy już plik graficzny, przejdźmy do ustawienia pozostałych parametrów. Współrzędną X ustawmy na 100 pikseli, zaś Y - na 270 (3). Następnie parametry '''Width''' (szerokość) na 70 pikseli, a '''Height''' (wysokość) na 20 pikseli.</li></ol><br />
'''<li>Squash - programowanie aplikacji</li>'''<br />
Po tym, jak zakończyliśmy projektowanie interfejsu aplikacji, możemy zająć się stworzeniem odpowiedniego programu. Tym razem zbudowanie poprawnego kodu będzie wymagało od nas większej pracy niż w przypadku poprzedniej aplikacji. Tam wystarczyła nam tylko jedna instrukcja zbudowana z bloków, natomiast tutaj potrzebujemy ich kilka. Przejdźmy więc teraz do zakładki '''Blocks''', a poniżej, krok po kroku, omówimy wszystkie instrukcje.<br />
<br />
'''Zderzenie piłki z paletką i odbicie piłki'''<br />
<br />
Podstawową interakcją w naszej grze jest zderzenie piłeczki z paletką. Gdy do tego dojdzie, piłka musi odbić się od paletki. Musimy zatem ustalić, w jaki sposób ma zachować się piłka i określić, w stosunku do jakiego obiektu to zachowanie ma wystąpić. <br />
<br />
Naszą instrukcję można opisać w następujący sposób: '''Kiedy piłka zderzy się z innym obiektem, to odbij piłkę tak, jakby dotknęła dolnej krawędzi.'''<br />
<br />
[[Plik:s2-9.png]]<br />
<br />
Jak to działa? Przede wszystkim pamiętajmy, że piłka ma swoją prędkość. Gdy poruszająca się '''Piłka''' uderza w krawędź '''Canvas''' (nasze '''Boisko'''), to wywołuje wydarzenie '''EdgeReached''' (''zetknięcie z krawędzią''), a gdy uderza w inny obiekt, to wywołuje wydarzenie '''CollidedWith''' (''zderzenie z...''). My na ekranie mamy tylko jeden obiekt inny niż piłka, czyli paletkę. Zatem gdy piłka uderzy w paletkę, to zostanie uruchomiona akcja '''call[Piłka].Bounce''' (“''odbij piłkę''”). Akcja odbicia musi jeszcze wiedzieć, w którą stronę ma piłkę odbić, gdy ta uderzy w krawędź boczną lub górną i właśnie do tego służy parametr '''edge''' (''krawędź''). Jego wartość ustawiona na -1 powoduje odbicie '''Piłki''' tak, jakby dotknęła dolnej krawędzi (oznaczenia wszystkich krawędzi znajdują<br />
się dalej).<br />
<br />
'''Other''' (''inny obiekt''), można wykorzystać do ustalenia, w który obiekt uderzyła '''Piłka'''. My na ekranie mamy tylko paletkę, więc nie musimy sprawdzać wartości '''other'''.<br />
<br />
Polecenia '''When[Piłka].CollidedWith''' oraz '''Call[Piłka].Bounce''' znajdziemy w grupie '''Piłka''' (1), zaś obiekt z wartością liczbową - w grupie '''Math''' (2).<br />
<br />
[[Plik:s2-10.png]]<br />
<br />
[[Plik:info.png]]''Wszystkie instrukcje, tak jak w Scratchu, podzielone są na kategorie oznaczone odpowiednimi kolorami, co ułatwia nawigację.''<br />
<br />
<br />
'''Numeracja krawędzi ekranu w App Inventorze.'''<br />
Przed momentem skonfigurowaliśmy uderzenie piłki w dolną krawędź ekranu, która jest oznaczona numerem -1. Skąd wziął się właśnie taki numer? Krawędzie w programie App Inventor mają takie oznaczenia, jakie zaprezentowano na poniższej ilustracji. Krawędź północna oznaczona jest numerem 1, północno-wschodnia numerem 2 i w ten sposób docieramy do krawędzi dolnej, która jest oznaczona numerem -1.<br />
<br />
[[Plik:s2-11.png]]<br />
'''Zderzenie piłki z krawędzią i odbicie piłki od krawędzi.'''<br />
Teraz zaprogramujemy wydarzenie zderzenia piłki z krawędzią. Tutaj musimy rozróżnić dwa rodzaje krawędzi - krawędź boczną i krawędź dolną. Jeśli piłka zderzy się z krawędzią boczną, to zostanie odbita, a wartość jej prędkości zwiększy się o 1. Natomiast jeśli zderzy się krawędzią dolną, to nastąpi ponowne rozpoczęcie gry poprzez wywołanie odrębnej procedury, którą przygotujemy.<br />
<br />
[[Plik:Pinfo.png]]Tu grafika!!!<br />
<br />
'''Wariant pierwszy - poruszanie paletką za pomocą ruchu palca.'''<br />
Kolejnym krokiem będzie zaprogramowanie mechanizmu poruszania paletki poprzez przeciągnięcie palcem. Tutaj wykorzystamy funkcję <b>when[Paletka].Dragged.</b><br />
<br />
'''Przygotowanie procedury reset'''<br />
Teraz przygotujmy procedurę własną reset. Będzie ona uruchamiana zawsze, gdy piłka dotknie dolnej krawędzi oraz zawsze na początku gry. Będą w niej zawarte wszystkie domyślne dla naszej gry parametry, takie jak kolor tła, czy wymiary boiska. Dzięki temu nasza gra po porażce i przy każdym wznowieniu oraz na początku zawsze będzie wyglądała i działała tak samo. W obszarze '''Blocks''' w grupie '''Procedures''' znajdźmy '''to[procedure] do''' i przeciągnijmy ten element do obszaru ''Viewer''. Następnie zmieńmy jego nazwę na ''reset'' i wstawmy poszczególne klocki, jak na poniższej ilustracji.<br />
<br />
Wariant pierwszy - poruszanie paletką za pomocą ruchu palcaKolejnym krokiem będzie zaprogramowanie mechanizmu poruszania paletki poprzez przeciągnięcie palcem. Tutaj wykorzystamy funkcję when[Paletka].Dragged.Przygotowanie procedury resetTeraz przygotujmy procedurę własną reset. Będzie ona uruchamiana zawsze, gdy piłka dotknie dolnej krawędzi oraz zawsze na początku gry. Będą w niej zawarte wszystkie domyślne dla naszej gry parametry, takie jak kolor tła, czy wymiary boiska. Dzięki temu nasza gra po porażce i przy każdym wznowieniu oraz na początku zawsze będzie wyglądała i działała tak samo. W obszarze Blocks w grupie Procedures znajdźmy to[procedure] do i przeciągnijmy ten element do obszaru Viewer. Następnie zmieńmy jego nazwę na reset i wstawmy poszczególne klocki, jak na poniższej ilustracji.<br />
<br />
[[Plik:Przykład.jpg]]Tu grafika!!!<br />
<br />
1. Na początek ustawmy kolor tła naszego Boiska – jeżeli kolor jest szary (czyli jeśli przegraliśmy), to ustawiamy na biały. Dodajmy jeszcze warunek, że jeżeli boisko ma jakikolwiek inny kolor niż szary, to ustawiamy na biały - o tym za chwilę.<br />
<br />
2. Następnie ustawmy parametry początkowe Piłki – współrzędne X i Y, kierunek ('''Heading''') oraz prędkość piłki ('''Speed'''). Dzięki temu na początku gry piłka zawsze będzie w tej samej pozycji.<br />
<br />
3. Na samym dole, wzdłuż dolnej krawędzi Boiska (linia x1) rysujemy linię (w kolorze i szerokości ustawionej w procedurze '''when[Screen1].Initialize''', którą stworzymy za chwilę). Linia ta musi być za każdym razem rysowana ponownie, ponieważ ustawienie tła Boiska (na szare lub białe) powyżej powoduje jej usunięcie (wyczyszczenie całości Boiska).<br />
<br />
Przypomnijmy jeszcze raz, że procedura reset będzie uruchamiana za każdym razem, gdy Piłka dotknie dolnej krawędzi Boiska (czerwonej linii) oraz podczas uruchomienia aplikacji.<br />
<br />
'''Instrukcja when[Screen1].Initialize'''<br />
<br />
Została nam już ostatnia instrukcja, która będzie uruchamiana w momencie inicjowania komponentu Screen1, czyli w naszym przypadku po prostu przy każdym starcie aplikacji. W tej instrukcji zdefiniujemy parametry początkowe naszej aplikacji. <br />
<br />
[[Plik:Przykład.jpg]]Tu grafika!!!<br />
<br />
1. Szerokość Paletki ustawmy na ¼ szerokości Boiska.<br />
<br />
2. Ustalmy parametry rysowania Boiska (kolor czerwony, szerokość/grubość rysowania 9) – to wykorzystamy do rysowania czerwonej linii na dole Boiska.<br />
<br />
3. Na sam koniec uruchamiamy jeszcze procedurę reset. I tutaj znajdziemy odpowiedź, dlaczego w procedurze reset sprawdzane są również inne kolory boiska niż tylko szary. Program rozpoczyna od procedury '''when[Screen1].Initialize''' i ustawia obrys koloru boiska na czerwony o grubości linii 9. Procedura '''reset''' z kolei sprawdza, jaki jest kolor boiska i jeżeli jest szary lub inny niż szary, zmienia kolor na biały, rysując dodatkowo trzy linie - górną oraz boczne. W ten sposób dolna linia w czerwonym kolorze pozostaje na boisku, również po wykonaniu procedury reset. Musieliśmy rozwiązać to w taki sposób, ponieważ porażkę sygnalizujemy zmianą koloru tła, natomiast zamiana koloru tła spowodowałaby usunięcie tej linii.<br />
<br />
'''4. Udostępnianie aplikacji'''<br />
<br />
Nasza aplikacja działa teraz prawidłowo, zaś paletka przemieszcza się, kiedy przesuwamy palcem po ekranie. Korzystając z faktu, że mamy ciekawą, działającą aplikację, poświęćmy teraz chwilę na udostępnienie tej aplikacji dalej po to, by można było zainstalować ją na dowolnym smartfonie. W tym celu kliknijmy w menu Build (1), gdzie znajdziemy dwie funkcje (2):<br />
<br />
1.App (Provide QP code for .apk) - wybranie tej opcji spowoduje wyświetlenie kodu QR i da możliwość załadowania przy pomocy tego kodu samodzielnej aplikacji na telefonie, bez użycia MIT AI2 Companion.<br />
<br />
2.App (save .apk to my computer) - wybranie tego polecenia spowoduje zapisanie aplikacji na komputerze jako plik .apk. Dzięki temu możemy chociażby przesłać aplikację jako załącznik w e-mailu.<br />
<br />
[[Plik:info.png]]Tu grafika!!!</div>M Kelniarzhttp://wiki.mistrzowiekodowania.pl/index.php?title=Scenariusz_2_-_SquashScenariusz 2 - Squash2015-09-14T15:12:46Z<p>M Kelniarz: /* Scenariusz 2 */</p>
<hr />
<div>=Squash w dwóch wariantach=<br />
==Scenariusz 2==<br />
'''Cele:'''<br />
<br />
Stworzymy prostą grę Squash, polegającą na odbijaniu piłeczki paletką, w dwóch wariantach. W ten sposób poznamy m.in. podstawy definiowania interfejsu użytkownika oraz nauczymy się wykonywać proste animacje. Po wykonaniu ćwiczenia będziemy też potrafili sterować obiektami za pomocą przeciągania palcem (pierwszy wariant) po ekranie oraz poprzez przechylanie telefonu (drugi wariant).<br />
<br />
W tej wersji Squasha nie będzie systemu naliczania punktów, jak w tradycyjnej wersji tej gry. W naszej aplikacji na dole będzie umieszczona czerwona linia i jeśli piłka się z nią zderzy, to nastąpi przegrana. Co więcej, gdy nie odbijemy piłeczki i ta spadnie na czerwoną linię, boisko zmieni kolor na szary, co będzie oznaczało koniec gry.<br />
<br />
<ol>'''<li>Rozpoczęcie pracy</li>'''<br />
Wejdźmy na stronę [http://appinventor.mit.edu http://appinventor.mit.edu] i wybierzmy '''Create''', by uruchomić App Inventor. Następnie przejdźmy do zakładki '''My Projects''' (1), gdzie znajdziemy wszystkie nasze projekty - wystarczy tylko zalogować się na odpowiednie konto Google. W celu rozpoczęcia pracy nad nowym projektem kliknijmy na '''Start new project''' (2) i wpiszmy w oknie jego nazwę, np. Squash.<br />
<br />
[[Plik:s2-1.png|800px]]<br />
<br />
Nastąpi teraz automatyczne przejście do okna budowy aplikacji.<br />
<br />
Jak już wspomnieliśmy powyżej - w pierwszym wariancie naszej gry sterowanie paletką będzie odbywało się poprzez przeciąganie palcem po ekranie smartfona, natomiast w drugiej wersji będziemy sterować obracając nim. Obracanie ekranu zgodnie z pozycją telefonu czy tabletu jest domyślnym zachowaniem. Dlatego też w pierwszym wariancie musimy zablokować ekran po to, by ten nie zmieniał swojej orientacji. I od tego właśnie zaczniemy budowę naszej gry.<br />
<br />
Przejdźmy zatem do okna '''Properties''' i dla komponentu '''Screen1,''' w polu '''Screen Orientation''' (1) wybierzmy '''Portrait'''. Dzięki temu nasz ekran zawsze będzie wyświetlany pionowo, niezależnie od tego, w jakiej pozycji znajduje się urządzenie. Dodatkowo w polu '''Title''' wpiszmy tytuł naszego bieżącego komponentu (2). Nazwijmy go '''Squash'''.<br />
<br />
[[Plik:s2-2.png]]<br />
<br />
'''<li>Squash - projektowanie interfejsu</li>'''<br />
Po zablokowaniu obrotu ekranu przejdźmy do dodania komponentów. W naszej aplikacji wykorzystamy trzy elementy - wszystkie znajdziemy w grupie Drawing and Animation. Są to:<br />
<ol>'''<li>Canvas''' ''(zamknięty obszar)'' - jest to komponent ograniczający obszar animacji oraz rysowania. W obszarze tego komponentu poruszają się Ball oraz ImageSprite.</li><br />
'''<li>Ball''' ''(piłka)'' - w naszej aplikacji to po prostu piłka, którą będziemy odbijać za pomocą paletki.</li><br />
'''<li>ImageSprite''' ''(“duszek”)'' - znany ze Scratcha duszek. W naszej aplikacji będzie to paletka. '''Image Sprite''' jest podobny do komponentu '''Ball''', jednak duszek ma kształt prostokąta, a jego tłem może być dowolny plik graficzny, np. w formacie jpg.</li><br />
</ol><br />
<br />
[[Plik:s2-3.png]]<br />
<br />
Jako pierwszy komponent dodajmy '''Canvas''' (1).Przeciągnijmy go na nasz obszar roboczy, czyli '''Viewer'''.<br />
<br />
[[Plik:s2-4.png]]<br />
<br />
Po tym, jak wstawiliśmy komponent '''Canvas''', musimy zmienić jego cechy w oknie '''Properties'''. Zmodyfikujmy dwa atrybuty: '''Width''' ''(szerokość)'' oraz '''Height''' ''(wysokość)''. Dla większości komponentów zarówno szerokość, jak i wysokość można ustawić jako:<br />
<ol>'''<li>Automatic''' ''(automatyczna)'' - system samodzielnie dobierze odpowiednią wartość szerokości i wysokości lub pozostawi je<br />
w standardowym ustawieniu.</li><br />
'''<li>Fill parent''' ''(wypełnienie obiektu nadrzędnego)'' - sprawia, że komponent przejmuje wielkość komponentu nadrzędnego. W przypadku naszej aplikacji zaznaczenie tej opcji sprawiłoby, że obszar '''Canvas1''' przejąłby szerokość i wysokość od komponentu '''Screen1''', co możemy zauważyć na ilustracji powyżej, w oknie '''Components''' - '''Cavas1''' jest obiektem podrzędnym dla '''Screen1'''.</li><br />
<li>'''... pixels - szerokość/wysokość o podanej przez nas liczbie pikseli.</li></ol><br />
Ustawmy zatem dla komponentu '''Canvas1''' wartości '''Width''' jako '''Fill Parent''' (1) oraz '''Height''' jako 300 pikseli(2).<br />
<br />
Teraz czas na kolejne komponenty. Dodajmy '''Ball''' (1) oraz '''ImageSprite''' (2) w dowolne miejsca w obrębie komponentu '''Canvas1'''. Tak jak wspomnieliśmy wcześniej, komponenty '''Ball''' oraz '''ImageSprite''' mogą być umieszczone jedynie na komponencie '''Canvas'''. Nie można umieścić ich poza tym obszarem, bezpośrednio na ekranie telefonu.<br />
<br />
[[Plik:s2-5.png]]<br />
<br />
Po dodaniu dwóch następnych komponentów dostosujmy ich właściwości tak, by odpowiadały naszym założeniom. Zacznijmy od komponentu '''Ball''' - na początek zmieńmy nazwę tego obiektu, klikając '''Rename''' (1) i wpisując '''Piłka''' w polu '''New Name'''. Następnie zmieńmy kilka cech tego komponentu w oknie właściwości, czyli '''Properties''':<br />
<ul><li>'''Heading''' (''kierunek'')- wpiszmy wartość 50 (2)</li><br />
<li>'''Paint Color''' (''kolor'')- wybierzmy '''Blue''' (3)</li><br />
<li>'''Radius''' (''promień'')- promień, czyli po prostu wielkość piłki ustalmy na 5 (4)</li><br />
<li>'''Speed''' (''prędkość'') - tutaj wpiszmy wartość 100 (5)</li><br />
<li>'''Współrzędne X i Y''' - obu współrzędnym nadajmy wartość 100 (6)</li></ul><br />
Inaczej niż w Scratchu, w programie App Inventor komponenty Ball oraz ImageSprite mogą mieć nadaną własną prędkość. W Scratchu efekt ten osiągaliśmy poprzez wielokrotne przesuwanie obiektu. Tutaj wystarczy, że nadamy komponentowi kierunek (Heading) oraz prędkość (Speed), zaś resztę pracy wykona za nas komputer.<br />
<br />
[[Plik:info.png|left]]''Warto zwrócić uwagę na hierarchię komponentów w oknie '''Components'''. Jak pamiętamy, w poprzedniej aplikacji wszystkie komponenty były bezpośrednio podrzędne dla '''Screen1'''. Tutaj podrzędny dla '''Screen1''' jest tylko '''Canvas1''', natomiast pozostałe dwa komponenty ('''Piłka''' oraz '''ImageSprite''') są podrzędne dla komponentu '''Canvas1'''.''<br />
<br />
<br />
[[Plik:s2-6.png]]<br />
<br />
Zmieńmy jeszcze nazwy pozostałych komponentów. '''Canvas1''' przestawmy na '''Boisko''' (1), zaś '''ImageSprite1''' na '''Paletka''' (2).<br />
<br />
[[Plik:s2-7.png]]<br />
<br />
Teraz przejdziemy do następnego kroku, czyli do skonfigurowania paletki.<br />
<br />
[[Plik:s2-8.png]]<br />
<br />
Przejdźmy zatem do zmiany właściwości komponentu o nazwie Paletka. Na początek kliknijmy na paletkę w oknie Components, by ją zaznaczyć - dzięki temu w oknie Properties pojawią się opcje, które pozwolą nam skonfigurować naszą paletkę. Konfigurację jej cech podzielimy na dwa kroki. W pierwszym kroku zadbamy o jej wygląd, zaś w drugim zajmiemy się jej rozmiarem i pozycją.<br />
<ol><li>'''Ustawienie pliku graficznego''' - wygląd paletki będzie wczytany z pliku graficznego, który załadujemy do programu. Paletka bez załadowanej grafiki byłaby przezroczysta, a to zdecydowanie utrudniłoby nam grę. Musimy zatem przygotować dowolny plik graficzny, np. w formacie png i wczytać go do mediów aplikacji, by następnie przypisać do paletki. Kliknijmy więc na '''Upload File''' (1) w oknie '''Media''' i odszukajmy plik, który chcemy wczytać do programu. Następnie przechodzimy do okna '''Properties''' i tam w polu '''Picture''' z rozwijanej listy wybierzmy nasz plik. Plików multimedialnych nie możemy przypisać bezpośrednio do komponentów, stąd w pierwszej kolejności musieliśmy wczytać plik do biblioteki mediów.</li><br />
<li>'''Wielkość i pozycja''' - po tym, jak wczytaliśmy już plik graficzny, przejdźmy do ustawienia pozostałych parametrów. Współrzędną X ustawmy na 100 pikseli, zaś Y - na 270 (3). Następnie parametry '''Width''' (szerokość) na 70 pikseli, a '''Height''' (wysokość) na 20 pikseli.</li></ol><br />
'''<li>Squash - programowanie aplikacji</li>'''<br />
Po tym, jak zakończyliśmy projektowanie interfejsu aplikacji, możemy zająć się stworzeniem odpowiedniego programu. Tym razem zbudowanie poprawnego kodu będzie wymagało od nas większej pracy niż w przypadku poprzedniej aplikacji. Tam wystarczyła nam tylko jedna instrukcja zbudowana z bloków, natomiast tutaj potrzebujemy ich kilka. Przejdźmy więc teraz do zakładki '''Blocks''', a poniżej, krok po kroku, omówimy wszystkie instrukcje.<br />
<br />
'''Zderzenie piłki z paletką i odbicie piłki'''<br />
<br />
Podstawową interakcją w naszej grze jest zderzenie piłeczki z paletką. Gdy do tego dojdzie, piłka musi odbić się od paletki. Musimy zatem ustalić, w jaki sposób ma zachować się piłka i określić, w stosunku do jakiego obiektu to zachowanie ma wystąpić. <br />
<br />
Naszą instrukcję można opisać w następujący sposób: '''Kiedy piłka zderzy się z innym obiektem, to odbij piłkę tak, jakby dotknęła dolnej krawędzi.'''<br />
<br />
[[Plik:s2-9.png]]<br />
<br />
Jak to działa? Przede wszystkim pamiętajmy, że piłka ma swoją prędkość. Gdy poruszająca się '''Piłka''' uderza w krawędź '''Canvas''' (nasze '''Boisko'''), to wywołuje wydarzenie '''EdgeReached''' (''zetknięcie z krawędzią''), a gdy uderza w inny obiekt, to wywołuje wydarzenie '''CollidedWith''' (''zderzenie z...''). My na ekranie mamy tylko jeden obiekt inny niż piłka, czyli paletkę. Zatem gdy piłka uderzy w paletkę, to zostanie uruchomiona akcja '''call[Piłka].Bounce''' (“''odbij piłkę''”). Akcja odbicia musi jeszcze wiedzieć, w którą stronę ma piłkę odbić, gdy ta uderzy w krawędź boczną lub górną i właśnie do tego służy parametr '''edge''' (''krawędź''). Jego wartość ustawiona na -1 powoduje odbicie '''Piłki''' tak, jakby dotknęła dolnej krawędzi (oznaczenia wszystkich krawędzi znajdują<br />
się dalej).<br />
<br />
'''Other''' (''inny obiekt''), można wykorzystać do ustalenia, w który obiekt uderzyła '''Piłka'''. My na ekranie mamy tylko paletkę, więc nie musimy sprawdzać wartości '''other'''.<br />
<br />
Polecenia '''When[Piłka].CollidedWith''' oraz '''Call[Piłka].Bounce''' znajdziemy w grupie '''Piłka''' (1), zaś obiekt z wartością liczbową - w grupie '''Math''' (2).<br />
<br />
[[Plik:s2-10.png]]<br />
<br />
[[Plik:info.png]]''Wszystkie instrukcje, tak jak w Scratchu, podzielone są na kategorie oznaczone odpowiednimi kolorami, co ułatwia nawigację.''<br />
<br />
<br />
'''Numeracja krawędzi ekranu w App Inventorze.'''<br />
Przed momentem skonfigurowaliśmy uderzenie piłki w dolną krawędź ekranu, która jest oznaczona numerem -1. Skąd wziął się właśnie taki numer? Krawędzie w programie App Inventor mają takie oznaczenia, jakie zaprezentowano na poniższej ilustracji. Krawędź północna oznaczona jest numerem 1, północno-wschodnia numerem 2 i w ten sposób docieramy do krawędzi dolnej, która jest oznaczona numerem -1.<br />
<br />
[[Plik:s2-11.png]]<br />
'''Zderzenie piłki z krawędzią i odbicie piłki od krawędzi.'''<br />
Teraz zaprogramujemy wydarzenie zderzenia piłki z krawędzią. Tutaj musimy rozróżnić dwa rodzaje krawędzi - krawędź boczną i krawędź dolną. Jeśli piłka zderzy się z krawędzią boczną, to zostanie odbita, a wartość jej prędkości zwiększy się o 1. Natomiast jeśli zderzy się krawędzią dolną, to nastąpi ponowne rozpoczęcie gry poprzez wywołanie odrębnej procedury, którą przygotujemy.<br />
<br />
[[Plik:Przykład.jpg]]Tu grafika!!!<br />
<br />
'''Wariant pierwszy - poruszanie paletką za pomocą ruchu palca.'''<br />
Kolejnym krokiem będzie zaprogramowanie mechanizmu poruszania paletki poprzez przeciągnięcie palcem. Tutaj wykorzystamy funkcję <b>when[Paletka].Dragged.</b><br />
<br />
'''Przygotowanie procedury reset'''<br />
Teraz przygotujmy procedurę własną reset. Będzie ona uruchamiana zawsze, gdy piłka dotknie dolnej krawędzi oraz zawsze na początku gry. Będą w niej zawarte wszystkie domyślne dla naszej gry parametry, takie jak kolor tła, czy wymiary boiska. Dzięki temu nasza gra po porażce i przy każdym wznowieniu oraz na początku zawsze będzie wyglądała i działała tak samo. W obszarze '''Blocks''' w grupie '''Procedures''' znajdźmy '''to[procedure] do''' i przeciągnijmy ten element do obszaru ''Viewer''. Następnie zmieńmy jego nazwę na ''reset'' i wstawmy poszczególne klocki, jak na poniższej ilustracji.<br />
<br />
Wariant pierwszy - poruszanie paletką za pomocą ruchu palcaKolejnym krokiem będzie zaprogramowanie mechanizmu poruszania paletki poprzez przeciągnięcie palcem. Tutaj wykorzystamy funkcję when[Paletka].Dragged.Przygotowanie procedury resetTeraz przygotujmy procedurę własną reset. Będzie ona uruchamiana zawsze, gdy piłka dotknie dolnej krawędzi oraz zawsze na początku gry. Będą w niej zawarte wszystkie domyślne dla naszej gry parametry, takie jak kolor tła, czy wymiary boiska. Dzięki temu nasza gra po porażce i przy każdym wznowieniu oraz na początku zawsze będzie wyglądała i działała tak samo. W obszarze Blocks w grupie Procedures znajdźmy to[procedure] do i przeciągnijmy ten element do obszaru Viewer. Następnie zmieńmy jego nazwę na reset i wstawmy poszczególne klocki, jak na poniższej ilustracji.<br />
<br />
[[Plik:Przykład.jpg]]Tu grafika!!!<br />
<br />
1. Na początek ustawmy kolor tła naszego Boiska – jeżeli kolor jest szary (czyli jeśli przegraliśmy), to ustawiamy na biały. Dodajmy jeszcze warunek, że jeżeli boisko ma jakikolwiek inny kolor niż szary, to ustawiamy na biały - o tym za chwilę.<br />
2. Następnie ustawmy parametry początkowe Piłki – współrzędne X i Y, kierunek ('''Heading''') oraz prędkość piłki ('''Speed'''). Dzięki temu na początku gry piłka zawsze będzie w tej samej pozycji.<br />
3. Na samym dole, wzdłuż dolnej krawędzi Boiska (linia x1) rysujemy linię (w kolorze i szerokości ustawionej w procedurze '''when[Screen1].Initialize''', którą stworzymy za chwilę). Linia ta musi być za każdym razem rysowana ponownie, ponieważ ustawienie tła Boiska (na szare lub białe) powyżej powoduje jej usunięcie (wyczyszczenie całości Boiska).</div>M Kelniarzhttp://wiki.mistrzowiekodowania.pl/index.php?title=Scenariusz_2_-_SquashScenariusz 2 - Squash2015-09-14T15:08:27Z<p>M Kelniarz: /* Scenariusz 2 */</p>
<hr />
<div>=Squash w dwóch wariantach=<br />
==Scenariusz 2==<br />
'''Cele:'''<br />
<br />
Stworzymy prostą grę Squash, polegającą na odbijaniu piłeczki paletką, w dwóch wariantach. W ten sposób poznamy m.in. podstawy definiowania interfejsu użytkownika oraz nauczymy się wykonywać proste animacje. Po wykonaniu ćwiczenia będziemy też potrafili sterować obiektami za pomocą przeciągania palcem (pierwszy wariant) po ekranie oraz poprzez przechylanie telefonu (drugi wariant).<br />
<br />
W tej wersji Squasha nie będzie systemu naliczania punktów, jak w tradycyjnej wersji tej gry. W naszej aplikacji na dole będzie umieszczona czerwona linia i jeśli piłka się z nią zderzy, to nastąpi przegrana. Co więcej, gdy nie odbijemy piłeczki i ta spadnie na czerwoną linię, boisko zmieni kolor na szary, co będzie oznaczało koniec gry.<br />
<br />
<ol>'''<li>Rozpoczęcie pracy</li>'''<br />
Wejdźmy na stronę [http://appinventor.mit.edu http://appinventor.mit.edu] i wybierzmy '''Create''', by uruchomić App Inventor. Następnie przejdźmy do zakładki '''My Projects''' (1), gdzie znajdziemy wszystkie nasze projekty - wystarczy tylko zalogować się na odpowiednie konto Google. W celu rozpoczęcia pracy nad nowym projektem kliknijmy na '''Start new project''' (2) i wpiszmy w oknie jego nazwę, np. Squash.<br />
<br />
[[Plik:s2-1.png|800px]]<br />
<br />
Nastąpi teraz automatyczne przejście do okna budowy aplikacji.<br />
<br />
Jak już wspomnieliśmy powyżej - w pierwszym wariancie naszej gry sterowanie paletką będzie odbywało się poprzez przeciąganie palcem po ekranie smartfona, natomiast w drugiej wersji będziemy sterować obracając nim. Obracanie ekranu zgodnie z pozycją telefonu czy tabletu jest domyślnym zachowaniem. Dlatego też w pierwszym wariancie musimy zablokować ekran po to, by ten nie zmieniał swojej orientacji. I od tego właśnie zaczniemy budowę naszej gry.<br />
<br />
Przejdźmy zatem do okna '''Properties''' i dla komponentu '''Screen1,''' w polu '''Screen Orientation''' (1) wybierzmy '''Portrait'''. Dzięki temu nasz ekran zawsze będzie wyświetlany pionowo, niezależnie od tego, w jakiej pozycji znajduje się urządzenie. Dodatkowo w polu '''Title''' wpiszmy tytuł naszego bieżącego komponentu (2). Nazwijmy go '''Squash'''.<br />
<br />
[[Plik:s2-2.png]]<br />
<br />
'''<li>Squash - projektowanie interfejsu</li>'''<br />
Po zablokowaniu obrotu ekranu przejdźmy do dodania komponentów. W naszej aplikacji wykorzystamy trzy elementy - wszystkie znajdziemy w grupie Drawing and Animation. Są to:<br />
<ol>'''<li>Canvas''' ''(zamknięty obszar)'' - jest to komponent ograniczający obszar animacji oraz rysowania. W obszarze tego komponentu poruszają się Ball oraz ImageSprite.</li><br />
'''<li>Ball''' ''(piłka)'' - w naszej aplikacji to po prostu piłka, którą będziemy odbijać za pomocą paletki.</li><br />
'''<li>ImageSprite''' ''(“duszek”)'' - znany ze Scratcha duszek. W naszej aplikacji będzie to paletka. '''Image Sprite''' jest podobny do komponentu '''Ball''', jednak duszek ma kształt prostokąta, a jego tłem może być dowolny plik graficzny, np. w formacie jpg.</li><br />
</ol><br />
<br />
[[Plik:s2-3.png]]<br />
<br />
Jako pierwszy komponent dodajmy '''Canvas''' (1).Przeciągnijmy go na nasz obszar roboczy, czyli '''Viewer'''.<br />
<br />
[[Plik:s2-4.png]]<br />
<br />
Po tym, jak wstawiliśmy komponent '''Canvas''', musimy zmienić jego cechy w oknie '''Properties'''. Zmodyfikujmy dwa atrybuty: '''Width''' ''(szerokość)'' oraz '''Height''' ''(wysokość)''. Dla większości komponentów zarówno szerokość, jak i wysokość można ustawić jako:<br />
<ol>'''<li>Automatic''' ''(automatyczna)'' - system samodzielnie dobierze odpowiednią wartość szerokości i wysokości lub pozostawi je<br />
w standardowym ustawieniu.</li><br />
'''<li>Fill parent''' ''(wypełnienie obiektu nadrzędnego)'' - sprawia, że komponent przejmuje wielkość komponentu nadrzędnego. W przypadku naszej aplikacji zaznaczenie tej opcji sprawiłoby, że obszar '''Canvas1''' przejąłby szerokość i wysokość od komponentu '''Screen1''', co możemy zauważyć na ilustracji powyżej, w oknie '''Components''' - '''Cavas1''' jest obiektem podrzędnym dla '''Screen1'''.</li><br />
<li>'''... pixels - szerokość/wysokość o podanej przez nas liczbie pikseli.</li></ol><br />
Ustawmy zatem dla komponentu '''Canvas1''' wartości '''Width''' jako '''Fill Parent''' (1) oraz '''Height''' jako 300 pikseli(2).<br />
<br />
Teraz czas na kolejne komponenty. Dodajmy '''Ball''' (1) oraz '''ImageSprite''' (2) w dowolne miejsca w obrębie komponentu '''Canvas1'''. Tak jak wspomnieliśmy wcześniej, komponenty '''Ball''' oraz '''ImageSprite''' mogą być umieszczone jedynie na komponencie '''Canvas'''. Nie można umieścić ich poza tym obszarem, bezpośrednio na ekranie telefonu.<br />
<br />
[[Plik:s2-5.png]]<br />
<br />
Po dodaniu dwóch następnych komponentów dostosujmy ich właściwości tak, by odpowiadały naszym założeniom. Zacznijmy od komponentu '''Ball''' - na początek zmieńmy nazwę tego obiektu, klikając '''Rename''' (1) i wpisując '''Piłka''' w polu '''New Name'''. Następnie zmieńmy kilka cech tego komponentu w oknie właściwości, czyli '''Properties''':<br />
<ul><li>'''Heading''' (''kierunek'')- wpiszmy wartość 50 (2)</li><br />
<li>'''Paint Color''' (''kolor'')- wybierzmy '''Blue''' (3)</li><br />
<li>'''Radius''' (''promień'')- promień, czyli po prostu wielkość piłki ustalmy na 5 (4)</li><br />
<li>'''Speed''' (''prędkość'') - tutaj wpiszmy wartość 100 (5)</li><br />
<li>'''Współrzędne X i Y''' - obu współrzędnym nadajmy wartość 100 (6)</li></ul><br />
Inaczej niż w Scratchu, w programie App Inventor komponenty Ball oraz ImageSprite mogą mieć nadaną własną prędkość. W Scratchu efekt ten osiągaliśmy poprzez wielokrotne przesuwanie obiektu. Tutaj wystarczy, że nadamy komponentowi kierunek (Heading) oraz prędkość (Speed), zaś resztę pracy wykona za nas komputer.<br />
<br />
[[Plik:info.png|left]]''Warto zwrócić uwagę na hierarchię komponentów w oknie '''Components'''. Jak pamiętamy, w poprzedniej aplikacji wszystkie komponenty były bezpośrednio podrzędne dla '''Screen1'''. Tutaj podrzędny dla '''Screen1''' jest tylko '''Canvas1''', natomiast pozostałe dwa komponenty ('''Piłka''' oraz '''ImageSprite''') są podrzędne dla komponentu '''Canvas1'''.''<br />
<br />
<br />
[[Plik:s2-6.png]]<br />
<br />
Zmieńmy jeszcze nazwy pozostałych komponentów. '''Canvas1''' przestawmy na '''Boisko''' (1), zaś '''ImageSprite1''' na '''Paletka''' (2).<br />
<br />
[[Plik:s2-7.png]]<br />
<br />
Teraz przejdziemy do następnego kroku, czyli do skonfigurowania paletki.<br />
<br />
[[Plik:s2-8.png]]<br />
<br />
Przejdźmy zatem do zmiany właściwości komponentu o nazwie Paletka. Na początek kliknijmy na paletkę w oknie Components, by ją zaznaczyć - dzięki temu w oknie Properties pojawią się opcje, które pozwolą nam skonfigurować naszą paletkę. Konfigurację jej cech podzielimy na dwa kroki. W pierwszym kroku zadbamy o jej wygląd, zaś w drugim zajmiemy się jej rozmiarem i pozycją.<br />
<ol><li>'''Ustawienie pliku graficznego''' - wygląd paletki będzie wczytany z pliku graficznego, który załadujemy do programu. Paletka bez załadowanej grafiki byłaby przezroczysta, a to zdecydowanie utrudniłoby nam grę. Musimy zatem przygotować dowolny plik graficzny, np. w formacie png i wczytać go do mediów aplikacji, by następnie przypisać do paletki. Kliknijmy więc na '''Upload File''' (1) w oknie '''Media''' i odszukajmy plik, który chcemy wczytać do programu. Następnie przechodzimy do okna '''Properties''' i tam w polu '''Picture''' z rozwijanej listy wybierzmy nasz plik. Plików multimedialnych nie możemy przypisać bezpośrednio do komponentów, stąd w pierwszej kolejności musieliśmy wczytać plik do biblioteki mediów.</li><br />
<li>'''Wielkość i pozycja''' - po tym, jak wczytaliśmy już plik graficzny, przejdźmy do ustawienia pozostałych parametrów. Współrzędną X ustawmy na 100 pikseli, zaś Y - na 270 (3). Następnie parametry '''Width''' (szerokość) na 70 pikseli, a '''Height''' (wysokość) na 20 pikseli.</li></ol><br />
'''<li>Squash - programowanie aplikacji</li>'''<br />
Po tym, jak zakończyliśmy projektowanie interfejsu aplikacji, możemy zająć się stworzeniem odpowiedniego programu. Tym razem zbudowanie poprawnego kodu będzie wymagało od nas większej pracy niż w przypadku poprzedniej aplikacji. Tam wystarczyła nam tylko jedna instrukcja zbudowana z bloków, natomiast tutaj potrzebujemy ich kilka. Przejdźmy więc teraz do zakładki '''Blocks''', a poniżej, krok po kroku, omówimy wszystkie instrukcje.<br />
<br />
'''Zderzenie piłki z paletką i odbicie piłki'''<br />
<br />
Podstawową interakcją w naszej grze jest zderzenie piłeczki z paletką. Gdy do tego dojdzie, piłka musi odbić się od paletki. Musimy zatem ustalić, w jaki sposób ma zachować się piłka i określić, w stosunku do jakiego obiektu to zachowanie ma wystąpić. <br />
<br />
Naszą instrukcję można opisać w następujący sposób: '''Kiedy piłka zderzy się z innym obiektem, to odbij piłkę tak, jakby dotknęła dolnej krawędzi.'''<br />
<br />
[[Plik:s2-9.png]]<br />
<br />
Jak to działa? Przede wszystkim pamiętajmy, że piłka ma swoją prędkość. Gdy poruszająca się '''Piłka''' uderza w krawędź '''Canvas''' (nasze '''Boisko'''), to wywołuje wydarzenie '''EdgeReached''' (''zetknięcie z krawędzią''), a gdy uderza w inny obiekt, to wywołuje wydarzenie '''CollidedWith''' (''zderzenie z...''). My na ekranie mamy tylko jeden obiekt inny niż piłka, czyli paletkę. Zatem gdy piłka uderzy w paletkę, to zostanie uruchomiona akcja '''call[Piłka].Bounce''' (“''odbij piłkę''”). Akcja odbicia musi jeszcze wiedzieć, w którą stronę ma piłkę odbić, gdy ta uderzy w krawędź boczną lub górną i właśnie do tego służy parametr '''edge''' (''krawędź''). Jego wartość ustawiona na -1 powoduje odbicie '''Piłki''' tak, jakby dotknęła dolnej krawędzi (oznaczenia wszystkich krawędzi znajdują<br />
się dalej).<br />
<br />
'''Other''' (''inny obiekt''), można wykorzystać do ustalenia, w który obiekt uderzyła '''Piłka'''. My na ekranie mamy tylko paletkę, więc nie musimy sprawdzać wartości '''other'''.<br />
<br />
Polecenia '''When[Piłka].CollidedWith''' oraz '''Call[Piłka].Bounce''' znajdziemy w grupie '''Piłka''' (1), zaś obiekt z wartością liczbową - w grupie '''Math''' (2).<br />
<br />
[[Plik:s2-10.png]]<br />
<br />
[[Plik:info.png]]''Wszystkie instrukcje, tak jak w Scratchu, podzielone są na kategorie oznaczone odpowiednimi kolorami, co ułatwia nawigację.''<br />
<br />
<br />
'''Numeracja krawędzi ekranu w App Inventorze.'''<br />
Przed momentem skonfigurowaliśmy uderzenie piłki w dolną krawędź ekranu, która jest oznaczona numerem -1. Skąd wziął się właśnie taki numer? Krawędzie w programie App Inventor mają takie oznaczenia, jakie zaprezentowano na poniższej ilustracji. Krawędź północna oznaczona jest numerem 1, północno-wschodnia numerem 2 i w ten sposób docieramy do krawędzi dolnej, która jest oznaczona numerem -1.<br />
<br />
[[Plik:s2-11.png]]<br />
'''Zderzenie piłki z krawędzią i odbicie piłki od krawędzi.'''<br />
Teraz zaprogramujemy wydarzenie zderzenia piłki z krawędzią. Tutaj musimy rozróżnić dwa rodzaje krawędzi - krawędź boczną i krawędź dolną. Jeśli piłka zderzy się z krawędzią boczną, to zostanie odbita, a wartość jej prędkości zwiększy się o 1. Natomiast jeśli zderzy się krawędzią dolną, to nastąpi ponowne rozpoczęcie gry poprzez wywołanie odrębnej procedury, którą przygotujemy.<br />
<br />
[[Plik:Przykład.jpg]]Tu grafika!!!<br />
<br />
'''Wariant pierwszy - poruszanie paletką za pomocą ruchu palca.'''<br />
Kolejnym krokiem będzie zaprogramowanie mechanizmu poruszania paletki poprzez przeciągnięcie palcem. Tutaj wykorzystamy funkcję <b>when[Paletka].Dragged.</b><br />
<br />
'''Przygotowanie procedury reset'''<br />
Teraz przygotujmy procedurę własną reset. Będzie ona uruchamiana zawsze, gdy piłka dotknie dolnej krawędzi oraz zawsze na początku gry. Będą w niej zawarte wszystkie domyślne dla naszej gry parametry, takie jak kolor tła, czy wymiary boiska. Dzięki temu nasza gra po porażce i przy każdym wznowieniu oraz na początku zawsze będzie wyglądała i działała tak samo. W obszarze '''Blocks''' w grupie '''Procedures''' znajdźmy '''to[procedure] do''' i przeciągnijmy ten element do obszaru ''Viewer''. Następnie zmieńmy jego nazwę na ''reset'' i wstawmy poszczególne klocki, jak na poniższej ilustracji.<br />
<br />
Wariant pierwszy - poruszanie paletką za pomocą ruchu palcaKolejnym krokiem będzie zaprogramowanie mechanizmu poruszania paletki poprzez przeciągnięcie palcem. Tutaj wykorzystamy funkcję when[Paletka].Dragged.Przygotowanie procedury resetTeraz przygotujmy procedurę własną reset. Będzie ona uruchamiana zawsze, gdy piłka dotknie dolnej krawędzi oraz zawsze na początku gry. Będą w niej zawarte wszystkie domyślne dla naszej gry parametry, takie jak kolor tła, czy wymiary boiska. Dzięki temu nasza gra po porażce i przy każdym wznowieniu oraz na początku zawsze będzie wyglądała i działała tak samo. W obszarze Blocks w grupie Procedures znajdźmy to[procedure] do i przeciągnijmy ten element do obszaru Viewer. Następnie zmieńmy jego nazwę na reset i wstawmy poszczególne klocki, jak na poniższej ilustracji.</div>M Kelniarzhttp://wiki.mistrzowiekodowania.pl/index.php?title=Strona_g%C5%82%C3%B3wnaStrona główna2015-09-14T14:26:07Z<p>M Kelniarz: /* Projekty */</p>
<hr />
<div>[[Plik:Logo_Mistrzowie.png|center]]<br />
<br />
<br />
<br />
'''Witaj na stronie ze scenariuszami!'''<br />
<br />
'''Wszystkie scenariusze w wersji .pdf mozesz znaleźc [https://www.dropbox.com/sh/9e29fdqcgseh65w/AABm12kGHhxg_fzzspVLyac8a?dl=0 '''TUTAJ''']'''<br />
<br />
==Scratch==<br />
===Scenariusze===<br />
<br />
* [[Quiz o Scratch]] <br />
<br />
''' Scenariusze dla klas 4-6 szkoły podstawowej'''<br />
<br />
''' Scenarios dedicated to primary school learners, 4th - 6th grade (basic level)'''<br />
<br />
{| class="wikitable" border="0"<br />
|-<br />
! Wersja polska<br />
! English version<br />
|-<br />
|<br />
* [[Wprowadzenie 1 - Korzystanie z konta Scratch]]<br />
* [[Wprowadzenie 2 - Opis środowiska Scratch]]<br />
* [[Wprowadzenie 3 - Słowniczek podstawowych bloków]]<br />
* [[Moduł 1 - "Pierwsze kroki w Scratch'u"]]<br />
* [[Moduł 2 - "Kot goni mysz"]]<br />
* [[Moduł 3 - "Kot w labiryncie"]]<br />
* [[Moduł 4 - "Kot zastawia pułapkę na mysz"]]<br />
* [[Moduł 5 - "Gra zręcznościowa - odbijanie piłeczki"]]<br />
* [[Moduł 6 - "Gra logiczna - zgadywanie liczby"]]<br />
* [[Moduł 7 - „Zawody lekkoatletyczne duszków”]]<br />
* [[Moduł 8 - „Multimedialna kartka świąteczna”]]<br />
|<br />
* [[Introduction 1 - Using a Scratch account]]<br />
* [[Introduction 2 - Description of the Scratch environment]]<br />
* [[Introduction 3 - Glossary of basic Scratch 2.0 blocks]]<br />
* [[Module 1 - Getting started in Scratch]]<br />
* [[Module 2 - The “Cat Chasing a Mouse” Project]]<br />
* [[Module 3 - The “Cat in a Maze” Project ]]<br />
* [[Module 4 - The “Cat Sets a Trap for the Mouse” Project]]<br />
* [[Module 5 - The “Bounce the Ball Arcade Game” Project]]<br />
* [[Module 6 - The “Guess the NumberLogic Game” Project]]<br />
* [[Module 7 - The “Sprites’ Track and Field Competition” Project]]<br />
* [[Module 8 - The “Multimedia Christmas Card” Project]]<br />
|}<br />
<br />
<br />
<br />
{| class="wikitable" border="0"<br />
|-<br />
! Szkoła podstawowa (klasy 1-3)<br />
! Szkoła podstawowa (klasy 4-6)<br />
! Gimnazjum<br />
|-<br />
|<br />
* [[Cykl życia motyla]]<br />
* [[Animacja poklatkowa: wzrost kwiatka]]<br />
* [[Interpretacja wiersza]]<br />
* [[Literowanie]]<br />
* [[Aplikacja do rysowania]]<br />
* [[Sumowanie]]<br />
* [[Segregacja odpadów]]<br />
* [[Gra kamień-nożyce-papier]]<br />
* [[Wyścigówka (wersja A)]]<br />
|<br />
* [[Interaktywna mapa Polski (punkty)]]<br />
* [[Animacja - układ pokarmowy]]<br />
* [[Maszynka losująca]]<br />
* [[Czasomierz lekcyjny]]<br />
* [[Arkanoid]]<br />
* [[Generator wielokątów]]<br />
* [[Wyścigówka (wersja B)]]<br />
* [[Gra platformowa]]<br />
|<br />
* [[Interaktywna mapa Polski (województwa)]]<br />
* [[Animacja - układ pokarmowy (wersja B)]]<br />
* [[Maszynka losująca (wersja B)]]<br />
* [[Czasomierz lekcyjny]]<br />
* [[Arkanoid (wersja B)]]<br />
* [[Labirynt]]<br />
* [[Generator wielokątów]]<br />
* [[Wyścigówka (wersja C)]]<br />
* [[Gra platformowa (wersja z przesuwanym tłem)]]<br />
|}<br />
<br />
==App Inventor==<br />
===Scenariusze===<br />
*[[Wprowadzenie]]<br />
*[[Scenariusz 1 - Kalkulator prosty]]<br />
*[[Scenariusz 2 - Squash]]<br />
*[[Scenariusz 3 - Rysowanie palcem po ekranie]]<br />
*[[Scenariusz 4 - Spaceshooter]]<br />
*[[Scenariusz 5 - Chat Bluetooth]]<br />
*[[Scenariusz 6 - Tablica ogłoszeń]]<br />
*[[Scenariusz 7 - Kalkulator (prawie) pełny]]<br />
<br />
===Tłumaczenia===<br />
Tłumaczenia tutoriali ze strony [http://appinventor.mit.edu/explore/ai2/support/blocks.html MIT App Inventor]<br />
<br />
*[[Jak podłączyć telefon lub tablet przez WiFi?]]<br />
*[[Hello Purr]]<br />
*[[Bouncing Ball]]<br />
*[[MoleMash]]<br />
*[[Magic Ball]]<br />
*[[QuizMe]]<br />
<br />
===Opis bloków===<br />
Opisy przygotowane na podstawie materiałów ze strony [http://appinventor.mit.edu/explore/ai2/tutorials.html MIT App Inventor]<br />
<br />
* [[Bloki kontrolne]]<br />
* [[Bloki logiczne]]<br />
* [[Bloki matematyczne]]<br />
* [[Bloki tekstowe]]<br />
* [[Bloki listowe]]<br />
* [[Bloki kolorów]]<br />
* [[Bloki zmiennych]]<br />
* [[Bloki procedur]]<br />
<br />
===Projekty===<br />
Pliki '''.aia''' i '''.apk''' do ewentualnego wykorzystania w trakcie zajęć App Inventor.<br />
<br />
*'''"Tylko media"''' - projekt bez ''layout'' i kodu - wczytane pliki mediów (grafika, dźwięk);<br />
*'''"Szablon"''' - projekt z plikami mediów i ''layoutem'' - bez kodu;<br />
*'''"Kod źródłowy"''' - kompletny plik .aia;<br />
*'''"Aplikacja"''' - plik instalacyjny (.apk);<br />
<br />
{| class="wikitable" border="0"<br />
|-<br />
! Projekt<br />
! Tylko media<br />
! Szablon<br />
! Kod źródłowy<br />
! Aplikacja<br />
|-<br />
|<br />
* Hello ''imię''<br />
* Nie klikaj<br />
* Rysowanie<br />
* Spaceshooter<br />
* Zgadnij liczbę<br />
* Kalkulator<br />
* zgadywanka Animals<br />
* Kamień, papier, nożyce<br />
|<br />
* <br />
* <br />
* <br />
* <br />
* <br />
* <br />
* [https://www.dropbox.com/s/59zh3exj1s3pzws/zgadywanka_media.aia?dl=1 plik '''.aia''']<br />
* [https://www.dropbox.com/s/mwjbvs3sc1fwokw/pnk_v2a_media.aia?dl=1 plik '''.aia''']<br />
|<br />
* <br />
* <br />
* [https://www.dropbox.com/s/wz45i7t7d0y5r5z/rysowanie_szablon.aia?dl=1 plik '''.aia''']<br />
* <br />
* [https://www.dropbox.com/s/5swpsr6iin6h2hv/zgadnij_liczbe_szablon.aia?dl=1 plik '''.aia''']<br />
* [https://www.dropbox.com/s/742kfkifl4ojwcb/kalkulator_prosty_szablon.aia?dl=1 plik '''.aia''']<br />
* [https://www.dropbox.com/s/48h970gd77k7z92/zgadywanka_szablon.aia?dl=1 plik '''.aia''']<br />
* [https://www.dropbox.com/s/ptxr4qnbez9pukh/pnk_v2a_szablon.aia?dl=1 plik '''.aia''']<br />
|<br />
* [https://www.dropbox.com/s/7zml10v5mwz4080/helloimie.aia?dl=1 plik '''.aia''']<br />
* [https://www.dropbox.com/s/vc9u7czby6o4raa/nie_klikaj.aia?dl=1 plik '''.aia''']<br />
* [https://www.dropbox.com/s/jzopcfcazrxnlkm/rysowanie_3.aia?dl=1 plik '''.aia''']<br />
* [https://www.dropbox.com/s/gn1nzpu9mq0knrp/spaceshooter.aia?dl=1 plik '''.aia''']<br />
* [https://www.dropbox.com/s/8wa7uh4ebyws0xr/zgadnij_liczbe.aia?dl=1 plik '''.aia''']<br />
* [https://www.dropbox.com/s/biq1732dpak7afu/kalkulator_prosty_v2a.aia?dl=1 plik '''.aia''']<br />
* [https://www.dropbox.com/s/qx0fenr2ij7g78l/zgadywanka_Animals.aia?dl=1 plik '''.aia''']<br />
* [https://www.dropbox.com/s/27c4adazfeepdit/pnk_v2a.aia?dl=1 plik '''.aia''']<br />
|<br />
* [https://www.dropbox.com/s/bzapjq7kmumix44/helloimie.apk?dl=1 plik '''.apk''']<br />
* [https://www.dropbox.com/s/8w90d4cpyhbwq1o/nie_klikaj.apk?dl=1 plik '''.apk''']<br />
* [https://www.dropbox.com/s/5l48hq3vmevdvre/rysowanie_3.apk?dl=1 plik '''.apk''']<br />
* [https://www.dropbox.com/s/uwu9db3uikwdeeq/spaceshooter.apk?dl=1 plik '''.apk''']<br />
* [https://www.dropbox.com/s/trb14osjpuzc30l/zgadnij_liczbe.apk?dl=1 plik '''.apk''']<br />
* [https://www.dropbox.com/s/vmc75o5pplzy6e2/kalkulator.apk?dl=1 plik '''.apk''']<br />
* [https://www.dropbox.com/s/ujy430f4537f160/zgadywanka_animals.apk?dl=1 plik '''.apk''']<br />
* [https://www.dropbox.com/s/9muj3nooi9le27o/pnk_v2a.apk?dl=1 plik '''.apk''']<br />
|}</div>M Kelniarzhttp://wiki.mistrzowiekodowania.pl/index.php?title=Strona_g%C5%82%C3%B3wnaStrona główna2015-09-14T14:16:25Z<p>M Kelniarz: /* Projekty */</p>
<hr />
<div>[[Plik:Logo_Mistrzowie.png|center]]<br />
<br />
<br />
<br />
'''Witaj na stronie ze scenariuszami!'''<br />
<br />
'''Wszystkie scenariusze w wersji .pdf mozesz znaleźc [https://www.dropbox.com/sh/9e29fdqcgseh65w/AABm12kGHhxg_fzzspVLyac8a?dl=0 '''TUTAJ''']'''<br />
<br />
==Scratch==<br />
===Scenariusze===<br />
<br />
* [[Quiz o Scratch]] <br />
<br />
''' Scenariusze dla klas 4-6 szkoły podstawowej'''<br />
<br />
''' Scenarios dedicated to primary school learners, 4th - 6th grade (basic level)'''<br />
<br />
{| class="wikitable" border="0"<br />
|-<br />
! Wersja polska<br />
! English version<br />
|-<br />
|<br />
* [[Wprowadzenie 1 - Korzystanie z konta Scratch]]<br />
* [[Wprowadzenie 2 - Opis środowiska Scratch]]<br />
* [[Wprowadzenie 3 - Słowniczek podstawowych bloków]]<br />
* [[Moduł 1 - "Pierwsze kroki w Scratch'u"]]<br />
* [[Moduł 2 - "Kot goni mysz"]]<br />
* [[Moduł 3 - "Kot w labiryncie"]]<br />
* [[Moduł 4 - "Kot zastawia pułapkę na mysz"]]<br />
* [[Moduł 5 - "Gra zręcznościowa - odbijanie piłeczki"]]<br />
* [[Moduł 6 - "Gra logiczna - zgadywanie liczby"]]<br />
* [[Moduł 7 - „Zawody lekkoatletyczne duszków”]]<br />
* [[Moduł 8 - „Multimedialna kartka świąteczna”]]<br />
|<br />
* [[Introduction 1 - Using a Scratch account]]<br />
* [[Introduction 2 - Description of the Scratch environment]]<br />
* [[Introduction 3 - Glossary of basic Scratch 2.0 blocks]]<br />
* [[Module 1 - Getting started in Scratch]]<br />
* [[Module 2 - The “Cat Chasing a Mouse” Project]]<br />
* [[Module 3 - The “Cat in a Maze” Project ]]<br />
* [[Module 4 - The “Cat Sets a Trap for the Mouse” Project]]<br />
* [[Module 5 - The “Bounce the Ball Arcade Game” Project]]<br />
* [[Module 6 - The “Guess the NumberLogic Game” Project]]<br />
* [[Module 7 - The “Sprites’ Track and Field Competition” Project]]<br />
* [[Module 8 - The “Multimedia Christmas Card” Project]]<br />
|}<br />
<br />
<br />
<br />
{| class="wikitable" border="0"<br />
|-<br />
! Szkoła podstawowa (klasy 1-3)<br />
! Szkoła podstawowa (klasy 4-6)<br />
! Gimnazjum<br />
|-<br />
|<br />
* [[Cykl życia motyla]]<br />
* [[Animacja poklatkowa: wzrost kwiatka]]<br />
* [[Interpretacja wiersza]]<br />
* [[Literowanie]]<br />
* [[Aplikacja do rysowania]]<br />
* [[Sumowanie]]<br />
* [[Segregacja odpadów]]<br />
* [[Gra kamień-nożyce-papier]]<br />
* [[Wyścigówka (wersja A)]]<br />
|<br />
* [[Interaktywna mapa Polski (punkty)]]<br />
* [[Animacja - układ pokarmowy]]<br />
* [[Maszynka losująca]]<br />
* [[Czasomierz lekcyjny]]<br />
* [[Arkanoid]]<br />
* [[Generator wielokątów]]<br />
* [[Wyścigówka (wersja B)]]<br />
* [[Gra platformowa]]<br />
|<br />
* [[Interaktywna mapa Polski (województwa)]]<br />
* [[Animacja - układ pokarmowy (wersja B)]]<br />
* [[Maszynka losująca (wersja B)]]<br />
* [[Czasomierz lekcyjny]]<br />
* [[Arkanoid (wersja B)]]<br />
* [[Labirynt]]<br />
* [[Generator wielokątów]]<br />
* [[Wyścigówka (wersja C)]]<br />
* [[Gra platformowa (wersja z przesuwanym tłem)]]<br />
|}<br />
<br />
==App Inventor==<br />
===Scenariusze===<br />
*[[Wprowadzenie]]<br />
*[[Scenariusz 1 - Kalkulator prosty]]<br />
*[[Scenariusz 2 - Squash]]<br />
*[[Scenariusz 3 - Rysowanie palcem po ekranie]]<br />
*[[Scenariusz 4 - Spaceshooter]]<br />
*[[Scenariusz 5 - Chat Bluetooth]]<br />
*[[Scenariusz 6 - Tablica ogłoszeń]]<br />
*[[Scenariusz 7 - Kalkulator (prawie) pełny]]<br />
<br />
===Tłumaczenia===<br />
Tłumaczenia tutoriali ze strony [http://appinventor.mit.edu/explore/ai2/support/blocks.html MIT App Inventor]<br />
<br />
*[[Jak podłączyć telefon lub tablet przez WiFi?]]<br />
*[[Hello Purr]]<br />
*[[Bouncing Ball]]<br />
*[[MoleMash]]<br />
*[[Magic Ball]]<br />
*[[QuizMe]]<br />
<br />
===Opis bloków===<br />
Opisy przygotowane na podstawie materiałów ze strony [http://appinventor.mit.edu/explore/ai2/tutorials.html MIT App Inventor]<br />
<br />
* [[Bloki kontrolne]]<br />
* [[Bloki logiczne]]<br />
* [[Bloki matematyczne]]<br />
* [[Bloki tekstowe]]<br />
* [[Bloki listowe]]<br />
* [[Bloki kolorów]]<br />
* [[Bloki zmiennych]]<br />
* [[Bloki procedur]]<br />
<br />
===Projekty===<br />
Pliki '''.aia''' i '''.apk''' do ewentualnego wykorzystania w trakcie zajęć App Inventor.<br />
<br />
*'''"Tylko media"''' - projekt bez ''layout'' i kodu - wczytane pliki mediów (grafika, dźwięk);<br />
*'''"Szablon"''' - projekt z plikami mediów i ''layoutem'' - bez kodu;<br />
*'''"Kod źródłowy"''' - kompletny plik .aia;<br />
*'''"Aplikacja"''' - plik instalacyjny (.apk);<br />
<br />
{| class="wikitable" border="0"<br />
|-<br />
! Projekt<br />
! Tylko media<br />
! Szablon<br />
! Kod źródłowy<br />
! Aplikacja<br />
|-<br />
|<br />
* Hello ''imię''<br />
* Nie klikaj<br />
* Rysowanie<br />
* Spaceshooter<br />
* Zgadnij liczbę<br />
* Kalkulator<br />
* zgadywanka Animals<br />
* Kamień, papier, nożyce<br />
|<br />
* <br />
* <br />
* <br />
* <br />
* <br />
* <br />
* [https://www.dropbox.com/s/59zh3exj1s3pzws/zgadywanka_media.aia?dl=1 plik '''.aia''']<br />
* [https://www.dropbox.com/s/mwjbvs3sc1fwokw/pnk_v2a_media.aia?dl=1 plik '''.aia''']<br />
|<br />
* <br />
* <br />
* [https://www.dropbox.com/s/wz45i7t7d0y5r5z/rysowanie_szablon.aia?dl=1 plik '''.aia''']<br />
* <br />
* [https://www.dropbox.com/s/5swpsr6iin6h2hv/zgadnij_liczbe_szablon.aia?dl=1 plik '''.aia''']<br />
* [https://www.dropbox.com/s/742kfkifl4ojwcb/kalkulator_prosty_szablon.aia?dl=1 plik '''.aia''']<br />
* [https://www.dropbox.com/s/48h970gd77k7z92/zgadywanka_szablon.aia?dl=1 plik '''.aia''']<br />
* [https://www.dropbox.com/s/ptxr4qnbez9pukh/pnk_v2a_szablon.aia?dl=1 plik '''.aia''']<br />
|<br />
* [https://www.dropbox.com/s/7zml10v5mwz4080/helloimie.aia?dl=1 plik '''.aia''']<br />
* [https://www.dropbox.com/s/vc9u7czby6o4raa/nie_klikaj.aia?dl=1 plik '''.aia''']<br />
* [https://www.dropbox.com/s/jzopcfcazrxnlkm/rysowanie_3.aia?dl=1 plik '''.aia''']<br />
* [https://www.dropbox.com/s/gn1nzpu9mq0knrp/spaceshooter.aia?dl=1 plik '''.aia''']<br />
* [https://www.dropbox.com/s/8wa7uh4ebyws0xr/zgadnij_liczbe.aia?dl=1 plik '''.aia''']<br />
* [https://www.dropbox.com/s/biq1732dpak7afu/kalkulator_prosty_v2a.aia?dl=1 plik '''.aia''']<br />
* [https://www.dropbox.com/s/qx0fenr2ij7g78l/zgadywanka_Animals.aia?dl=1 plik '''.aia''']<br />
* [https://www.dropbox.com/s/27c4adazfeepdit/pnk_v2a.aia?dl=1 plik '''.aia''']<br />
|<br />
* [http://1drv.ms/1wYg1F3 plik '''.apk''']<br />
* [http://1drv.ms/1wGFVT3 plik '''.apk''']<br />
* [http://1drv.ms/1A10Jk3 plik '''.apk''']<br />
* [http://1drv.ms/1w7rvuE plik '''.apk''']<br />
* [http://1drv.ms/1w7sqvc plik '''.apk''']<br />
* [http://1drv.ms/1BUq8SP plik '''.apk''']<br />
* [http://1drv.ms/1wYkN5t plik '''.apk''']<br />
* [http://1drv.ms/1DQ7Z3s plik '''.apk''']<br />
|}</div>M Kelniarzhttp://wiki.mistrzowiekodowania.pl/index.php?title=Strona_g%C5%82%C3%B3wnaStrona główna2015-09-14T14:12:31Z<p>M Kelniarz: /* Projekty */</p>
<hr />
<div>[[Plik:Logo_Mistrzowie.png|center]]<br />
<br />
<br />
<br />
'''Witaj na stronie ze scenariuszami!'''<br />
<br />
'''Wszystkie scenariusze w wersji .pdf mozesz znaleźc [https://www.dropbox.com/sh/9e29fdqcgseh65w/AABm12kGHhxg_fzzspVLyac8a?dl=0 '''TUTAJ''']'''<br />
<br />
==Scratch==<br />
===Scenariusze===<br />
<br />
* [[Quiz o Scratch]] <br />
<br />
''' Scenariusze dla klas 4-6 szkoły podstawowej'''<br />
<br />
''' Scenarios dedicated to primary school learners, 4th - 6th grade (basic level)'''<br />
<br />
{| class="wikitable" border="0"<br />
|-<br />
! Wersja polska<br />
! English version<br />
|-<br />
|<br />
* [[Wprowadzenie 1 - Korzystanie z konta Scratch]]<br />
* [[Wprowadzenie 2 - Opis środowiska Scratch]]<br />
* [[Wprowadzenie 3 - Słowniczek podstawowych bloków]]<br />
* [[Moduł 1 - "Pierwsze kroki w Scratch'u"]]<br />
* [[Moduł 2 - "Kot goni mysz"]]<br />
* [[Moduł 3 - "Kot w labiryncie"]]<br />
* [[Moduł 4 - "Kot zastawia pułapkę na mysz"]]<br />
* [[Moduł 5 - "Gra zręcznościowa - odbijanie piłeczki"]]<br />
* [[Moduł 6 - "Gra logiczna - zgadywanie liczby"]]<br />
* [[Moduł 7 - „Zawody lekkoatletyczne duszków”]]<br />
* [[Moduł 8 - „Multimedialna kartka świąteczna”]]<br />
|<br />
* [[Introduction 1 - Using a Scratch account]]<br />
* [[Introduction 2 - Description of the Scratch environment]]<br />
* [[Introduction 3 - Glossary of basic Scratch 2.0 blocks]]<br />
* [[Module 1 - Getting started in Scratch]]<br />
* [[Module 2 - The “Cat Chasing a Mouse” Project]]<br />
* [[Module 3 - The “Cat in a Maze” Project ]]<br />
* [[Module 4 - The “Cat Sets a Trap for the Mouse” Project]]<br />
* [[Module 5 - The “Bounce the Ball Arcade Game” Project]]<br />
* [[Module 6 - The “Guess the NumberLogic Game” Project]]<br />
* [[Module 7 - The “Sprites’ Track and Field Competition” Project]]<br />
* [[Module 8 - The “Multimedia Christmas Card” Project]]<br />
|}<br />
<br />
<br />
<br />
{| class="wikitable" border="0"<br />
|-<br />
! Szkoła podstawowa (klasy 1-3)<br />
! Szkoła podstawowa (klasy 4-6)<br />
! Gimnazjum<br />
|-<br />
|<br />
* [[Cykl życia motyla]]<br />
* [[Animacja poklatkowa: wzrost kwiatka]]<br />
* [[Interpretacja wiersza]]<br />
* [[Literowanie]]<br />
* [[Aplikacja do rysowania]]<br />
* [[Sumowanie]]<br />
* [[Segregacja odpadów]]<br />
* [[Gra kamień-nożyce-papier]]<br />
* [[Wyścigówka (wersja A)]]<br />
|<br />
* [[Interaktywna mapa Polski (punkty)]]<br />
* [[Animacja - układ pokarmowy]]<br />
* [[Maszynka losująca]]<br />
* [[Czasomierz lekcyjny]]<br />
* [[Arkanoid]]<br />
* [[Generator wielokątów]]<br />
* [[Wyścigówka (wersja B)]]<br />
* [[Gra platformowa]]<br />
|<br />
* [[Interaktywna mapa Polski (województwa)]]<br />
* [[Animacja - układ pokarmowy (wersja B)]]<br />
* [[Maszynka losująca (wersja B)]]<br />
* [[Czasomierz lekcyjny]]<br />
* [[Arkanoid (wersja B)]]<br />
* [[Labirynt]]<br />
* [[Generator wielokątów]]<br />
* [[Wyścigówka (wersja C)]]<br />
* [[Gra platformowa (wersja z przesuwanym tłem)]]<br />
|}<br />
<br />
==App Inventor==<br />
===Scenariusze===<br />
*[[Wprowadzenie]]<br />
*[[Scenariusz 1 - Kalkulator prosty]]<br />
*[[Scenariusz 2 - Squash]]<br />
*[[Scenariusz 3 - Rysowanie palcem po ekranie]]<br />
*[[Scenariusz 4 - Spaceshooter]]<br />
*[[Scenariusz 5 - Chat Bluetooth]]<br />
*[[Scenariusz 6 - Tablica ogłoszeń]]<br />
*[[Scenariusz 7 - Kalkulator (prawie) pełny]]<br />
<br />
===Tłumaczenia===<br />
Tłumaczenia tutoriali ze strony [http://appinventor.mit.edu/explore/ai2/support/blocks.html MIT App Inventor]<br />
<br />
*[[Jak podłączyć telefon lub tablet przez WiFi?]]<br />
*[[Hello Purr]]<br />
*[[Bouncing Ball]]<br />
*[[MoleMash]]<br />
*[[Magic Ball]]<br />
*[[QuizMe]]<br />
<br />
===Opis bloków===<br />
Opisy przygotowane na podstawie materiałów ze strony [http://appinventor.mit.edu/explore/ai2/tutorials.html MIT App Inventor]<br />
<br />
* [[Bloki kontrolne]]<br />
* [[Bloki logiczne]]<br />
* [[Bloki matematyczne]]<br />
* [[Bloki tekstowe]]<br />
* [[Bloki listowe]]<br />
* [[Bloki kolorów]]<br />
* [[Bloki zmiennych]]<br />
* [[Bloki procedur]]<br />
<br />
===Projekty===<br />
Pliki '''.aia''' i '''.apk''' do ewentualnego wykorzystania w trakcie zajęć App Inventor.<br />
<br />
*'''"Tylko media"''' - projekt bez ''layout'' i kodu - wczytane pliki mediów (grafika, dźwięk);<br />
*'''"Szablon"''' - projekt z plikami mediów i ''layoutem'' - bez kodu;<br />
*'''"Kod źródłowy"''' - kompletny plik .aia;<br />
*'''"Aplikacja"''' - plik instalacyjny (.apk);<br />
<br />
{| class="wikitable" border="0"<br />
|-<br />
! Projekt<br />
! Tylko media<br />
! Szablon<br />
! Kod źródłowy<br />
! Aplikacja<br />
|-<br />
|<br />
* Hello ''imię''<br />
* Nie klikaj<br />
* Rysowanie<br />
* Spaceshooter<br />
* Zgadnij liczbę<br />
* Kalkulator<br />
* zgadywanka Animals<br />
* Kamień, papier, nożyce<br />
|<br />
* <br />
* <br />
* <br />
* <br />
* <br />
* <br />
* [https://www.dropbox.com/s/59zh3exj1s3pzws/zgadywanka_media.aia?dl=0 plik '''.aia''']<br />
* [https://www.dropbox.com/s/mwjbvs3sc1fwokw/pnk_v2a_media.aia?dl=1 plik '''.aia''']<br />
|<br />
* <br />
* <br />
* [http://1drv.ms/1zQ6uA6 plik '''.aia''']<br />
* <br />
* [http://1drv.ms/1G29BJS plik '''.aia''']<br />
* [http://1drv.ms/18m9Uny plik '''.aia''']<br />
* [http://1drv.ms/1CCpGYU plik '''.aia''']<br />
* [http://1drv.ms/18m5mNR plik '''.aia''']<br />
|<br />
* [https://www.dropbox.com/s/7zml10v5mwz4080/helloimie.aia?dl=1 plik '''.aia''']<br />
* [https://www.dropbox.com/s/vc9u7czby6o4raa/nie_klikaj.aia?dl=1 plik '''.aia''']<br />
* [https://www.dropbox.com/s/jzopcfcazrxnlkm/rysowanie_3.aia?dl=1 plik '''.aia''']<br />
* [https://www.dropbox.com/s/gn1nzpu9mq0knrp/spaceshooter.aia?dl=1 plik '''.aia''']<br />
* [https://www.dropbox.com/s/8wa7uh4ebyws0xr/zgadnij_liczbe.aia?dl=1 plik '''.aia''']<br />
* [https://www.dropbox.com/s/biq1732dpak7afu/kalkulator_prosty_v2a.aia?dl=1 plik '''.aia''']<br />
* [https://www.dropbox.com/s/qx0fenr2ij7g78l/zgadywanka_Animals.aia?dl=1 plik '''.aia''']<br />
* [https://www.dropbox.com/s/27c4adazfeepdit/pnk_v2a.aia?dl=1 plik '''.aia''']<br />
|<br />
* [http://1drv.ms/1wYg1F3 plik '''.apk''']<br />
* [http://1drv.ms/1wGFVT3 plik '''.apk''']<br />
* [http://1drv.ms/1A10Jk3 plik '''.apk''']<br />
* [http://1drv.ms/1w7rvuE plik '''.apk''']<br />
* [http://1drv.ms/1w7sqvc plik '''.apk''']<br />
* [http://1drv.ms/1BUq8SP plik '''.apk''']<br />
* [http://1drv.ms/1wYkN5t plik '''.apk''']<br />
* [http://1drv.ms/1DQ7Z3s plik '''.apk''']<br />
|}</div>M Kelniarzhttp://wiki.mistrzowiekodowania.pl/index.php?title=Strona_g%C5%82%C3%B3wnaStrona główna2015-09-14T10:43:09Z<p>M Kelniarz: /* Projekty */</p>
<hr />
<div>[[Plik:Logo_Mistrzowie.png|center]]<br />
<br />
<br />
<br />
'''Witaj na stronie ze scenariuszami!'''<br />
<br />
'''Wszystkie scenariusze w wersji .pdf mozesz znaleźc [https://www.dropbox.com/sh/9e29fdqcgseh65w/AABm12kGHhxg_fzzspVLyac8a?dl=0 '''TUTAJ''']'''<br />
<br />
==Scratch==<br />
===Scenariusze===<br />
<br />
* [[Quiz o Scratch]] <br />
<br />
''' Scenariusze dla klas 4-6 szkoły podstawowej'''<br />
<br />
''' Scenarios dedicated to primary school learners, 4th - 6th grade (basic level)'''<br />
<br />
{| class="wikitable" border="0"<br />
|-<br />
! Wersja polska<br />
! English version<br />
|-<br />
|<br />
* [[Wprowadzenie 1 - Korzystanie z konta Scratch]]<br />
* [[Wprowadzenie 2 - Opis środowiska Scratch]]<br />
* [[Wprowadzenie 3 - Słowniczek podstawowych bloków]]<br />
* [[Moduł 1 - "Pierwsze kroki w Scratch'u"]]<br />
* [[Moduł 2 - "Kot goni mysz"]]<br />
* [[Moduł 3 - "Kot w labiryncie"]]<br />
* [[Moduł 4 - "Kot zastawia pułapkę na mysz"]]<br />
* [[Moduł 5 - "Gra zręcznościowa - odbijanie piłeczki"]]<br />
* [[Moduł 6 - "Gra logiczna - zgadywanie liczby"]]<br />
* [[Moduł 7 - „Zawody lekkoatletyczne duszków”]]<br />
* [[Moduł 8 - „Multimedialna kartka świąteczna”]]<br />
|<br />
* [[Introduction 1 - Using a Scratch account]]<br />
* [[Introduction 2 - Description of the Scratch environment]]<br />
* [[Introduction 3 - Glossary of basic Scratch 2.0 blocks]]<br />
* [[Module 1 - Getting started in Scratch]]<br />
* [[Module 2 - The “Cat Chasing a Mouse” Project]]<br />
* [[Module 3 - The “Cat in a Maze” Project ]]<br />
* [[Module 4 - The “Cat Sets a Trap for the Mouse” Project]]<br />
* [[Module 5 - The “Bounce the Ball Arcade Game” Project]]<br />
* [[Module 6 - The “Guess the NumberLogic Game” Project]]<br />
* [[Module 7 - The “Sprites’ Track and Field Competition” Project]]<br />
* [[Module 8 - The “Multimedia Christmas Card” Project]]<br />
|}<br />
<br />
<br />
<br />
{| class="wikitable" border="0"<br />
|-<br />
! Szkoła podstawowa (klasy 1-3)<br />
! Szkoła podstawowa (klasy 4-6)<br />
! Gimnazjum<br />
|-<br />
|<br />
* [[Cykl życia motyla]]<br />
* [[Animacja poklatkowa: wzrost kwiatka]]<br />
* [[Interpretacja wiersza]]<br />
* [[Literowanie]]<br />
* [[Aplikacja do rysowania]]<br />
* [[Sumowanie]]<br />
* [[Segregacja odpadów]]<br />
* [[Gra kamień-nożyce-papier]]<br />
* [[Wyścigówka (wersja A)]]<br />
|<br />
* [[Interaktywna mapa Polski (punkty)]]<br />
* [[Animacja - układ pokarmowy]]<br />
* [[Maszynka losująca]]<br />
* [[Czasomierz lekcyjny]]<br />
* [[Arkanoid]]<br />
* [[Generator wielokątów]]<br />
* [[Wyścigówka (wersja B)]]<br />
* [[Gra platformowa]]<br />
|<br />
* [[Interaktywna mapa Polski (województwa)]]<br />
* [[Animacja - układ pokarmowy (wersja B)]]<br />
* [[Maszynka losująca (wersja B)]]<br />
* [[Czasomierz lekcyjny]]<br />
* [[Arkanoid (wersja B)]]<br />
* [[Labirynt]]<br />
* [[Generator wielokątów]]<br />
* [[Wyścigówka (wersja C)]]<br />
* [[Gra platformowa (wersja z przesuwanym tłem)]]<br />
|}<br />
<br />
==App Inventor==<br />
===Scenariusze===<br />
*[[Wprowadzenie]]<br />
*[[Scenariusz 1 - Kalkulator prosty]]<br />
*[[Scenariusz 2 - Squash]]<br />
*[[Scenariusz 3 - Rysowanie palcem po ekranie]]<br />
*[[Scenariusz 4 - Spaceshooter]]<br />
*[[Scenariusz 5 - Chat Bluetooth]]<br />
*[[Scenariusz 6 - Tablica ogłoszeń]]<br />
*[[Scenariusz 7 - Kalkulator (prawie) pełny]]<br />
<br />
===Tłumaczenia===<br />
Tłumaczenia tutoriali ze strony [http://appinventor.mit.edu/explore/ai2/support/blocks.html MIT App Inventor]<br />
<br />
*[[Jak podłączyć telefon lub tablet przez WiFi?]]<br />
*[[Hello Purr]]<br />
*[[Bouncing Ball]]<br />
*[[MoleMash]]<br />
*[[Magic Ball]]<br />
*[[QuizMe]]<br />
<br />
===Opis bloków===<br />
Opisy przygotowane na podstawie materiałów ze strony [http://appinventor.mit.edu/explore/ai2/tutorials.html MIT App Inventor]<br />
<br />
* [[Bloki kontrolne]]<br />
* [[Bloki logiczne]]<br />
* [[Bloki matematyczne]]<br />
* [[Bloki tekstowe]]<br />
* [[Bloki listowe]]<br />
* [[Bloki kolorów]]<br />
* [[Bloki zmiennych]]<br />
* [[Bloki procedur]]<br />
<br />
===Projekty===<br />
Pliki '''.aia''' i '''.apk''' do ewentualnego wykorzystania w trakcie zajęć App Inventor.<br />
<br />
*'''"Tylko media"''' - projekt bez ''layout'' i kodu - wczytane pliki mediów (grafika, dźwięk);<br />
*'''"Szablon"''' - projekt z plikami mediów i ''layoutem'' - bez kodu;<br />
*'''"Kod źródłowy"''' - kompletny plik .aia;<br />
*'''"Aplikacja"''' - plik instalacyjny (.apk);<br />
<br />
{| class="wikitable" border="0"<br />
|-<br />
! Projekt<br />
! Tylko media<br />
! Szablon<br />
! Kod źródłowy<br />
! Aplikacja<br />
|-<br />
|<br />
* Hello ''imię''<br />
* Nie klikaj<br />
* Rysowanie<br />
* Spaceshooter<br />
* Zgadnij liczbę<br />
* Kalkulator<br />
* zgadywanka Animals<br />
* Kamień, papier, nożyce<br />
|<br />
* <br />
* <br />
* <br />
* <br />
* <br />
* <br />
* [http://1drv.ms/1CCq6hW plik '''.aia''']<br />
* [http://1drv.ms/1BbAcDe plik '''.aia''']<br />
|<br />
* <br />
* <br />
* [http://1drv.ms/1zQ6uA6 plik '''.aia''']<br />
* <br />
* [http://1drv.ms/1G29BJS plik '''.aia''']<br />
* [http://1drv.ms/18m9Uny plik '''.aia''']<br />
* [http://1drv.ms/1CCpGYU plik '''.aia''']<br />
* [http://1drv.ms/18m5mNR plik '''.aia''']<br />
|<br />
* [https://www.dropbox.com/s/7zml10v5mwz4080/helloimie.aia?dl=1 plik '''.aia''']<br />
* [https://www.dropbox.com/s/vc9u7czby6o4raa/nie_klikaj.aia?dl=1 plik '''.aia''']<br />
* [https://www.dropbox.com/s/jzopcfcazrxnlkm/rysowanie_3.aia?dl=1 plik '''.aia''']<br />
* [https://www.dropbox.com/s/gn1nzpu9mq0knrp/spaceshooter.aia?dl=1 plik '''.aia''']<br />
* [https://www.dropbox.com/s/8wa7uh4ebyws0xr/zgadnij_liczbe.aia?dl=1 plik '''.aia''']<br />
* [https://www.dropbox.com/s/biq1732dpak7afu/kalkulator_prosty_v2a.aia?dl=1 plik '''.aia''']<br />
* [https://www.dropbox.com/s/qx0fenr2ij7g78l/zgadywanka_Animals.aia?dl=1 plik '''.aia''']<br />
* [https://www.dropbox.com/s/27c4adazfeepdit/pnk_v2a.aia?dl=1 plik '''.aia''']<br />
|<br />
* [http://1drv.ms/1wYg1F3 plik '''.apk''']<br />
* [http://1drv.ms/1wGFVT3 plik '''.apk''']<br />
* [http://1drv.ms/1A10Jk3 plik '''.apk''']<br />
* [http://1drv.ms/1w7rvuE plik '''.apk''']<br />
* [http://1drv.ms/1w7sqvc plik '''.apk''']<br />
* [http://1drv.ms/1BUq8SP plik '''.apk''']<br />
* [http://1drv.ms/1wYkN5t plik '''.apk''']<br />
* [http://1drv.ms/1DQ7Z3s plik '''.apk''']<br />
|}</div>M Kelniarzhttp://wiki.mistrzowiekodowania.pl/index.php?title=Strona_g%C5%82%C3%B3wnaStrona główna2015-09-14T10:40:30Z<p>M Kelniarz: /* Projekty */</p>
<hr />
<div>[[Plik:Logo_Mistrzowie.png|center]]<br />
<br />
<br />
<br />
'''Witaj na stronie ze scenariuszami!'''<br />
<br />
'''Wszystkie scenariusze w wersji .pdf mozesz znaleźc [https://www.dropbox.com/sh/9e29fdqcgseh65w/AABm12kGHhxg_fzzspVLyac8a?dl=0 '''TUTAJ''']'''<br />
<br />
==Scratch==<br />
===Scenariusze===<br />
<br />
* [[Quiz o Scratch]] <br />
<br />
''' Scenariusze dla klas 4-6 szkoły podstawowej'''<br />
<br />
''' Scenarios dedicated to primary school learners, 4th - 6th grade (basic level)'''<br />
<br />
{| class="wikitable" border="0"<br />
|-<br />
! Wersja polska<br />
! English version<br />
|-<br />
|<br />
* [[Wprowadzenie 1 - Korzystanie z konta Scratch]]<br />
* [[Wprowadzenie 2 - Opis środowiska Scratch]]<br />
* [[Wprowadzenie 3 - Słowniczek podstawowych bloków]]<br />
* [[Moduł 1 - "Pierwsze kroki w Scratch'u"]]<br />
* [[Moduł 2 - "Kot goni mysz"]]<br />
* [[Moduł 3 - "Kot w labiryncie"]]<br />
* [[Moduł 4 - "Kot zastawia pułapkę na mysz"]]<br />
* [[Moduł 5 - "Gra zręcznościowa - odbijanie piłeczki"]]<br />
* [[Moduł 6 - "Gra logiczna - zgadywanie liczby"]]<br />
* [[Moduł 7 - „Zawody lekkoatletyczne duszków”]]<br />
* [[Moduł 8 - „Multimedialna kartka świąteczna”]]<br />
|<br />
* [[Introduction 1 - Using a Scratch account]]<br />
* [[Introduction 2 - Description of the Scratch environment]]<br />
* [[Introduction 3 - Glossary of basic Scratch 2.0 blocks]]<br />
* [[Module 1 - Getting started in Scratch]]<br />
* [[Module 2 - The “Cat Chasing a Mouse” Project]]<br />
* [[Module 3 - The “Cat in a Maze” Project ]]<br />
* [[Module 4 - The “Cat Sets a Trap for the Mouse” Project]]<br />
* [[Module 5 - The “Bounce the Ball Arcade Game” Project]]<br />
* [[Module 6 - The “Guess the NumberLogic Game” Project]]<br />
* [[Module 7 - The “Sprites’ Track and Field Competition” Project]]<br />
* [[Module 8 - The “Multimedia Christmas Card” Project]]<br />
|}<br />
<br />
<br />
<br />
{| class="wikitable" border="0"<br />
|-<br />
! Szkoła podstawowa (klasy 1-3)<br />
! Szkoła podstawowa (klasy 4-6)<br />
! Gimnazjum<br />
|-<br />
|<br />
* [[Cykl życia motyla]]<br />
* [[Animacja poklatkowa: wzrost kwiatka]]<br />
* [[Interpretacja wiersza]]<br />
* [[Literowanie]]<br />
* [[Aplikacja do rysowania]]<br />
* [[Sumowanie]]<br />
* [[Segregacja odpadów]]<br />
* [[Gra kamień-nożyce-papier]]<br />
* [[Wyścigówka (wersja A)]]<br />
|<br />
* [[Interaktywna mapa Polski (punkty)]]<br />
* [[Animacja - układ pokarmowy]]<br />
* [[Maszynka losująca]]<br />
* [[Czasomierz lekcyjny]]<br />
* [[Arkanoid]]<br />
* [[Generator wielokątów]]<br />
* [[Wyścigówka (wersja B)]]<br />
* [[Gra platformowa]]<br />
|<br />
* [[Interaktywna mapa Polski (województwa)]]<br />
* [[Animacja - układ pokarmowy (wersja B)]]<br />
* [[Maszynka losująca (wersja B)]]<br />
* [[Czasomierz lekcyjny]]<br />
* [[Arkanoid (wersja B)]]<br />
* [[Labirynt]]<br />
* [[Generator wielokątów]]<br />
* [[Wyścigówka (wersja C)]]<br />
* [[Gra platformowa (wersja z przesuwanym tłem)]]<br />
|}<br />
<br />
==App Inventor==<br />
===Scenariusze===<br />
*[[Wprowadzenie]]<br />
*[[Scenariusz 1 - Kalkulator prosty]]<br />
*[[Scenariusz 2 - Squash]]<br />
*[[Scenariusz 3 - Rysowanie palcem po ekranie]]<br />
*[[Scenariusz 4 - Spaceshooter]]<br />
*[[Scenariusz 5 - Chat Bluetooth]]<br />
*[[Scenariusz 6 - Tablica ogłoszeń]]<br />
*[[Scenariusz 7 - Kalkulator (prawie) pełny]]<br />
<br />
===Tłumaczenia===<br />
Tłumaczenia tutoriali ze strony [http://appinventor.mit.edu/explore/ai2/support/blocks.html MIT App Inventor]<br />
<br />
*[[Jak podłączyć telefon lub tablet przez WiFi?]]<br />
*[[Hello Purr]]<br />
*[[Bouncing Ball]]<br />
*[[MoleMash]]<br />
*[[Magic Ball]]<br />
*[[QuizMe]]<br />
<br />
===Opis bloków===<br />
Opisy przygotowane na podstawie materiałów ze strony [http://appinventor.mit.edu/explore/ai2/tutorials.html MIT App Inventor]<br />
<br />
* [[Bloki kontrolne]]<br />
* [[Bloki logiczne]]<br />
* [[Bloki matematyczne]]<br />
* [[Bloki tekstowe]]<br />
* [[Bloki listowe]]<br />
* [[Bloki kolorów]]<br />
* [[Bloki zmiennych]]<br />
* [[Bloki procedur]]<br />
<br />
===Projekty===<br />
Pliki '''.aia''' i '''.apk''' do ewentualnego wykorzystania w trakcie zajęć App Inventor.<br />
<br />
*'''"Tylko media"''' - projekt bez ''layout'' i kodu - wczytane pliki mediów (grafika, dźwięk);<br />
*'''"Szablon"''' - projekt z plikami mediów i ''layoutem'' - bez kodu;<br />
*'''"Kod źródłowy"''' - kompletny plik .aia;<br />
*'''"Aplikacja"''' - plik instalacyjny (.apk);<br />
<br />
{| class="wikitable" border="0"<br />
|-<br />
! Projekt<br />
! Tylko media<br />
! Szablon<br />
! Kod źródłowy<br />
! Aplikacja<br />
|-<br />
|<br />
* Hello ''imię''<br />
* Nie klikaj<br />
* Rysowanie<br />
* Spaceshooter<br />
* Zgadnij liczbę<br />
* Kalkulator<br />
* zgadywanka Animals<br />
* Kamień, papier, nożyce<br />
|<br />
* <br />
* <br />
* <br />
* <br />
* <br />
* <br />
* [http://1drv.ms/1CCq6hW plik '''.aia''']<br />
* [http://1drv.ms/1BbAcDe plik '''.aia''']<br />
|<br />
* <br />
* <br />
* [http://1drv.ms/1zQ6uA6 plik '''.aia''']<br />
* <br />
* [http://1drv.ms/1G29BJS plik '''.aia''']<br />
* [http://1drv.ms/18m9Uny plik '''.aia''']<br />
* [http://1drv.ms/1CCpGYU plik '''.aia''']<br />
* [http://1drv.ms/18m5mNR plik '''.aia''']<br />
|<br />
* [https://www.dropbox.com/s/7zml10v5mwz4080/helloimie.aia?dl=1 plik '''.aia''']<br />
* [https://www.dropbox.com/s/vc9u7czby6o4raa/nie_klikaj.aia?dl=1 plik '''.aia''']<br />
* [https://www.dropbox.com/s/jzopcfcazrxnlkm/rysowanie_3.aia?dl=1 plik '''.aia''']<br />
* [https://www.dropbox.com/s/gn1nzpu9mq0knrp/spaceshooter.aia?dl=1 plik '''.aia''']<br />
* [https://www.dropbox.com/s/8wa7uh4ebyws0xr/zgadnij_liczbe.aia?dl=1 plik '''.aia''']<br />
* [https://www.dropbox.com/s/jun2nf4o9arym5y/RYSOWANIE.aia?dl=1 plik '''.aia''']<br />
* [https://www.dropbox.com/s/27c4adazfeepdit/pnk_v2a.aia?dl=1 plik '''.aia''']<br />
* [https://www.dropbox.com/s/27c4adazfeepdit/pnk_v2a.aia?dl=1 plik '''.aia''']<br />
|<br />
* [http://1drv.ms/1wYg1F3 plik '''.apk''']<br />
* [http://1drv.ms/1wGFVT3 plik '''.apk''']<br />
* [http://1drv.ms/1A10Jk3 plik '''.apk''']<br />
* [http://1drv.ms/1w7rvuE plik '''.apk''']<br />
* [http://1drv.ms/1w7sqvc plik '''.apk''']<br />
* [http://1drv.ms/1BUq8SP plik '''.apk''']<br />
* [http://1drv.ms/1wYkN5t plik '''.apk''']<br />
* [http://1drv.ms/1DQ7Z3s plik '''.apk''']<br />
|}</div>M Kelniarzhttp://wiki.mistrzowiekodowania.pl/index.php?title=Strona_g%C5%82%C3%B3wnaStrona główna2015-09-14T10:39:13Z<p>M Kelniarz: /* Projekty */</p>
<hr />
<div>[[Plik:Logo_Mistrzowie.png|center]]<br />
<br />
<br />
<br />
'''Witaj na stronie ze scenariuszami!'''<br />
<br />
'''Wszystkie scenariusze w wersji .pdf mozesz znaleźc [https://www.dropbox.com/sh/9e29fdqcgseh65w/AABm12kGHhxg_fzzspVLyac8a?dl=0 '''TUTAJ''']'''<br />
<br />
==Scratch==<br />
===Scenariusze===<br />
<br />
* [[Quiz o Scratch]] <br />
<br />
''' Scenariusze dla klas 4-6 szkoły podstawowej'''<br />
<br />
''' Scenarios dedicated to primary school learners, 4th - 6th grade (basic level)'''<br />
<br />
{| class="wikitable" border="0"<br />
|-<br />
! Wersja polska<br />
! English version<br />
|-<br />
|<br />
* [[Wprowadzenie 1 - Korzystanie z konta Scratch]]<br />
* [[Wprowadzenie 2 - Opis środowiska Scratch]]<br />
* [[Wprowadzenie 3 - Słowniczek podstawowych bloków]]<br />
* [[Moduł 1 - "Pierwsze kroki w Scratch'u"]]<br />
* [[Moduł 2 - "Kot goni mysz"]]<br />
* [[Moduł 3 - "Kot w labiryncie"]]<br />
* [[Moduł 4 - "Kot zastawia pułapkę na mysz"]]<br />
* [[Moduł 5 - "Gra zręcznościowa - odbijanie piłeczki"]]<br />
* [[Moduł 6 - "Gra logiczna - zgadywanie liczby"]]<br />
* [[Moduł 7 - „Zawody lekkoatletyczne duszków”]]<br />
* [[Moduł 8 - „Multimedialna kartka świąteczna”]]<br />
|<br />
* [[Introduction 1 - Using a Scratch account]]<br />
* [[Introduction 2 - Description of the Scratch environment]]<br />
* [[Introduction 3 - Glossary of basic Scratch 2.0 blocks]]<br />
* [[Module 1 - Getting started in Scratch]]<br />
* [[Module 2 - The “Cat Chasing a Mouse” Project]]<br />
* [[Module 3 - The “Cat in a Maze” Project ]]<br />
* [[Module 4 - The “Cat Sets a Trap for the Mouse” Project]]<br />
* [[Module 5 - The “Bounce the Ball Arcade Game” Project]]<br />
* [[Module 6 - The “Guess the NumberLogic Game” Project]]<br />
* [[Module 7 - The “Sprites’ Track and Field Competition” Project]]<br />
* [[Module 8 - The “Multimedia Christmas Card” Project]]<br />
|}<br />
<br />
<br />
<br />
{| class="wikitable" border="0"<br />
|-<br />
! Szkoła podstawowa (klasy 1-3)<br />
! Szkoła podstawowa (klasy 4-6)<br />
! Gimnazjum<br />
|-<br />
|<br />
* [[Cykl życia motyla]]<br />
* [[Animacja poklatkowa: wzrost kwiatka]]<br />
* [[Interpretacja wiersza]]<br />
* [[Literowanie]]<br />
* [[Aplikacja do rysowania]]<br />
* [[Sumowanie]]<br />
* [[Segregacja odpadów]]<br />
* [[Gra kamień-nożyce-papier]]<br />
* [[Wyścigówka (wersja A)]]<br />
|<br />
* [[Interaktywna mapa Polski (punkty)]]<br />
* [[Animacja - układ pokarmowy]]<br />
* [[Maszynka losująca]]<br />
* [[Czasomierz lekcyjny]]<br />
* [[Arkanoid]]<br />
* [[Generator wielokątów]]<br />
* [[Wyścigówka (wersja B)]]<br />
* [[Gra platformowa]]<br />
|<br />
* [[Interaktywna mapa Polski (województwa)]]<br />
* [[Animacja - układ pokarmowy (wersja B)]]<br />
* [[Maszynka losująca (wersja B)]]<br />
* [[Czasomierz lekcyjny]]<br />
* [[Arkanoid (wersja B)]]<br />
* [[Labirynt]]<br />
* [[Generator wielokątów]]<br />
* [[Wyścigówka (wersja C)]]<br />
* [[Gra platformowa (wersja z przesuwanym tłem)]]<br />
|}<br />
<br />
==App Inventor==<br />
===Scenariusze===<br />
*[[Wprowadzenie]]<br />
*[[Scenariusz 1 - Kalkulator prosty]]<br />
*[[Scenariusz 2 - Squash]]<br />
*[[Scenariusz 3 - Rysowanie palcem po ekranie]]<br />
*[[Scenariusz 4 - Spaceshooter]]<br />
*[[Scenariusz 5 - Chat Bluetooth]]<br />
*[[Scenariusz 6 - Tablica ogłoszeń]]<br />
*[[Scenariusz 7 - Kalkulator (prawie) pełny]]<br />
<br />
===Tłumaczenia===<br />
Tłumaczenia tutoriali ze strony [http://appinventor.mit.edu/explore/ai2/support/blocks.html MIT App Inventor]<br />
<br />
*[[Jak podłączyć telefon lub tablet przez WiFi?]]<br />
*[[Hello Purr]]<br />
*[[Bouncing Ball]]<br />
*[[MoleMash]]<br />
*[[Magic Ball]]<br />
*[[QuizMe]]<br />
<br />
===Opis bloków===<br />
Opisy przygotowane na podstawie materiałów ze strony [http://appinventor.mit.edu/explore/ai2/tutorials.html MIT App Inventor]<br />
<br />
* [[Bloki kontrolne]]<br />
* [[Bloki logiczne]]<br />
* [[Bloki matematyczne]]<br />
* [[Bloki tekstowe]]<br />
* [[Bloki listowe]]<br />
* [[Bloki kolorów]]<br />
* [[Bloki zmiennych]]<br />
* [[Bloki procedur]]<br />
<br />
===Projekty===<br />
Pliki '''.aia''' i '''.apk''' do ewentualnego wykorzystania w trakcie zajęć App Inventor.<br />
<br />
*'''"Tylko media"''' - projekt bez ''layout'' i kodu - wczytane pliki mediów (grafika, dźwięk);<br />
*'''"Szablon"''' - projekt z plikami mediów i ''layoutem'' - bez kodu;<br />
*'''"Kod źródłowy"''' - kompletny plik .aia;<br />
*'''"Aplikacja"''' - plik instalacyjny (.apk);<br />
<br />
{| class="wikitable" border="0"<br />
|-<br />
! Projekt<br />
! Tylko media<br />
! Szablon<br />
! Kod źródłowy<br />
! Aplikacja<br />
|-<br />
|<br />
* Hello ''imię''<br />
* Nie klikaj<br />
* Rysowanie<br />
* Spaceshooter<br />
* Zgadnij liczbę<br />
* Kalkulator<br />
* zgadywanka Animals<br />
* Kamień, papier, nożyce<br />
|<br />
* <br />
* <br />
* <br />
* <br />
* <br />
* <br />
* [http://1drv.ms/1CCq6hW plik '''.aia''']<br />
* [http://1drv.ms/1BbAcDe plik '''.aia''']<br />
|<br />
* <br />
* <br />
* [http://1drv.ms/1zQ6uA6 plik '''.aia''']<br />
* <br />
* [http://1drv.ms/1G29BJS plik '''.aia''']<br />
* [http://1drv.ms/18m9Uny plik '''.aia''']<br />
* [http://1drv.ms/1CCpGYU plik '''.aia''']<br />
* [http://1drv.ms/18m5mNR plik '''.aia''']<br />
|<br />
* [https://www.dropbox.com/s/7zml10v5mwz4080/helloimie.aia?dl=1 plik '''.aia''']<br />
* [https://www.dropbox.com/s/vc9u7czby6o4raa/nie_klikaj.aia?dl=0 plik '''.aia''']<br />
* [https://www.dropbox.com/s/jzopcfcazrxnlkm/rysowanie_3.aia?dl=0 plik '''.aia''']<br />
* [https://www.dropbox.com/s/gn1nzpu9mq0knrp/spaceshooter.aia?dl=0 plik '''.aia''']<br />
* [https://www.dropbox.com/s/8wa7uh4ebyws0xr/zgadnij_liczbe.aia?dl=0 plik '''.aia''']<br />
* [https://www.dropbox.com/s/jun2nf4o9arym5y/RYSOWANIE.aia?dl=0 plik '''.aia''']<br />
* [https://www.dropbox.com/s/27c4adazfeepdit/pnk_v2a.aia?dl=0 plik '''.aia''']<br />
* [https://www.dropbox.com/s/27c4adazfeepdit/pnk_v2a.aia?dl=0 plik '''.aia''']<br />
|<br />
* [http://1drv.ms/1wYg1F3 plik '''.apk''']<br />
* [http://1drv.ms/1wGFVT3 plik '''.apk''']<br />
* [http://1drv.ms/1A10Jk3 plik '''.apk''']<br />
* [http://1drv.ms/1w7rvuE plik '''.apk''']<br />
* [http://1drv.ms/1w7sqvc plik '''.apk''']<br />
* [http://1drv.ms/1BUq8SP plik '''.apk''']<br />
* [http://1drv.ms/1wYkN5t plik '''.apk''']<br />
* [http://1drv.ms/1DQ7Z3s plik '''.apk''']<br />
|}</div>M Kelniarzhttp://wiki.mistrzowiekodowania.pl/index.php?title=Strona_g%C5%82%C3%B3wnaStrona główna2015-09-14T07:33:00Z<p>M Kelniarz: /* Projekty */</p>
<hr />
<div>[[Plik:Logo_Mistrzowie.png|center]]<br />
<br />
<br />
<br />
'''Witaj na stronie ze scenariuszami!'''<br />
<br />
'''Wszystkie scenariusze w wersji .pdf mozesz znaleźc [https://www.dropbox.com/sh/9e29fdqcgseh65w/AABm12kGHhxg_fzzspVLyac8a?dl=0 '''TUTAJ''']'''<br />
<br />
==Scratch==<br />
===Scenariusze===<br />
<br />
* [[Quiz o Scratch]] <br />
<br />
''' Scenariusze dla klas 4-6 szkoły podstawowej'''<br />
<br />
''' Scenarios dedicated to primary school learners, 4th - 6th grade (basic level)'''<br />
<br />
{| class="wikitable" border="0"<br />
|-<br />
! Wersja polska<br />
! English version<br />
|-<br />
|<br />
* [[Wprowadzenie 1 - Korzystanie z konta Scratch]]<br />
* [[Wprowadzenie 2 - Opis środowiska Scratch]]<br />
* [[Wprowadzenie 3 - Słowniczek podstawowych bloków]]<br />
* [[Moduł 1 - "Pierwsze kroki w Scratch'u"]]<br />
* [[Moduł 2 - "Kot goni mysz"]]<br />
* [[Moduł 3 - "Kot w labiryncie"]]<br />
* [[Moduł 4 - "Kot zastawia pułapkę na mysz"]]<br />
* [[Moduł 5 - "Gra zręcznościowa - odbijanie piłeczki"]]<br />
* [[Moduł 6 - "Gra logiczna - zgadywanie liczby"]]<br />
* [[Moduł 7 - „Zawody lekkoatletyczne duszków”]]<br />
* [[Moduł 8 - „Multimedialna kartka świąteczna”]]<br />
|<br />
* [[Introduction 1 - Using a Scratch account]]<br />
* [[Introduction 2 - Description of the Scratch environment]]<br />
* [[Introduction 3 - Glossary of basic Scratch 2.0 blocks]]<br />
* [[Module 1 - Getting started in Scratch]]<br />
* [[Module 2 - The “Cat Chasing a Mouse” Project]]<br />
* [[Module 3 - The “Cat in a Maze” Project ]]<br />
* [[Module 4 - The “Cat Sets a Trap for the Mouse” Project]]<br />
* [[Module 5 - The “Bounce the Ball Arcade Game” Project]]<br />
* [[Module 6 - The “Guess the NumberLogic Game” Project]]<br />
* [[Module 7 - The “Sprites’ Track and Field Competition” Project]]<br />
* [[Module 8 - The “Multimedia Christmas Card” Project]]<br />
|}<br />
<br />
<br />
<br />
{| class="wikitable" border="0"<br />
|-<br />
! Szkoła podstawowa (klasy 1-3)<br />
! Szkoła podstawowa (klasy 4-6)<br />
! Gimnazjum<br />
|-<br />
|<br />
* [[Cykl życia motyla]]<br />
* [[Animacja poklatkowa: wzrost kwiatka]]<br />
* [[Interpretacja wiersza]]<br />
* [[Literowanie]]<br />
* [[Aplikacja do rysowania]]<br />
* [[Sumowanie]]<br />
* [[Segregacja odpadów]]<br />
* [[Gra kamień-nożyce-papier]]<br />
* [[Wyścigówka (wersja A)]]<br />
|<br />
* [[Interaktywna mapa Polski (punkty)]]<br />
* [[Animacja - układ pokarmowy]]<br />
* [[Maszynka losująca]]<br />
* [[Czasomierz lekcyjny]]<br />
* [[Arkanoid]]<br />
* [[Generator wielokątów]]<br />
* [[Wyścigówka (wersja B)]]<br />
* [[Gra platformowa]]<br />
|<br />
* [[Interaktywna mapa Polski (województwa)]]<br />
* [[Animacja - układ pokarmowy (wersja B)]]<br />
* [[Maszynka losująca (wersja B)]]<br />
* [[Czasomierz lekcyjny]]<br />
* [[Arkanoid (wersja B)]]<br />
* [[Labirynt]]<br />
* [[Generator wielokątów]]<br />
* [[Wyścigówka (wersja C)]]<br />
* [[Gra platformowa (wersja z przesuwanym tłem)]]<br />
|}<br />
<br />
==App Inventor==<br />
===Scenariusze===<br />
*[[Wprowadzenie]]<br />
*[[Scenariusz 1 - Kalkulator prosty]]<br />
*[[Scenariusz 2 - Squash]]<br />
*[[Scenariusz 3 - Rysowanie palcem po ekranie]]<br />
*[[Scenariusz 4 - Spaceshooter]]<br />
*[[Scenariusz 5 - Chat Bluetooth]]<br />
*[[Scenariusz 6 - Tablica ogłoszeń]]<br />
*[[Scenariusz 7 - Kalkulator (prawie) pełny]]<br />
<br />
===Tłumaczenia===<br />
Tłumaczenia tutoriali ze strony [http://appinventor.mit.edu/explore/ai2/support/blocks.html MIT App Inventor]<br />
<br />
*[[Jak podłączyć telefon lub tablet przez WiFi?]]<br />
*[[Hello Purr]]<br />
*[[Bouncing Ball]]<br />
*[[MoleMash]]<br />
*[[Magic Ball]]<br />
*[[QuizMe]]<br />
<br />
===Opis bloków===<br />
Opisy przygotowane na podstawie materiałów ze strony [http://appinventor.mit.edu/explore/ai2/tutorials.html MIT App Inventor]<br />
<br />
* [[Bloki kontrolne]]<br />
* [[Bloki logiczne]]<br />
* [[Bloki matematyczne]]<br />
* [[Bloki tekstowe]]<br />
* [[Bloki listowe]]<br />
* [[Bloki kolorów]]<br />
* [[Bloki zmiennych]]<br />
* [[Bloki procedur]]<br />
<br />
===Projekty===<br />
Pliki '''.aia''' i '''.apk''' do ewentualnego wykorzystania w trakcie zajęć App Inventor.<br />
<br />
*'''"Tylko media"''' - projekt bez ''layout'' i kodu - wczytane pliki mediów (grafika, dźwięk);<br />
*'''"Szablon"''' - projekt z plikami mediów i ''layoutem'' - bez kodu;<br />
*'''"Kod źródłowy"''' - kompletny plik .aia;<br />
*'''"Aplikacja"''' - plik instalacyjny (.apk);<br />
<br />
{| class="wikitable" border="0"<br />
|-<br />
! Projekt<br />
! Tylko media<br />
! Szablon<br />
! Kod źródłowy<br />
! Aplikacja<br />
|-<br />
|<br />
* Hello ''imię''<br />
* Nie klikaj<br />
* Rysowanie<br />
* Spaceshooter<br />
* Zgadnij liczbę<br />
* Kalkulator<br />
* zgadywanka Animals<br />
* Kamień, papier, nożyce<br />
|<br />
* <br />
* <br />
* <br />
* <br />
* <br />
* <br />
* [http://1drv.ms/1CCq6hW plik '''.aia''']<br />
* [http://1drv.ms/1BbAcDe plik '''.aia''']<br />
|<br />
* <br />
* <br />
* [http://1drv.ms/1zQ6uA6 plik '''.aia''']<br />
* <br />
* [http://1drv.ms/1G29BJS plik '''.aia''']<br />
* [http://1drv.ms/18m9Uny plik '''.aia''']<br />
* [http://1drv.ms/1CCpGYU plik '''.aia''']<br />
* [http://1drv.ms/18m5mNR plik '''.aia''']<br />
|<br />
* [https://www.dropbox.com/s/7zml10v5mwz4080/helloimie.aia?dl=0 plik '''.aia''']<br />
* [https://www.dropbox.com/s/biq1732dpak7afu/kalkulator_prosty_v2a.aia?dl=0 plik '''.aia''']<br />
* [https://www.dropbox.com/s/vc9u7czby6o4raa/nie_klikaj.aia?dl=0 plik '''.aia''']<br />
* [https://www.dropbox.com/s/27c4adazfeepdit/pnk_v2a.aia?dl=0 plik '''.aia''']<br />
* [https://www.dropbox.com/s/jzopcfcazrxnlkm/rysowanie_3.aia?dl=0 plik '''.aia''']<br />
* [https://www.dropbox.com/s/jun2nf4o9arym5y/RYSOWANIE.aia?dl=0 plik '''.aia''']<br />
* [https://www.dropbox.com/s/gn1nzpu9mq0knrp/spaceshooter.aia?dl=0 plik '''.aia''']<br />
* [https://www.dropbox.com/s/8wa7uh4ebyws0xr/zgadnij_liczbe.aia?dl=0 plik '''.aia''']<br />
|<br />
* [http://1drv.ms/1wYg1F3 plik '''.apk''']<br />
* [http://1drv.ms/1wGFVT3 plik '''.apk''']<br />
* [http://1drv.ms/1A10Jk3 plik '''.apk''']<br />
* [http://1drv.ms/1w7rvuE plik '''.apk''']<br />
* [http://1drv.ms/1w7sqvc plik '''.apk''']<br />
* [http://1drv.ms/1BUq8SP plik '''.apk''']<br />
* [http://1drv.ms/1wYkN5t plik '''.apk''']<br />
* [http://1drv.ms/1DQ7Z3s plik '''.apk''']<br />
|}</div>M Kelniarzhttp://wiki.mistrzowiekodowania.pl/index.php?title=Strona_g%C5%82%C3%B3wnaStrona główna2015-09-14T07:16:20Z<p>M Kelniarz: </p>
<hr />
<div>[[Plik:Logo_Mistrzowie.png|center]]<br />
<br />
<br />
<br />
'''Witaj na stronie ze scenariuszami!'''<br />
<br />
'''Wszystkie scenariusze w wersji .pdf mozesz znaleźc [https://www.dropbox.com/sh/9e29fdqcgseh65w/AABm12kGHhxg_fzzspVLyac8a?dl=0 '''TUTAJ''']'''<br />
<br />
==Scratch==<br />
===Scenariusze===<br />
<br />
* [[Quiz o Scratch]] <br />
<br />
''' Scenariusze dla klas 4-6 szkoły podstawowej'''<br />
<br />
''' Scenarios dedicated to primary school learners, 4th - 6th grade (basic level)'''<br />
<br />
{| class="wikitable" border="0"<br />
|-<br />
! Wersja polska<br />
! English version<br />
|-<br />
|<br />
* [[Wprowadzenie 1 - Korzystanie z konta Scratch]]<br />
* [[Wprowadzenie 2 - Opis środowiska Scratch]]<br />
* [[Wprowadzenie 3 - Słowniczek podstawowych bloków]]<br />
* [[Moduł 1 - "Pierwsze kroki w Scratch'u"]]<br />
* [[Moduł 2 - "Kot goni mysz"]]<br />
* [[Moduł 3 - "Kot w labiryncie"]]<br />
* [[Moduł 4 - "Kot zastawia pułapkę na mysz"]]<br />
* [[Moduł 5 - "Gra zręcznościowa - odbijanie piłeczki"]]<br />
* [[Moduł 6 - "Gra logiczna - zgadywanie liczby"]]<br />
* [[Moduł 7 - „Zawody lekkoatletyczne duszków”]]<br />
* [[Moduł 8 - „Multimedialna kartka świąteczna”]]<br />
|<br />
* [[Introduction 1 - Using a Scratch account]]<br />
* [[Introduction 2 - Description of the Scratch environment]]<br />
* [[Introduction 3 - Glossary of basic Scratch 2.0 blocks]]<br />
* [[Module 1 - Getting started in Scratch]]<br />
* [[Module 2 - The “Cat Chasing a Mouse” Project]]<br />
* [[Module 3 - The “Cat in a Maze” Project ]]<br />
* [[Module 4 - The “Cat Sets a Trap for the Mouse” Project]]<br />
* [[Module 5 - The “Bounce the Ball Arcade Game” Project]]<br />
* [[Module 6 - The “Guess the NumberLogic Game” Project]]<br />
* [[Module 7 - The “Sprites’ Track and Field Competition” Project]]<br />
* [[Module 8 - The “Multimedia Christmas Card” Project]]<br />
|}<br />
<br />
<br />
<br />
{| class="wikitable" border="0"<br />
|-<br />
! Szkoła podstawowa (klasy 1-3)<br />
! Szkoła podstawowa (klasy 4-6)<br />
! Gimnazjum<br />
|-<br />
|<br />
* [[Cykl życia motyla]]<br />
* [[Animacja poklatkowa: wzrost kwiatka]]<br />
* [[Interpretacja wiersza]]<br />
* [[Literowanie]]<br />
* [[Aplikacja do rysowania]]<br />
* [[Sumowanie]]<br />
* [[Segregacja odpadów]]<br />
* [[Gra kamień-nożyce-papier]]<br />
* [[Wyścigówka (wersja A)]]<br />
|<br />
* [[Interaktywna mapa Polski (punkty)]]<br />
* [[Animacja - układ pokarmowy]]<br />
* [[Maszynka losująca]]<br />
* [[Czasomierz lekcyjny]]<br />
* [[Arkanoid]]<br />
* [[Generator wielokątów]]<br />
* [[Wyścigówka (wersja B)]]<br />
* [[Gra platformowa]]<br />
|<br />
* [[Interaktywna mapa Polski (województwa)]]<br />
* [[Animacja - układ pokarmowy (wersja B)]]<br />
* [[Maszynka losująca (wersja B)]]<br />
* [[Czasomierz lekcyjny]]<br />
* [[Arkanoid (wersja B)]]<br />
* [[Labirynt]]<br />
* [[Generator wielokątów]]<br />
* [[Wyścigówka (wersja C)]]<br />
* [[Gra platformowa (wersja z przesuwanym tłem)]]<br />
|}<br />
<br />
==App Inventor==<br />
===Scenariusze===<br />
*[[Wprowadzenie]]<br />
*[[Scenariusz 1 - Kalkulator prosty]]<br />
*[[Scenariusz 2 - Squash]]<br />
*[[Scenariusz 3 - Rysowanie palcem po ekranie]]<br />
*[[Scenariusz 4 - Spaceshooter]]<br />
*[[Scenariusz 5 - Chat Bluetooth]]<br />
*[[Scenariusz 6 - Tablica ogłoszeń]]<br />
*[[Scenariusz 7 - Kalkulator (prawie) pełny]]<br />
<br />
===Tłumaczenia===<br />
Tłumaczenia tutoriali ze strony [http://appinventor.mit.edu/explore/ai2/support/blocks.html MIT App Inventor]<br />
<br />
*[[Jak podłączyć telefon lub tablet przez WiFi?]]<br />
*[[Hello Purr]]<br />
*[[Bouncing Ball]]<br />
*[[MoleMash]]<br />
*[[Magic Ball]]<br />
*[[QuizMe]]<br />
<br />
===Opis bloków===<br />
Opisy przygotowane na podstawie materiałów ze strony [http://appinventor.mit.edu/explore/ai2/tutorials.html MIT App Inventor]<br />
<br />
* [[Bloki kontrolne]]<br />
* [[Bloki logiczne]]<br />
* [[Bloki matematyczne]]<br />
* [[Bloki tekstowe]]<br />
* [[Bloki listowe]]<br />
* [[Bloki kolorów]]<br />
* [[Bloki zmiennych]]<br />
* [[Bloki procedur]]<br />
<br />
===Projekty===<br />
Pliki '''.aia''' i '''.apk''' do ewentualnego wykorzystania w trakcie zajęć App Inventor.<br />
<br />
*'''"Tylko media"''' - projekt bez ''layout'' i kodu - wczytane pliki mediów (grafika, dźwięk);<br />
*'''"Szablon"''' - projekt z plikami mediów i ''layoutem'' - bez kodu;<br />
*'''"Kod źródłowy"''' - kompletny plik .aia;<br />
*'''"Aplikacja"''' - plik instalacyjny (.apk);<br />
<br />
{| class="wikitable" border="0"<br />
|-<br />
! Projekt<br />
! Tylko media<br />
! Szablon<br />
! Kod źródłowy<br />
! Aplikacja<br />
|-<br />
|<br />
* Hello ''imię''<br />
* Nie klikaj<br />
* Rysowanie<br />
* Spaceshooter<br />
* Zgadnij liczbę<br />
* Kalkulator<br />
* zgadywanka Animals<br />
* Kamień, papier, nożyce<br />
|<br />
* <br />
* <br />
* <br />
* <br />
* <br />
* <br />
* [http://1drv.ms/1CCq6hW plik '''.aia''']<br />
* [http://1drv.ms/1BbAcDe plik '''.aia''']<br />
|<br />
* <br />
* <br />
* [http://1drv.ms/1zQ6uA6 plik '''.aia''']<br />
* <br />
* [http://1drv.ms/1G29BJS plik '''.aia''']<br />
* [http://1drv.ms/18m9Uny plik '''.aia''']<br />
* [http://1drv.ms/1CCpGYU plik '''.aia''']<br />
* [http://1drv.ms/18m5mNR plik '''.aia''']<br />
|<br />
* [http://1drv.ms/18lSwzl plik '''.aia''']<br />
* [http://1drv.ms/17NqM6M plik '''.aia''']<br />
* [http://1drv.ms/1wYgg2J plik '''.aia''']<br />
* [http://1drv.ms/18lSTd1 plik '''.aia''']<br />
* [http://1drv.ms/1G29BJS plik '''.aia''']<br />
* [http://1drv.ms/1EjbZPk plik '''.aia''']<br />
* [http://1drv.ms/1EjckBB plik '''.aia''']<br />
* [http://1drv.ms/1Ejcxof plik '''.aia''']<br />
|<br />
* [http://1drv.ms/1wYg1F3 plik '''.apk''']<br />
* [http://1drv.ms/1wGFVT3 plik '''.apk''']<br />
* [http://1drv.ms/1A10Jk3 plik '''.apk''']<br />
* [http://1drv.ms/1w7rvuE plik '''.apk''']<br />
* [http://1drv.ms/1w7sqvc plik '''.apk''']<br />
* [http://1drv.ms/1BUq8SP plik '''.apk''']<br />
* [http://1drv.ms/1wYkN5t plik '''.apk''']<br />
* [http://1drv.ms/1DQ7Z3s plik '''.apk''']<br />
|}</div>M Kelniarzhttp://wiki.mistrzowiekodowania.pl/index.php?title=Strona_g%C5%82%C3%B3wnaStrona główna2015-09-14T07:15:20Z<p>M Kelniarz: </p>
<hr />
<div>[[Plik:Logo_Mistrzowie.png|center]]<br />
<br />
<br />
<br />
''Witaj na stronie ze scenariuszami!''<br />
<br />
'''Wszystkie scenariusze w wersji .pdf mozesz znaleźc [https://www.dropbox.com/sh/9e29fdqcgseh65w/AABm12kGHhxg_fzzspVLyac8a?dl=0 '''TUTAJ''']'''<br />
<br />
==Scratch==<br />
===Scenariusze===<br />
<br />
* [[Quiz o Scratch]] <br />
<br />
''' Scenariusze dla klas 4-6 szkoły podstawowej'''<br />
<br />
''' Scenarios dedicated to primary school learners, 4th - 6th grade (basic level)'''<br />
<br />
{| class="wikitable" border="0"<br />
|-<br />
! Wersja polska<br />
! English version<br />
|-<br />
|<br />
* [[Wprowadzenie 1 - Korzystanie z konta Scratch]]<br />
* [[Wprowadzenie 2 - Opis środowiska Scratch]]<br />
* [[Wprowadzenie 3 - Słowniczek podstawowych bloków]]<br />
* [[Moduł 1 - "Pierwsze kroki w Scratch'u"]]<br />
* [[Moduł 2 - "Kot goni mysz"]]<br />
* [[Moduł 3 - "Kot w labiryncie"]]<br />
* [[Moduł 4 - "Kot zastawia pułapkę na mysz"]]<br />
* [[Moduł 5 - "Gra zręcznościowa - odbijanie piłeczki"]]<br />
* [[Moduł 6 - "Gra logiczna - zgadywanie liczby"]]<br />
* [[Moduł 7 - „Zawody lekkoatletyczne duszków”]]<br />
* [[Moduł 8 - „Multimedialna kartka świąteczna”]]<br />
|<br />
* [[Introduction 1 - Using a Scratch account]]<br />
* [[Introduction 2 - Description of the Scratch environment]]<br />
* [[Introduction 3 - Glossary of basic Scratch 2.0 blocks]]<br />
* [[Module 1 - Getting started in Scratch]]<br />
* [[Module 2 - The “Cat Chasing a Mouse” Project]]<br />
* [[Module 3 - The “Cat in a Maze” Project ]]<br />
* [[Module 4 - The “Cat Sets a Trap for the Mouse” Project]]<br />
* [[Module 5 - The “Bounce the Ball Arcade Game” Project]]<br />
* [[Module 6 - The “Guess the NumberLogic Game” Project]]<br />
* [[Module 7 - The “Sprites’ Track and Field Competition” Project]]<br />
* [[Module 8 - The “Multimedia Christmas Card” Project]]<br />
|}<br />
<br />
<br />
<br />
{| class="wikitable" border="0"<br />
|-<br />
! Szkoła podstawowa (klasy 1-3)<br />
! Szkoła podstawowa (klasy 4-6)<br />
! Gimnazjum<br />
|-<br />
|<br />
* [[Cykl życia motyla]]<br />
* [[Animacja poklatkowa: wzrost kwiatka]]<br />
* [[Interpretacja wiersza]]<br />
* [[Literowanie]]<br />
* [[Aplikacja do rysowania]]<br />
* [[Sumowanie]]<br />
* [[Segregacja odpadów]]<br />
* [[Gra kamień-nożyce-papier]]<br />
* [[Wyścigówka (wersja A)]]<br />
|<br />
* [[Interaktywna mapa Polski (punkty)]]<br />
* [[Animacja - układ pokarmowy]]<br />
* [[Maszynka losująca]]<br />
* [[Czasomierz lekcyjny]]<br />
* [[Arkanoid]]<br />
* [[Generator wielokątów]]<br />
* [[Wyścigówka (wersja B)]]<br />
* [[Gra platformowa]]<br />
|<br />
* [[Interaktywna mapa Polski (województwa)]]<br />
* [[Animacja - układ pokarmowy (wersja B)]]<br />
* [[Maszynka losująca (wersja B)]]<br />
* [[Czasomierz lekcyjny]]<br />
* [[Arkanoid (wersja B)]]<br />
* [[Labirynt]]<br />
* [[Generator wielokątów]]<br />
* [[Wyścigówka (wersja C)]]<br />
* [[Gra platformowa (wersja z przesuwanym tłem)]]<br />
|}<br />
<br />
==App Inventor==<br />
===Scenariusze===<br />
*[[Wprowadzenie]]<br />
*[[Scenariusz 1 - Kalkulator prosty]]<br />
*[[Scenariusz 2 - Squash]]<br />
*[[Scenariusz 3 - Rysowanie palcem po ekranie]]<br />
*[[Scenariusz 4 - Spaceshooter]]<br />
*[[Scenariusz 5 - Chat Bluetooth]]<br />
*[[Scenariusz 6 - Tablica ogłoszeń]]<br />
*[[Scenariusz 7 - Kalkulator (prawie) pełny]]<br />
<br />
===Tłumaczenia===<br />
Tłumaczenia tutoriali ze strony [http://appinventor.mit.edu/explore/ai2/support/blocks.html MIT App Inventor]<br />
<br />
*[[Jak podłączyć telefon lub tablet przez WiFi?]]<br />
*[[Hello Purr]]<br />
*[[Bouncing Ball]]<br />
*[[MoleMash]]<br />
*[[Magic Ball]]<br />
*[[QuizMe]]<br />
<br />
===Opis bloków===<br />
Opisy przygotowane na podstawie materiałów ze strony [http://appinventor.mit.edu/explore/ai2/tutorials.html MIT App Inventor]<br />
<br />
* [[Bloki kontrolne]]<br />
* [[Bloki logiczne]]<br />
* [[Bloki matematyczne]]<br />
* [[Bloki tekstowe]]<br />
* [[Bloki listowe]]<br />
* [[Bloki kolorów]]<br />
* [[Bloki zmiennych]]<br />
* [[Bloki procedur]]<br />
<br />
===Projekty===<br />
Pliki '''.aia''' i '''.apk''' do ewentualnego wykorzystania w trakcie zajęć App Inventor.<br />
<br />
*'''"Tylko media"''' - projekt bez ''layout'' i kodu - wczytane pliki mediów (grafika, dźwięk);<br />
*'''"Szablon"''' - projekt z plikami mediów i ''layoutem'' - bez kodu;<br />
*'''"Kod źródłowy"''' - kompletny plik .aia;<br />
*'''"Aplikacja"''' - plik instalacyjny (.apk);<br />
<br />
{| class="wikitable" border="0"<br />
|-<br />
! Projekt<br />
! Tylko media<br />
! Szablon<br />
! Kod źródłowy<br />
! Aplikacja<br />
|-<br />
|<br />
* Hello ''imię''<br />
* Nie klikaj<br />
* Rysowanie<br />
* Spaceshooter<br />
* Zgadnij liczbę<br />
* Kalkulator<br />
* zgadywanka Animals<br />
* Kamień, papier, nożyce<br />
|<br />
* <br />
* <br />
* <br />
* <br />
* <br />
* <br />
* [http://1drv.ms/1CCq6hW plik '''.aia''']<br />
* [http://1drv.ms/1BbAcDe plik '''.aia''']<br />
|<br />
* <br />
* <br />
* [http://1drv.ms/1zQ6uA6 plik '''.aia''']<br />
* <br />
* [http://1drv.ms/1G29BJS plik '''.aia''']<br />
* [http://1drv.ms/18m9Uny plik '''.aia''']<br />
* [http://1drv.ms/1CCpGYU plik '''.aia''']<br />
* [http://1drv.ms/18m5mNR plik '''.aia''']<br />
|<br />
* [http://1drv.ms/18lSwzl plik '''.aia''']<br />
* [http://1drv.ms/17NqM6M plik '''.aia''']<br />
* [http://1drv.ms/1wYgg2J plik '''.aia''']<br />
* [http://1drv.ms/18lSTd1 plik '''.aia''']<br />
* [http://1drv.ms/1G29BJS plik '''.aia''']<br />
* [http://1drv.ms/1EjbZPk plik '''.aia''']<br />
* [http://1drv.ms/1EjckBB plik '''.aia''']<br />
* [http://1drv.ms/1Ejcxof plik '''.aia''']<br />
|<br />
* [http://1drv.ms/1wYg1F3 plik '''.apk''']<br />
* [http://1drv.ms/1wGFVT3 plik '''.apk''']<br />
* [http://1drv.ms/1A10Jk3 plik '''.apk''']<br />
* [http://1drv.ms/1w7rvuE plik '''.apk''']<br />
* [http://1drv.ms/1w7sqvc plik '''.apk''']<br />
* [http://1drv.ms/1BUq8SP plik '''.apk''']<br />
* [http://1drv.ms/1wYkN5t plik '''.apk''']<br />
* [http://1drv.ms/1DQ7Z3s plik '''.apk''']<br />
|}</div>M Kelniarzhttp://wiki.mistrzowiekodowania.pl/index.php?title=QuizMeQuizMe2015-03-15T18:42:20Z<p>M Kelniarz: /* Zeskanuj próbną aplikację do telefonu */</p>
<hr />
<div>=Aplikacja QuizMe dla App Inventor 2=<br />
<br />
==Co tworzysz?==<br />
[[Plik:t6-1.png|right]]QuizMe to gra dotycząca ciekawostek baseballowych, ale można jej użyć jako szablonu do tworzenia quizów z dowolnej dziedziny. W aplikacji użytkownik odpowiada na szereg pytań, otrzymując następnie informację zwrotną, czy udzielił poprawnej, czy błędnej odpowiedzi. Gracz przechodzi do kolejnego pytania, klikając przycisk.<br />
<br />
W grze QuizMe dysponujemy zamkniętym zbiorem pytań, chyba że programista je zmieni. W następnym etapie można utworzyć MakeQuiz & TakeQuiz – aplikację, która pozwala użytkownikom na tworzenie i modyfikowanie pytań.<br />
<br />
Poradnik ten zakłada, że znasz już podstawy tworzenia aplikacji w App Inventorze – korzystanie z Projektanta komponentów w celu utworzenia interfejsu użytkownika i z Edytora bloków, aby określić obsługę zdarzeń. Jeżeli potrzebujesz przypomnienia, spróbuj popracować z poradnikami podstawowymi zanim przejdziesz dalej.<br />
<br />
==Zaczynamy!==<br />
Połącz się z witryną internetową App Inventor i załóż nowy projekt. Nazwij go QuizMe, ustaw taki sam tytuł ekranu (Title). Za pomocą MIT AI2 Companion połącz program z urządzeniem mobilnym. Pobierz poniższe zdjęcia baseballistów i zapisz je w komputerze. Później załadujesz je do projektu.<br />
<ul><li> [http://beta.appinventor.mit.edu/learn/tutorials/quizme/QuizMeAssets/Larsenberra.jpg Larsenberra.jpg]</li><br />
<li> [http://beta.appinventor.mit.edu/learn/tutorials/quizme/QuizMeAssets/dallasbraden.jpg Dallasbraden.jpg]</li><br />
<li> [http://beta.appinventor.mit.edu/learn/tutorials/quizme/QuizMeAssets/cyyoung.jpg Cyyoung.jpg]</li><br />
<li> [http://beta.appinventor.mit.edu/learn/tutorials/quizme/QuizMeAssets/nolanryan.jpg Nolanryan.jpg]</li></ul><br />
<br />
==Wstęp==<br />
Zaprojektujesz grę typu quiz, w której użytkownik będzie przechodził do kolejnych pytań, klikając przycisk Dalej, a następnie otrzymywał prostą ocenę Dobrze/Źle dla każdej odpowiedzi.<br />
<br />
W tym przewodniku omówimy:<br />
<ul><li>definiowanie i wyświetlanie listy informacji;</li><br />
<li>przechodzenie przez listę za pomocą zmiennej indeksującej – zmiennej, która śledzi pozycję na liście;</li><br />
<li>zachowania warunkowe – wykonywanie określonych operacji tylko wtedy, gdy spełniony jest określony warunek;</li><br />
<li>Zmianę zdjęcia w zależności od sytuacji.</li></ul><br />
<br />
==Projektowanie aplikacji==<br />
Użyj Projektanta komponentów do utworzenia interfejsu dla aplikacji QuizMe. <br />
Aby utworzyć interfejs, najpierw załaduj do projektu pobrane zdjęcia. Kliknij przycisk Prześlij plik (Upload File...) w obszarze Media i wybierz jeden z pobranych wcześniej plików (np. Larsenberra.jpg). Następnie zrób to samo z pozostałymi trzema zdjęciami.<br />
Utwórz następujące komponenty, przeciągając je z Palety (Palette) do Przeglądarki (Viewer) i ustaw właściwości komponentów zgodnie z poniższym opisem:<br />
{|class="wikitable"<br />
! Typ komponentu<br />
! Kategoria<br />
! Jaką nadać jej nazwę<br />
! Działanie<br />
! Działanie komponentu<br />
|-<br />
|Image<br />
|User interface<br />
|Image1<br />
|Ustaw właściwość zdjęcia (Picture) na Larsenberra.jpg. Jest to pierwsze wyświetlane zdjęcie.<br />
|Obrazkowa część pytania<br />
|-<br />
|Label<br />
|User interface<br />
|QuestionLabel<br />
|Zmień właściwość tekstu (Text) na Pytanie:<br />
|Wyświetla bieżące pytanie<br />
|-<br />
|HorizontalArrangement<br />
|Layout<br />
|HorizontalArrangement1<br />
| <br />
|Organizuje komponenty AnswerPrompt i Text (podaj odpowiedź i tekst)<br />
|-<br />
|Label<br />
|User interface<br />
|AnswerPromptLabel<br />
|Zmień właściwość tekstu (Text) na Podaj odpowiedź:. Na ekranie przeglądarki przesuń tę etykietę do HorizontalArrangement1.<br />
|Wyświetla tekst prośby o odpowiedź.<br />
|-<br />
|TextBox<br />
|User interface<br />
|AnswerText<br />
|Zmień wskazówkę (Hint) na Podaj odpowiedź. Na ekranie przeglądarki przenieś AnswerText do komponentu HorizontalArrangement1.<br />
|Tutaj użytkownik podaje odpowiedź.<br />
|-<br />
|Label<br />
|User interface <br />
|RightWrongLabel<br />
|Zmień właściwość tekstu (Text) na Dobrze/Źle.<br />
|Tutaj wyświetlana jest ocena Dobrze/Źle.<br />
|-<br />
|HorizontalArrangement<br />
|Layout<br />
|HorizontalArrangement2<br />
|<br />
|Organizuje przyciski AnswerButton i NextButton (przycisk odpowiedzi i przycisk dalej).<br />
|-<br />
|Przycisk<br />
|User interface<br />
|AnswerButton<br />
|Zmień właściwość tekstu (Text) na Wyślij. Na ekranie przeglądarki przesuń ten przycisk do HorizontalArrangment2.<br />
|Użytkownik klika, aby przesłać odpowiedź.<br />
|-<br />
|Przycisk<br />
|User interface<br />
|NextButton<br />
|Zmień właściwość tekstu (Text) na Dalej. Przenieś ten przycisk do HorizontalArrangement2.<br />
|Użytkownik klika, aby przejść do następnego pytania.<br />
|} <br />
Po zakończeniu powinien on wyglądać jak poniższa ilustracja (pod nią znajdują się również bardziej szczegółowe informacje).<br />
[[Plik:t6-2.png]]<br />
<br />
==Programowanie aplikacji==<br />
Otwórz Edytor bloków, aby zaprogramować działanie komponentów. Najpierw zdefiniuj dwie zmienne - listy: zmienną QuestionList, zawierającą listę pytań i zmienną AnswerList z listą odpowiedzi na te pytania.<br />
<br />
Aby zdefiniować te dwie zmienne listy, potrzebujesz następujących bloków:<br />
{| class="wikitable"<br />
!Typ bloku<br />
!Kategoria<br />
!Działanie<br />
|-<br />
|initialize global name to<br />
|Variables<br />
|Definiuje zmienną QuestionList (zmień jej nazwę)<br />
|-<br />
|initialize global name to<br />
|Variables<br />
|Definiuje zmienną AnswerList (zmień jej nazwę)<br />
|-<br />
|make a list<br />
|Lists<br />
|Służy do dodawania elementów do zmiennej QuestionList<br />
|-<br />
|„ „ (trzykrotnie)<br />
|Lists<br />
|Służy do wpisania pytań<br />
|-<br />
|make a list<br />
|Lists<br />
|Służy do dodawania elementów do zmiennej AnswerList<br />
|-<br />
|„ „ (trzykrotnie)<br />
|Text<br />
|Służy do wpisania odpowiedzi<br />
|}<br />
Utwórz zmienne całościowe, przeciągając z kategorii zmiennych (Variables) na obszar roboczy blok Initialize global name to. Kliknij dwukrotnie domyślną nazwę name, aby ją zmienić. Blok Initialize global name to zawiera pole na początkową wartość zmiennej. Zmienna może zawierać liczbę, tekst, a nawet listę – aby ją utworzyć, podłącz blok Make a list do definicji zmiennej.<br />
<br />
Bloki powinny wyglądać następująco:<br />
<br />
[[Plik:t6-3.png]]<br />
===Zdefiniuj ukrytą zmienną Index===<br />
Za każdym razem, gdy użytkownik kliknie przycisk NextButton, aby przejść dalej, aplikacja musi pamiętać, przy którym pytaniu jest obecnie gracz. W języku programowania, aby coś zapamiętać, trzeba zdefiniować nową zmienną. W tym przypadku aplikacja musi zapamiętać bieżący numer pytania – indeks listy QuestionList.<br />
Aby zdefiniować zmienną currentQuestionIndex, potrzebujesz następujących bloków:<br />
{| class="wikitable"<br />
!Typ bloku<br />
!Kategoria<br />
!Działanie<br />
|-<br />
|initialize global name to<br />
|Variables<br />
|Definiuje zmienną currentQuestionIndex (zmień nazwę)<br />
|-<br />
|0 (1)<br />
|Math<br />
|Ustaw wartość początkową currentQuestionIndex na 1 (zmień liczbę)<br />
|}<br />
Bloki powinny wyglądać następująco:<br />
<br />
[[Plik:t6-4.png]]<br />
<br />
===Wyświetl pierwsze pytanie===<br />
Odłóż na razie kwestię odpowiedzi i skup się na zaprogramowaniu sekwencyjnego przejścia przez pytania. Pożądane zachowanie jest następujące: po uruchomieniu aplikacji na etykiecie o nazwie QuestionLabel pojawia się pierwsze pytanie. Gdy użytkownik kliknie NextButton, wyświetlone zostaje drugie pytanie. Po ponownym kliknięciu pojawia się trzecie pytanie. Po dotarciu do ostatniego pytania kliknięcie przycisku NextButton powoduje ponowne pojawienie się pierwszego pytania w etykiecie QuestionLabel.<br />
<br />
W programie App Inventor określone pozycje na liście są wybierane za pomocą bloku select list item. W tym bloku trzeba podać listę i indeks – pozycję na liście. Jeżeli na liście są trzy pozycje, prawidłowe indeksy to 1, 2 i 3.<br />
<br />
Po uruchomieniu aplikacja QuizMe powinna wybrać pierwsze pytanie z listy i wyświetlić je w komponencie QuestionLabel. Do tego zachowania inicjalizującego działanie aplikacji potrzebne są następujące bloki:<br />
<br />
{| class="wikitable"<br />
!Typ bloku<br />
!Kategoria<br />
!Działanie<br />
|-<br />
|when Screen1.Initialize<br />
|Screen1<br />
|Podczas uruchamiania aplikacji zainicjowana jest ta obsługa zdarzenia<br />
|-<br />
|set QuestionLabel.Text to<br />
|QuestionLabel<br />
|Umieszcza pierwsze pytanie w etykiecie QuestionLabel<br />
|-<br />
|select list item<br />
|Lists<br />
|Wybiera pierwsze pytanie z etykiety QuestionLabel<br />
|-<br />
|get <br />
|Variables<br />
|Ustala listę, z której jest wybierany element. Tutaj: Global QuestionList<br />
|-<br />
|0 (1)<br />
|Math<br />
|Wybiera pierwsze pytanie za pomocą indeksu 1. Ustaw wartość na 1.<br />
|}<br />
Bloki powinny wyglądać następująco:<br />
<br />
[[Plik:t6-5.png]]<br />
<br />
===Jak działają bloki?===<br />
Zdarzenie when Screen1.Initialize jest wyzwalane podczas uruchomienia aplikacji. Pierwsza pozycja zmiennej QuestionList zostaje wybrana i umieszczona w bloku set QuestionLabel.Text. Gdy aplikacja zostanie uruchomiona, użytkownik zobaczy pierwsze pytanie.<br />
===Przetestuj to zachowanie===<br />
Jeśli dotychczas nie skomunikowałeś urządzenia mobilnego z programem, zrób to teraz. Co pojawia się na urządzeniu? Jeżeli utworzono listę QuestionList tak, jak wskazano powyżej, w etykiecie QuestionLabel powinna pojawić się pierwsza pozycja tej listy (Kto był doskonałym miotaczem w World Series?).<br />
<br />
==Iteracja pytań==<br />
Zdefiniowałeś już zmienną CurrentQuestionIndex, zapamiętującą pytanie, przy którym znajduje się użytkownik. Zaprogramuj teraz zachowanie przycisku NextButton. Gdy zostanie on kliknięty, aplikacja zwiększy wartość zmiennej, np. zmieni ją z 1 na 2 lub z 2 na 3 itd., a następnie użyje tej wartości do zaznaczenia nowego bieżącego pytania. Do tego zachowania potrzebne są następujące bloki:<br />
{| class="wikitable"<br />
!Typ bloku<br />
!Kategoria<br />
!Działanie<br />
|-<br />
|when NextButton.Click<br />
|NextButton<br />
|Uruchamia obsługę zdarzeń po kliknięciu przycisku<br />
|-<br />
|set currentQuestionIndex to<br />
|Zmienne<br />
|Decyduje o ustawieniu indeksu wybranej listy<br />
|-<br />
|+ <br />
|Math<br />
|Służy do zwiększania wartości zmiennej currentQuestionIndex<br />
|-<br />
|get global currentQuestionIndex<br />
|Zmienne<br />
|Tworzy nową wartość poprzez zwiększenie poprzedniej wartości o 1<br />
|-<br />
|0 (1)<br />
|Math<br />
|Dla + 1<br />
|-<br />
|set QuestionLabel.Text to<br />
|QuestionLabel<br />
|Wyświetla kolejne pytanie<br />
|-<br />
|select list item<br />
|Listy<br />
|Ustawia element listy jako wartość QuestionLabel<br />
|-<br />
|get global QuestionList<br />
|Zmienne<br />
|Wskazuje, która lista będzie wybrana<br />
|-<br />
|get global currentQuestionIndex<br />
|Zmienne<br />
|Wskazuje, który element wybranej listy będzie wybrany<br />
|}<br />
Bloki powinny wyglądać następująco:<br />
<br />
[[Plik:t6-6.png]]<br />
<br />
===Jak działają bloki?===<br />
Pierwszy wiersz polecenia zwiększa wartość zmiennej currentQuestionIndex o 1 (jeżeli zmienna zawiera wartość 1, zostaje ona zmieniona na 2, z 2 na 3 itd.). Następnie wykorzystuje nową wartość do wyboru pytania o tym indeksie.<br />
<br />
Przypomnijmy, że w bloku obsługi zdarzeń Screen.Initialize aplikacja wybrała pierwsze do wyświetlenia pytanie:<br />
<br />
[[Plik:t6-7.png]]<br />
<br />
Po kliknięciu przycisku NextButton aplikacja nie wybiera konkretnie pierwszej, drugiej czy trzeciej pozycji na liście, tylko pozycję o n-tej wartości zmiennej currentQuestionIndex.<br />
<br />
[[Plik:t6-8.png]]<br />
<br />
Polecenia w blokach są wykonywane od prawej do lewej, tzn. aplikacja najpierw określa wartość parametru z bloku Select list item, którym jest zmienna CurrentQuestionIndex. Liczba zawarta w tej zmiennej zostaje użyta jako indeks podczas wykonania poleceń zawartych w bloku Select list item.<br />
<br />
[[Plik:info.png|left]]''Po pierwszym kliknięciu przycisku NextButton, wartość zmiennej currentQuestionIndex przeskoczy z 1 na 2, aby aplikacja wybrała drugą pozycję z listy QuestionList (Kto był pierwszym doskonałym miotaczem w 2010?). Po drugim kliknięciu przycisku NextButton, wartość zmiennej currentQuestionIndex zostanie zmieniona z 2 na 3, a aplikacja wybierze trzecie pytanie z listy (Kto był pierwszym doskonałym miotaczem nowej ery?).''<br />
<br />
<br />
===Przetestuj to zachowanie===<br />
Przetestuj zachowanie przycisku NextButton, aby sprawdzić, czy aplikacja działa poprawnie. Wciel się w rolę użytkownika i kliknij przycisk NextButton w telefonie. Czy urządzenie wyświetliło drugie pytanie: Kto był pierwszym doskonałym miotaczem w 2010?? Trzecie pytanie powinno pojawić się po kolejnym kliknięciu przycisku. Jeżeli aplikacja działa, pogratuluj sobie i przejdź dalej. Kliknij przycisk NextButton ponownie (po raz trzeci). Powinien zostać wyświetlony błąd: Próba uzyskania elementu 4 z listy o długości 3. Czy wiesz, na czym polega problem?<br />
<br />
Problem z aplikacją polega na tym, że zawsze po kliknięciu przycisku NextButton zwiększa ona zmienną CurrentQuestionIndex o 1. Gdy wartość zmiennej wynosi już 3, a użytkownik kolejny raz kliknie przycisk NextButton, aplikacja zmieni wartość zmiennej z 3 na 4, następnie wywoła blok Select list item, aby odczytać pozycję o aktualnym indeksie CurrentQuestionIndex, czyli w tym przypadku czwartą pozycję. Ponieważ zmienna QuestionList zawiera tylko trzy elementy, Android wykaże błąd.<br />
<br />
Aplikacja musi zadawać pytanie - sprawdzać warunek - gdy nastąpi kliknięcie przycisku NextButton i realizować polecenia zawarte w różnych blokach w zależności od odpowiedzi. Elementem do sprawdzenia jest to, czy zmienna CurrentQuestionIndex już ma wartość 3. Jeżeli tak - należy ustawić CurrentQuestionIndex z powrotem na 0, aby użytkownik wrócił do pierwszego pytania.<br />
<br />
Będziesz potrzebował następujących bloków:<br />
{| class="wikitable"<br />
!Typ bloku<br />
!Kategoria<br />
!Działanie<br />
|-<br />
|if then<br />
|Control<br />
|sprawdzenie, czy użytkownik jest na etapie ostatniego pytania<br />
|-<br />
|= <br />
|Math<br />
|sprawdzenie, czy currentQuestionIndex ma wartość 3<br />
|-<br />
|get global currentQuestionIndex<br />
|Variables<br />
|<br />
|-<br />
|0 (3)<br />
|Math<br />
|3 to numer na liście<br />
|-<br />
|set currentQuestionIndex to<br />
|Variables<br />
|ustawienie na 0, aby wrócić do pierwszego pytania<br />
|-<br />
|0<br />
|Math<br />
|ustawienie na 0, ponieważ kolejne bloki zwiększą wartość do 1<br />
|}<br />
Zmodyfikowany blok obsługi zdarzenia When NextButton.Click powinien wyglądać następująco:<br />
<br />
[[Plik:t6-9.png]]<br />
<br />
===Jak działają bloki===<br />
Po kliknięciu przycisku NextButton aplikacja najpierw sprawdza, czy currentQuestionIndex ma wartość 3. Jeżeli tak, wartość tej zmiennej jest ustawiana na 0, aby po zwiększeniu jej w dalszych krokach jej wartość wyniosła 1. Wtedy quiz wróci do pierwszego pytania. Zauważ, że tylko bloki osadzone w bloku if-then są zależne od warunku. Blok zwiększenia wartości i blok Set QuestionLabel.Text to są wykonywane bez względu na jakikolwiek warunek.<br />
<br />
==Aplikacja modyfikowalna: Ułatwianie modyfikowania pytań==<br />
Teraz zmodyfikujemy aplikację, aby można było łatwo dodawać i usuwać elementy z listy. Zmień bloki tak, aby działały na liście o dowolnej długości, a nie tylko liście z dokładnie trzema pozycjami. <br />
Na początek dodaj czwarte pytanie do zmiennej QuestionList i kolejną odpowiedź do AnswerList. W tym celu musisz najpierw zwiększyć liczbę dostępnych pól za pomocą przycisku modyfikującego (mutatora). Aby dowiedzieć się więcej o tym elemencie, zobacz: http://appinventor.mit.edu/explore/ai2/support/concepts/mutators. Bloki powinny wyglądać następująco:<br />
<br />
[[Plik:t6-10.png]]<br />
<br />
===Przetestuj zmodyfikowaną aplikację.===<br />
Kliknij przycisk NextButton kilka razy. Zauważysz, że czwarte pytanie nigdy się nie pojawia, bez względu na to, ile razy klikniesz przycisk.<br />
<br />
Problemem jest to, że test sprawdzający, czy użytkownik znajduje się przy ostatnim pytaniu, jest zbyt szczegółowy: pyta, czy zmienna CurrentQuestionIndex ma wartość 3:<br />
<br />
[[Plik:t6-11.png]]<br />
<br />
Możesz po prostu zmienić liczbę z 3 na 4, a aplikacja będzie znów działać poprawnie. Problem polega jednak na tym, że za każdym razem, gdy zmodyfikujesz liczbę pytań i odpowiedzi, będziesz musiał pamiętać, aby dokonać także tej zmiany. Takie zależności w programie komputerowym często prowadzą do błędów, w szczególności gdy aplikacja staje się bardziej złożona. Znacznie lepiej jest przygotować program w taki sposób, aby działał niezależnie od liczby pytań. Takie uogólnienie jest jeszcze ważniejsze, gdy lista, z którą pracujesz, zmienia się dynamicznie, na przykład w aplikacji z quizem, gdzie użytkownik może dodawać nowe pytania.<br />
<br />
Lepszym rozwiązaniem jest sprawdzenie warunku w sposób bardziej ogólny. Tak naprawdę chcesz wiedzieć, czy bieżące pytanie – czyli wartość zmiennej currentQuestionIndex jest tak duża, jak ilość elementów w zmiennej QuestionList. Jeżeli aplikacja sprawdzi warunek w bardziej ogólny sposób, to będzie działać, nawet jeżeli dodasz lub usuniesz elementy ze zmiennej QuestionList. Aby zmienić blok obsługi zdarzenia When NextButton.Click, zmień poprzedni test sprawdzający, który odnosił się bezpośrednio do 3. Będziesz potrzebował następujących bloków:<br />
{| class="wikitable"<br />
!Typ bloku<br />
!Szuflada<br />
!Działanie<br />
|-<br />
|length of list<br />
|Lists<br />
|Pyta, ile elementów jest w zmiennej QuestionList<br />
|-<br />
|get global QuestionList<br />
|Variables<br />
|Określa, o którą listę chodzi<br />
|}<br />
Blok obsługi zdarzenia When NextButton.Click powinien teraz wyglądać następująco:<br />
<br />
[[Plik:t6-12.png]]<br />
<br />
<br />
<br />
===Jak działają bloki?===<br />
Warunek if porównuje teraz wartość zmiennej CurrentQuestionIndex z długością zmiennej QuestionList. Zatem jeżeli zmienna CurrentQuestionIndex ma wartość 4, a długość zmiennej QuestionList wynosi 4, to wartość zmiennej currentQuestionIndex zostanie ustawiona na 0 (a następnie na 1, 2 itd.). Zauważ - bloki nie odwołują się już do 3 ani żadnej innej określonej wartości, dlatego instrukcja będzie działać bez względu na liczbę elementów listy.<br />
<br />
Przetestuj zmodyfikowane zachowanie. Czy po kliknięciu przycisku NextButton aplikacja przechodzi teraz przez cztery pytania, wracając po ostatnim do pierwszego?<br />
<br />
==Przełączanie zdjęcia dla każdego pytania==<br />
Na razie aplikacja wyświetla to samo zdjęcie, bez względu na to, jakie pytanie zostaje zadane. Możesz to zmienić tak, aby po kliknięciu przycisku NextButton pojawiała się fotografia dotycząca danego pytania. W obszarze Media dostępne są cztery dodane wcześniej zdjęcia. Teraz utworzymy trzecią listę - PictureList, której elementami będą nazwy plików zdjęć, a następnie zmodyfikujemy blok obsługi zdarzenia When NextButton.Click, aby program po każdym pytaniu przełączał zdjęcie.<br />
Najpierw utwórz listę PictureList i zainicjuj ją nazwami plików graficznych. Upewnij się, czy nazwy są dokładnie takie same jak nazwy plików, które zostały załadowane do obszaru Media. Oto jak powinien wyglądać blok dla listy PictureList:<br />
<br />
[[Plik:t6-13.png]]<br />
<br />
Następnie zmodyfikuj blok obsługi zdarzeń When NextButton.Click, aby zmieniał wyświetlane zdjęcie w zależności od zadanego pytania. Jeżeli ustawisz właściwość Image.Picture na nazwę pliku zdjęcia, które zostało załadowane, właśnie ta fotografia zostanie wyświetlona. Aby zmodyfikować blok When NextButton.Click, potrzebujesz następujących bloków:<br />
{| class="wikitable"<br />
!Typ bloku<br />
!Kategoria<br />
!Działanie<br />
|-<br />
|set Image1.Picture to<br />
|Image1<br />
|ustaw, aby zmieniać zdjęcie<br />
|-<br />
|select list item<br />
|Lists<br />
|należy wybrać zdjęcie odpowiadające na aktualne pytanie<br />
|-<br />
|get global PictureList<br />
|Variables<br />
|wybierz nazwę pliku z tej listy<br />
|-<br />
|get global currentQuestionIndex<br />
|Variables<br />
|wybierz element o n-tym indeksie currentQuestionIndex<br />
|}<br />
Oto jak powinny wyglądać bloki:<br />
<br />
[[Plik:t6-14.png]]<br />
<br />
===Jak działają bloki?===<br />
Zmienna CurrentQuestionIndex służy jako indeks dla zmiennej QuestionList. Wartość CurrentQuestionIndex wynosi 1, aplikacja wybiera pierwsze pytanie i pierwsze zdjęcie. Gdy CurrentQuestionIndex wynosi 2, aplikacja wybiera drugie pytanie i drugie zdjęcie. Oczywiście takie działanie zależy od tego, czy listy są ze sobą zsynchronizowane. Tak jest w tym przypadku - pierwszy obraz - LarsenBerra.jpg to zdjęcie Dona Larsena, jednocześnie Don Larsen to odpowiedź na pierwsze pytanie (Kto był doskonałym miotaczem w World Series?). <br />
Przetestuj zmodyfikowane zachowanie. Czy nowe zdjęcie pojawia się po każdym kliknięciu przycisku NextButton?<br />
<br />
==Ocena udzielanych odpowiedzi==<br />
Teraz dodamy bloki, które określają, czy użytkownik odpowiedział na pytanie prawidłowo, czy też nie. Gracz wprowadza odpowiedź do AnswerText, a następnie klika przycisk AnswerButton. Aplikacja musi porównać wpis użytkownika z odpowiedzią na bieżące pytanie, używając bloku if... then... w celu jej sprawdzenia. Etykieta RightWrongLabel powinna być modyfikowana, aby podawać, czy odpowiedź jest prawidłowa, czy nie.<br />
<br />
Do tego zachowania będą potrzebne następujące bloki:<br />
{| class="wikitable"<br />
!Typ bloku<br />
!Kategoria<br />
!Działanie<br />
|-<br />
|when AnswerButton.Click<br />
|AnswerButton<br />
|zachowanie jest wyzwalane, gdy użytkownik kliknie przycisk AnswerButton<br />
|-<br />
|if... then...<br />
|Control<br />
|Użyj mutatora, aby dodać alternatywę (else). Jeżeli odpowiedź jest prawidłowa - zrób jedno, w przeciwnym razie (else) - zrób coś innego<br />
|-<br />
|= <br />
|Math<br />
|sprawdzenie, czy odpowiedź jest prawidłowa<br />
|-<br />
|AnswerText.Text<br />
|AnswerText<br />
|Odpowiedź użytkownika pojawia się w tym polu tekstowym<br />
|-<br />
|select list item<br />
|Lists<br />
|wybrać bieżącą odpowiedź z listy AnswerList<br />
|-<br />
|get global AnswerList<br />
|Variables<br />
|lista, z której jest wybierany element<br />
|-<br />
|get global currentQuestionIndex<br />
|Variables<br />
|numer pytania (i numer odpowiedzi), przy którym jest użytkownik<br />
|-<br />
|set RightWrongLabel.Text to<br />
|RightWrongLabel<br />
|tutaj podaj odpowiedź<br />
|-<br />
|Dobrze!<br />
|Text<br />
|jeżeli odpowiedź jest prawidłowa<br />
|-<br />
|set RightWrongLabel.Text to<br />
|RightWrongLabel<br />
|tutaj podaj odpowiedź<br />
|-<br />
|Źle<br />
|Text<br />
|jeżeli odpowiedź jest nieprawidłowa<br />
|}<br />
Bloki powinny wyglądać następująco:<br />
<br />
[[Plik:t6-15.png]]<br />
<br />
===Jak działają bloki?===<br />
Test if sprawdza, czy odpowiedź użytkownika (AnswerText.Text) jest taka sama, jak element na liście AnswerList o indeksie równym wartości zmiennej CurrentQuestionIndex. Jeżeli zmienna CurrentQuestionIndex ma wartość 1, aplikacja porównuje odpowiedź użytkownika z pierwszą pozycją na liście AnswerList, (Don Larsen). Jeżeli zmienna CurrentQuestionIndex zmieni wartość na 2, program zestawia odpowiedź z drugą pozycją na liście, czyli Dallas Branden. Jeśli wynik porównania jest pozytywny, przeprowadzane są bloki then, a treść etykiety RightWrongLabel zostaje ustawiona na Dobrze!. Jeżeli wynik testu jest negatywny (fałszywy), przeprowadzane są bloki alternatywy (else), a treść etykiety RightWrongLabel zostaje ustawiona na Źle.<br />
<br />
Przetestuj zmodyfikowaną aplikację. Spróbuj odpowiedzieć na jedno z pytań. Powinna pojawić się ocena, czy odpowiedź była dokładnie taka sama, jak na liście AnswerList. Sprawdź zarówno prawidłowe, jak i nieprawidłowe odpowiedzi (Uwaga - uwzględniana jest wielkość liter!). Kliknij przycisk NextButton i odpowiedz na drugie pytanie. Czy aplikacja nadal działa? Powinna, ale zauważ, że gdy klikniesz przycisk NextButton, tekst Dobrze! lub Źle oraz poprzednia odpowiedź nadal będą wyświetlane. Choć nie wpływa to zasadniczo na naszą grę, to takie szczegóły interfejsu z pewnością zostaną zauważone przez użytkowników Twojej aplikacji.<br />
<br />
Aby wyzerować etykietę RightWrongLabel i AnswerText, umieść poniższe bloki w bloku obsługi zdarzeń When NextButton.click:<br />
{| class="wikitable"<br />
!Typ bloku<br />
!Kategoria<br />
!Działanie<br />
|-<br />
|set RightWrongLabel.Text to<br />
|RightWrongLabel<br />
|Ustawia wartość etykiety na…<br />
|-<br />
|„ „<br />
|Text<br />
|pusty tekst<br />
|-<br />
|set AnswerText.Text to<br />
|AnswerText<br />
|Ustawia wartość etykiety na…<br />
|-<br />
|„ „<br />
|Text<br />
|pusty tekst<br />
|}<br />
Bloki powinny wyglądać następująco:<br />
<br />
[[Plik:t6-16.png]]<br />
<br />
===Jak działają bloki?===<br />
Po kliknięciu przycisku NextButton użytkownik przechodzi do następnego pytania, dlatego początkowe wiersze bloku obsługi zdarzeń zerują etykietę RightWrongLabel i pole AnswerText.<br />
Przetestuj to zachowanie Odpowiedz na pytanie i kliknij przycisk Wyślij, a następnie - NextButton. Czy Twoja poprzednia odpowiedź i jej ocena zniknęły?<br />
<br />
==Ostateczna postać programu==<br />
Oto gotowa aplikacja QuizMe:<br />
<br />
[[Plik:t6-17.png]]<br />
<br />
Utwórz wykonywalną wersję aplikacji, wybierając menu Build/App (provide QR code for .apk). Gdy pojawi się kod kreskowy, użyj czytnika kodów w telefonie, aby pobrać i zainstalować aplikację.<br />
<br />
===Modyfikacje===<br />
Quiz w tej wersji jest już gotowy. Czy masz ochotę przemyśleć pewne zmiany?<br />
<br />
Zamiast wyświetlać zdjęcie dla każdego pytania, spróbuj odtworzyć dźwięk lub krótkie wideo. Za pomocą dźwięku możesz zmienić quiz w aplikację Jaka to melodia?.<br />
<br />
Quiz akceptuje ściśle określone odpowiedzi. Jeśli gracz odpowiedziałby, lekko przekształcając tekst (np. podając inicjał zamiast imienia), program uzna to za błąd. Można to zmienić na kilka różnych sposobów. Jednym z nich jest użycie bloku text.contains, aby sprawdzić, czy odpowiedź użytkownika zawiera prawidłową odpowiedź. Inny sposób to dostarczenie wielu odpowiedzi na każde pytanie i sprawdzenie przez iterację (użycie bloku for each), czy któraś z nich pasuje.<br />
<br />
Przekształć quiz tak, aby przedstawiał odpowiedzi do wyboru. Lista odpowiedzi będzie musiała być listą list, a każda podrzędna lista będzie musiała zawierać opcje odpowiedzi. Użyj komponentu ListPicker, aby umożliwić użytkownikowi wybranie odpowiedzi.<br />
<br />
<br />
==Podsumowanie==<br />
Oto niektóre koncepcje omówione w tym przewodniku:<br />
<ul><li>Aplikacje można tworzyć w sposób ogólny, aby pracować z dowolną listą danych.</li><br />
<li>Zmienne indeksu są wykorzystywane do śledzenia bieżącej pozycji na liście. Zwiększając wartość zmiennej indeksu, należy uważać na przekroczenie końca listy.</li></ul><br />
<br />
==Zeskanuj próbną aplikację do telefonu==<br />
Aby zainstalować i uruchomić aplikację próbną, zeskanuj poniższy kod kreskowy:<br />
<br />
[[Plik:t6-18.png]]<br />
<br />
==Pobierz kod źródłowy==<br />
Jeżeli chcesz pracować z tą próbką w programie App Inventor:<br />
<ul><li>pobierz na komputer kod źródłowy: [http://appinventor.mit.edu/explore/sites/all/files/ai2tutorials/QuizMe/QuizMe_MIT.aia http://appinventor.mit.edu/explore/sites/all/files/ai2tutorials/QuizMe/QuizMe_MIT.aia]</li><br />
<li>otwórz program App Inventor,</li><br />
<li>kliknij opcję My Projects,</li><br />
<li>wybierz Import project (.aia) from my computer...</li><br />
<li>znajdź i zatwierdź pobrany kod źródłowy.</li></ul></div>M Kelniarzhttp://wiki.mistrzowiekodowania.pl/index.php?title=QuizMeQuizMe2015-03-15T18:41:56Z<p>M Kelniarz: /* Ostateczna postać programu */</p>
<hr />
<div>=Aplikacja QuizMe dla App Inventor 2=<br />
<br />
==Co tworzysz?==<br />
[[Plik:t6-1.png|right]]QuizMe to gra dotycząca ciekawostek baseballowych, ale można jej użyć jako szablonu do tworzenia quizów z dowolnej dziedziny. W aplikacji użytkownik odpowiada na szereg pytań, otrzymując następnie informację zwrotną, czy udzielił poprawnej, czy błędnej odpowiedzi. Gracz przechodzi do kolejnego pytania, klikając przycisk.<br />
<br />
W grze QuizMe dysponujemy zamkniętym zbiorem pytań, chyba że programista je zmieni. W następnym etapie można utworzyć MakeQuiz & TakeQuiz – aplikację, która pozwala użytkownikom na tworzenie i modyfikowanie pytań.<br />
<br />
Poradnik ten zakłada, że znasz już podstawy tworzenia aplikacji w App Inventorze – korzystanie z Projektanta komponentów w celu utworzenia interfejsu użytkownika i z Edytora bloków, aby określić obsługę zdarzeń. Jeżeli potrzebujesz przypomnienia, spróbuj popracować z poradnikami podstawowymi zanim przejdziesz dalej.<br />
<br />
==Zaczynamy!==<br />
Połącz się z witryną internetową App Inventor i załóż nowy projekt. Nazwij go QuizMe, ustaw taki sam tytuł ekranu (Title). Za pomocą MIT AI2 Companion połącz program z urządzeniem mobilnym. Pobierz poniższe zdjęcia baseballistów i zapisz je w komputerze. Później załadujesz je do projektu.<br />
<ul><li> [http://beta.appinventor.mit.edu/learn/tutorials/quizme/QuizMeAssets/Larsenberra.jpg Larsenberra.jpg]</li><br />
<li> [http://beta.appinventor.mit.edu/learn/tutorials/quizme/QuizMeAssets/dallasbraden.jpg Dallasbraden.jpg]</li><br />
<li> [http://beta.appinventor.mit.edu/learn/tutorials/quizme/QuizMeAssets/cyyoung.jpg Cyyoung.jpg]</li><br />
<li> [http://beta.appinventor.mit.edu/learn/tutorials/quizme/QuizMeAssets/nolanryan.jpg Nolanryan.jpg]</li></ul><br />
<br />
==Wstęp==<br />
Zaprojektujesz grę typu quiz, w której użytkownik będzie przechodził do kolejnych pytań, klikając przycisk Dalej, a następnie otrzymywał prostą ocenę Dobrze/Źle dla każdej odpowiedzi.<br />
<br />
W tym przewodniku omówimy:<br />
<ul><li>definiowanie i wyświetlanie listy informacji;</li><br />
<li>przechodzenie przez listę za pomocą zmiennej indeksującej – zmiennej, która śledzi pozycję na liście;</li><br />
<li>zachowania warunkowe – wykonywanie określonych operacji tylko wtedy, gdy spełniony jest określony warunek;</li><br />
<li>Zmianę zdjęcia w zależności od sytuacji.</li></ul><br />
<br />
==Projektowanie aplikacji==<br />
Użyj Projektanta komponentów do utworzenia interfejsu dla aplikacji QuizMe. <br />
Aby utworzyć interfejs, najpierw załaduj do projektu pobrane zdjęcia. Kliknij przycisk Prześlij plik (Upload File...) w obszarze Media i wybierz jeden z pobranych wcześniej plików (np. Larsenberra.jpg). Następnie zrób to samo z pozostałymi trzema zdjęciami.<br />
Utwórz następujące komponenty, przeciągając je z Palety (Palette) do Przeglądarki (Viewer) i ustaw właściwości komponentów zgodnie z poniższym opisem:<br />
{|class="wikitable"<br />
! Typ komponentu<br />
! Kategoria<br />
! Jaką nadać jej nazwę<br />
! Działanie<br />
! Działanie komponentu<br />
|-<br />
|Image<br />
|User interface<br />
|Image1<br />
|Ustaw właściwość zdjęcia (Picture) na Larsenberra.jpg. Jest to pierwsze wyświetlane zdjęcie.<br />
|Obrazkowa część pytania<br />
|-<br />
|Label<br />
|User interface<br />
|QuestionLabel<br />
|Zmień właściwość tekstu (Text) na Pytanie:<br />
|Wyświetla bieżące pytanie<br />
|-<br />
|HorizontalArrangement<br />
|Layout<br />
|HorizontalArrangement1<br />
| <br />
|Organizuje komponenty AnswerPrompt i Text (podaj odpowiedź i tekst)<br />
|-<br />
|Label<br />
|User interface<br />
|AnswerPromptLabel<br />
|Zmień właściwość tekstu (Text) na Podaj odpowiedź:. Na ekranie przeglądarki przesuń tę etykietę do HorizontalArrangement1.<br />
|Wyświetla tekst prośby o odpowiedź.<br />
|-<br />
|TextBox<br />
|User interface<br />
|AnswerText<br />
|Zmień wskazówkę (Hint) na Podaj odpowiedź. Na ekranie przeglądarki przenieś AnswerText do komponentu HorizontalArrangement1.<br />
|Tutaj użytkownik podaje odpowiedź.<br />
|-<br />
|Label<br />
|User interface <br />
|RightWrongLabel<br />
|Zmień właściwość tekstu (Text) na Dobrze/Źle.<br />
|Tutaj wyświetlana jest ocena Dobrze/Źle.<br />
|-<br />
|HorizontalArrangement<br />
|Layout<br />
|HorizontalArrangement2<br />
|<br />
|Organizuje przyciski AnswerButton i NextButton (przycisk odpowiedzi i przycisk dalej).<br />
|-<br />
|Przycisk<br />
|User interface<br />
|AnswerButton<br />
|Zmień właściwość tekstu (Text) na Wyślij. Na ekranie przeglądarki przesuń ten przycisk do HorizontalArrangment2.<br />
|Użytkownik klika, aby przesłać odpowiedź.<br />
|-<br />
|Przycisk<br />
|User interface<br />
|NextButton<br />
|Zmień właściwość tekstu (Text) na Dalej. Przenieś ten przycisk do HorizontalArrangement2.<br />
|Użytkownik klika, aby przejść do następnego pytania.<br />
|} <br />
Po zakończeniu powinien on wyglądać jak poniższa ilustracja (pod nią znajdują się również bardziej szczegółowe informacje).<br />
[[Plik:t6-2.png]]<br />
<br />
==Programowanie aplikacji==<br />
Otwórz Edytor bloków, aby zaprogramować działanie komponentów. Najpierw zdefiniuj dwie zmienne - listy: zmienną QuestionList, zawierającą listę pytań i zmienną AnswerList z listą odpowiedzi na te pytania.<br />
<br />
Aby zdefiniować te dwie zmienne listy, potrzebujesz następujących bloków:<br />
{| class="wikitable"<br />
!Typ bloku<br />
!Kategoria<br />
!Działanie<br />
|-<br />
|initialize global name to<br />
|Variables<br />
|Definiuje zmienną QuestionList (zmień jej nazwę)<br />
|-<br />
|initialize global name to<br />
|Variables<br />
|Definiuje zmienną AnswerList (zmień jej nazwę)<br />
|-<br />
|make a list<br />
|Lists<br />
|Służy do dodawania elementów do zmiennej QuestionList<br />
|-<br />
|„ „ (trzykrotnie)<br />
|Lists<br />
|Służy do wpisania pytań<br />
|-<br />
|make a list<br />
|Lists<br />
|Służy do dodawania elementów do zmiennej AnswerList<br />
|-<br />
|„ „ (trzykrotnie)<br />
|Text<br />
|Służy do wpisania odpowiedzi<br />
|}<br />
Utwórz zmienne całościowe, przeciągając z kategorii zmiennych (Variables) na obszar roboczy blok Initialize global name to. Kliknij dwukrotnie domyślną nazwę name, aby ją zmienić. Blok Initialize global name to zawiera pole na początkową wartość zmiennej. Zmienna może zawierać liczbę, tekst, a nawet listę – aby ją utworzyć, podłącz blok Make a list do definicji zmiennej.<br />
<br />
Bloki powinny wyglądać następująco:<br />
<br />
[[Plik:t6-3.png]]<br />
===Zdefiniuj ukrytą zmienną Index===<br />
Za każdym razem, gdy użytkownik kliknie przycisk NextButton, aby przejść dalej, aplikacja musi pamiętać, przy którym pytaniu jest obecnie gracz. W języku programowania, aby coś zapamiętać, trzeba zdefiniować nową zmienną. W tym przypadku aplikacja musi zapamiętać bieżący numer pytania – indeks listy QuestionList.<br />
Aby zdefiniować zmienną currentQuestionIndex, potrzebujesz następujących bloków:<br />
{| class="wikitable"<br />
!Typ bloku<br />
!Kategoria<br />
!Działanie<br />
|-<br />
|initialize global name to<br />
|Variables<br />
|Definiuje zmienną currentQuestionIndex (zmień nazwę)<br />
|-<br />
|0 (1)<br />
|Math<br />
|Ustaw wartość początkową currentQuestionIndex na 1 (zmień liczbę)<br />
|}<br />
Bloki powinny wyglądać następująco:<br />
<br />
[[Plik:t6-4.png]]<br />
<br />
===Wyświetl pierwsze pytanie===<br />
Odłóż na razie kwestię odpowiedzi i skup się na zaprogramowaniu sekwencyjnego przejścia przez pytania. Pożądane zachowanie jest następujące: po uruchomieniu aplikacji na etykiecie o nazwie QuestionLabel pojawia się pierwsze pytanie. Gdy użytkownik kliknie NextButton, wyświetlone zostaje drugie pytanie. Po ponownym kliknięciu pojawia się trzecie pytanie. Po dotarciu do ostatniego pytania kliknięcie przycisku NextButton powoduje ponowne pojawienie się pierwszego pytania w etykiecie QuestionLabel.<br />
<br />
W programie App Inventor określone pozycje na liście są wybierane za pomocą bloku select list item. W tym bloku trzeba podać listę i indeks – pozycję na liście. Jeżeli na liście są trzy pozycje, prawidłowe indeksy to 1, 2 i 3.<br />
<br />
Po uruchomieniu aplikacja QuizMe powinna wybrać pierwsze pytanie z listy i wyświetlić je w komponencie QuestionLabel. Do tego zachowania inicjalizującego działanie aplikacji potrzebne są następujące bloki:<br />
<br />
{| class="wikitable"<br />
!Typ bloku<br />
!Kategoria<br />
!Działanie<br />
|-<br />
|when Screen1.Initialize<br />
|Screen1<br />
|Podczas uruchamiania aplikacji zainicjowana jest ta obsługa zdarzenia<br />
|-<br />
|set QuestionLabel.Text to<br />
|QuestionLabel<br />
|Umieszcza pierwsze pytanie w etykiecie QuestionLabel<br />
|-<br />
|select list item<br />
|Lists<br />
|Wybiera pierwsze pytanie z etykiety QuestionLabel<br />
|-<br />
|get <br />
|Variables<br />
|Ustala listę, z której jest wybierany element. Tutaj: Global QuestionList<br />
|-<br />
|0 (1)<br />
|Math<br />
|Wybiera pierwsze pytanie za pomocą indeksu 1. Ustaw wartość na 1.<br />
|}<br />
Bloki powinny wyglądać następująco:<br />
<br />
[[Plik:t6-5.png]]<br />
<br />
===Jak działają bloki?===<br />
Zdarzenie when Screen1.Initialize jest wyzwalane podczas uruchomienia aplikacji. Pierwsza pozycja zmiennej QuestionList zostaje wybrana i umieszczona w bloku set QuestionLabel.Text. Gdy aplikacja zostanie uruchomiona, użytkownik zobaczy pierwsze pytanie.<br />
===Przetestuj to zachowanie===<br />
Jeśli dotychczas nie skomunikowałeś urządzenia mobilnego z programem, zrób to teraz. Co pojawia się na urządzeniu? Jeżeli utworzono listę QuestionList tak, jak wskazano powyżej, w etykiecie QuestionLabel powinna pojawić się pierwsza pozycja tej listy (Kto był doskonałym miotaczem w World Series?).<br />
<br />
==Iteracja pytań==<br />
Zdefiniowałeś już zmienną CurrentQuestionIndex, zapamiętującą pytanie, przy którym znajduje się użytkownik. Zaprogramuj teraz zachowanie przycisku NextButton. Gdy zostanie on kliknięty, aplikacja zwiększy wartość zmiennej, np. zmieni ją z 1 na 2 lub z 2 na 3 itd., a następnie użyje tej wartości do zaznaczenia nowego bieżącego pytania. Do tego zachowania potrzebne są następujące bloki:<br />
{| class="wikitable"<br />
!Typ bloku<br />
!Kategoria<br />
!Działanie<br />
|-<br />
|when NextButton.Click<br />
|NextButton<br />
|Uruchamia obsługę zdarzeń po kliknięciu przycisku<br />
|-<br />
|set currentQuestionIndex to<br />
|Zmienne<br />
|Decyduje o ustawieniu indeksu wybranej listy<br />
|-<br />
|+ <br />
|Math<br />
|Służy do zwiększania wartości zmiennej currentQuestionIndex<br />
|-<br />
|get global currentQuestionIndex<br />
|Zmienne<br />
|Tworzy nową wartość poprzez zwiększenie poprzedniej wartości o 1<br />
|-<br />
|0 (1)<br />
|Math<br />
|Dla + 1<br />
|-<br />
|set QuestionLabel.Text to<br />
|QuestionLabel<br />
|Wyświetla kolejne pytanie<br />
|-<br />
|select list item<br />
|Listy<br />
|Ustawia element listy jako wartość QuestionLabel<br />
|-<br />
|get global QuestionList<br />
|Zmienne<br />
|Wskazuje, która lista będzie wybrana<br />
|-<br />
|get global currentQuestionIndex<br />
|Zmienne<br />
|Wskazuje, który element wybranej listy będzie wybrany<br />
|}<br />
Bloki powinny wyglądać następująco:<br />
<br />
[[Plik:t6-6.png]]<br />
<br />
===Jak działają bloki?===<br />
Pierwszy wiersz polecenia zwiększa wartość zmiennej currentQuestionIndex o 1 (jeżeli zmienna zawiera wartość 1, zostaje ona zmieniona na 2, z 2 na 3 itd.). Następnie wykorzystuje nową wartość do wyboru pytania o tym indeksie.<br />
<br />
Przypomnijmy, że w bloku obsługi zdarzeń Screen.Initialize aplikacja wybrała pierwsze do wyświetlenia pytanie:<br />
<br />
[[Plik:t6-7.png]]<br />
<br />
Po kliknięciu przycisku NextButton aplikacja nie wybiera konkretnie pierwszej, drugiej czy trzeciej pozycji na liście, tylko pozycję o n-tej wartości zmiennej currentQuestionIndex.<br />
<br />
[[Plik:t6-8.png]]<br />
<br />
Polecenia w blokach są wykonywane od prawej do lewej, tzn. aplikacja najpierw określa wartość parametru z bloku Select list item, którym jest zmienna CurrentQuestionIndex. Liczba zawarta w tej zmiennej zostaje użyta jako indeks podczas wykonania poleceń zawartych w bloku Select list item.<br />
<br />
[[Plik:info.png|left]]''Po pierwszym kliknięciu przycisku NextButton, wartość zmiennej currentQuestionIndex przeskoczy z 1 na 2, aby aplikacja wybrała drugą pozycję z listy QuestionList (Kto był pierwszym doskonałym miotaczem w 2010?). Po drugim kliknięciu przycisku NextButton, wartość zmiennej currentQuestionIndex zostanie zmieniona z 2 na 3, a aplikacja wybierze trzecie pytanie z listy (Kto był pierwszym doskonałym miotaczem nowej ery?).''<br />
<br />
<br />
===Przetestuj to zachowanie===<br />
Przetestuj zachowanie przycisku NextButton, aby sprawdzić, czy aplikacja działa poprawnie. Wciel się w rolę użytkownika i kliknij przycisk NextButton w telefonie. Czy urządzenie wyświetliło drugie pytanie: Kto był pierwszym doskonałym miotaczem w 2010?? Trzecie pytanie powinno pojawić się po kolejnym kliknięciu przycisku. Jeżeli aplikacja działa, pogratuluj sobie i przejdź dalej. Kliknij przycisk NextButton ponownie (po raz trzeci). Powinien zostać wyświetlony błąd: Próba uzyskania elementu 4 z listy o długości 3. Czy wiesz, na czym polega problem?<br />
<br />
Problem z aplikacją polega na tym, że zawsze po kliknięciu przycisku NextButton zwiększa ona zmienną CurrentQuestionIndex o 1. Gdy wartość zmiennej wynosi już 3, a użytkownik kolejny raz kliknie przycisk NextButton, aplikacja zmieni wartość zmiennej z 3 na 4, następnie wywoła blok Select list item, aby odczytać pozycję o aktualnym indeksie CurrentQuestionIndex, czyli w tym przypadku czwartą pozycję. Ponieważ zmienna QuestionList zawiera tylko trzy elementy, Android wykaże błąd.<br />
<br />
Aplikacja musi zadawać pytanie - sprawdzać warunek - gdy nastąpi kliknięcie przycisku NextButton i realizować polecenia zawarte w różnych blokach w zależności od odpowiedzi. Elementem do sprawdzenia jest to, czy zmienna CurrentQuestionIndex już ma wartość 3. Jeżeli tak - należy ustawić CurrentQuestionIndex z powrotem na 0, aby użytkownik wrócił do pierwszego pytania.<br />
<br />
Będziesz potrzebował następujących bloków:<br />
{| class="wikitable"<br />
!Typ bloku<br />
!Kategoria<br />
!Działanie<br />
|-<br />
|if then<br />
|Control<br />
|sprawdzenie, czy użytkownik jest na etapie ostatniego pytania<br />
|-<br />
|= <br />
|Math<br />
|sprawdzenie, czy currentQuestionIndex ma wartość 3<br />
|-<br />
|get global currentQuestionIndex<br />
|Variables<br />
|<br />
|-<br />
|0 (3)<br />
|Math<br />
|3 to numer na liście<br />
|-<br />
|set currentQuestionIndex to<br />
|Variables<br />
|ustawienie na 0, aby wrócić do pierwszego pytania<br />
|-<br />
|0<br />
|Math<br />
|ustawienie na 0, ponieważ kolejne bloki zwiększą wartość do 1<br />
|}<br />
Zmodyfikowany blok obsługi zdarzenia When NextButton.Click powinien wyglądać następująco:<br />
<br />
[[Plik:t6-9.png]]<br />
<br />
===Jak działają bloki===<br />
Po kliknięciu przycisku NextButton aplikacja najpierw sprawdza, czy currentQuestionIndex ma wartość 3. Jeżeli tak, wartość tej zmiennej jest ustawiana na 0, aby po zwiększeniu jej w dalszych krokach jej wartość wyniosła 1. Wtedy quiz wróci do pierwszego pytania. Zauważ, że tylko bloki osadzone w bloku if-then są zależne od warunku. Blok zwiększenia wartości i blok Set QuestionLabel.Text to są wykonywane bez względu na jakikolwiek warunek.<br />
<br />
==Aplikacja modyfikowalna: Ułatwianie modyfikowania pytań==<br />
Teraz zmodyfikujemy aplikację, aby można było łatwo dodawać i usuwać elementy z listy. Zmień bloki tak, aby działały na liście o dowolnej długości, a nie tylko liście z dokładnie trzema pozycjami. <br />
Na początek dodaj czwarte pytanie do zmiennej QuestionList i kolejną odpowiedź do AnswerList. W tym celu musisz najpierw zwiększyć liczbę dostępnych pól za pomocą przycisku modyfikującego (mutatora). Aby dowiedzieć się więcej o tym elemencie, zobacz: http://appinventor.mit.edu/explore/ai2/support/concepts/mutators. Bloki powinny wyglądać następująco:<br />
<br />
[[Plik:t6-10.png]]<br />
<br />
===Przetestuj zmodyfikowaną aplikację.===<br />
Kliknij przycisk NextButton kilka razy. Zauważysz, że czwarte pytanie nigdy się nie pojawia, bez względu na to, ile razy klikniesz przycisk.<br />
<br />
Problemem jest to, że test sprawdzający, czy użytkownik znajduje się przy ostatnim pytaniu, jest zbyt szczegółowy: pyta, czy zmienna CurrentQuestionIndex ma wartość 3:<br />
<br />
[[Plik:t6-11.png]]<br />
<br />
Możesz po prostu zmienić liczbę z 3 na 4, a aplikacja będzie znów działać poprawnie. Problem polega jednak na tym, że za każdym razem, gdy zmodyfikujesz liczbę pytań i odpowiedzi, będziesz musiał pamiętać, aby dokonać także tej zmiany. Takie zależności w programie komputerowym często prowadzą do błędów, w szczególności gdy aplikacja staje się bardziej złożona. Znacznie lepiej jest przygotować program w taki sposób, aby działał niezależnie od liczby pytań. Takie uogólnienie jest jeszcze ważniejsze, gdy lista, z którą pracujesz, zmienia się dynamicznie, na przykład w aplikacji z quizem, gdzie użytkownik może dodawać nowe pytania.<br />
<br />
Lepszym rozwiązaniem jest sprawdzenie warunku w sposób bardziej ogólny. Tak naprawdę chcesz wiedzieć, czy bieżące pytanie – czyli wartość zmiennej currentQuestionIndex jest tak duża, jak ilość elementów w zmiennej QuestionList. Jeżeli aplikacja sprawdzi warunek w bardziej ogólny sposób, to będzie działać, nawet jeżeli dodasz lub usuniesz elementy ze zmiennej QuestionList. Aby zmienić blok obsługi zdarzenia When NextButton.Click, zmień poprzedni test sprawdzający, który odnosił się bezpośrednio do 3. Będziesz potrzebował następujących bloków:<br />
{| class="wikitable"<br />
!Typ bloku<br />
!Szuflada<br />
!Działanie<br />
|-<br />
|length of list<br />
|Lists<br />
|Pyta, ile elementów jest w zmiennej QuestionList<br />
|-<br />
|get global QuestionList<br />
|Variables<br />
|Określa, o którą listę chodzi<br />
|}<br />
Blok obsługi zdarzenia When NextButton.Click powinien teraz wyglądać następująco:<br />
<br />
[[Plik:t6-12.png]]<br />
<br />
<br />
<br />
===Jak działają bloki?===<br />
Warunek if porównuje teraz wartość zmiennej CurrentQuestionIndex z długością zmiennej QuestionList. Zatem jeżeli zmienna CurrentQuestionIndex ma wartość 4, a długość zmiennej QuestionList wynosi 4, to wartość zmiennej currentQuestionIndex zostanie ustawiona na 0 (a następnie na 1, 2 itd.). Zauważ - bloki nie odwołują się już do 3 ani żadnej innej określonej wartości, dlatego instrukcja będzie działać bez względu na liczbę elementów listy.<br />
<br />
Przetestuj zmodyfikowane zachowanie. Czy po kliknięciu przycisku NextButton aplikacja przechodzi teraz przez cztery pytania, wracając po ostatnim do pierwszego?<br />
<br />
==Przełączanie zdjęcia dla każdego pytania==<br />
Na razie aplikacja wyświetla to samo zdjęcie, bez względu na to, jakie pytanie zostaje zadane. Możesz to zmienić tak, aby po kliknięciu przycisku NextButton pojawiała się fotografia dotycząca danego pytania. W obszarze Media dostępne są cztery dodane wcześniej zdjęcia. Teraz utworzymy trzecią listę - PictureList, której elementami będą nazwy plików zdjęć, a następnie zmodyfikujemy blok obsługi zdarzenia When NextButton.Click, aby program po każdym pytaniu przełączał zdjęcie.<br />
Najpierw utwórz listę PictureList i zainicjuj ją nazwami plików graficznych. Upewnij się, czy nazwy są dokładnie takie same jak nazwy plików, które zostały załadowane do obszaru Media. Oto jak powinien wyglądać blok dla listy PictureList:<br />
<br />
[[Plik:t6-13.png]]<br />
<br />
Następnie zmodyfikuj blok obsługi zdarzeń When NextButton.Click, aby zmieniał wyświetlane zdjęcie w zależności od zadanego pytania. Jeżeli ustawisz właściwość Image.Picture na nazwę pliku zdjęcia, które zostało załadowane, właśnie ta fotografia zostanie wyświetlona. Aby zmodyfikować blok When NextButton.Click, potrzebujesz następujących bloków:<br />
{| class="wikitable"<br />
!Typ bloku<br />
!Kategoria<br />
!Działanie<br />
|-<br />
|set Image1.Picture to<br />
|Image1<br />
|ustaw, aby zmieniać zdjęcie<br />
|-<br />
|select list item<br />
|Lists<br />
|należy wybrać zdjęcie odpowiadające na aktualne pytanie<br />
|-<br />
|get global PictureList<br />
|Variables<br />
|wybierz nazwę pliku z tej listy<br />
|-<br />
|get global currentQuestionIndex<br />
|Variables<br />
|wybierz element o n-tym indeksie currentQuestionIndex<br />
|}<br />
Oto jak powinny wyglądać bloki:<br />
<br />
[[Plik:t6-14.png]]<br />
<br />
===Jak działają bloki?===<br />
Zmienna CurrentQuestionIndex służy jako indeks dla zmiennej QuestionList. Wartość CurrentQuestionIndex wynosi 1, aplikacja wybiera pierwsze pytanie i pierwsze zdjęcie. Gdy CurrentQuestionIndex wynosi 2, aplikacja wybiera drugie pytanie i drugie zdjęcie. Oczywiście takie działanie zależy od tego, czy listy są ze sobą zsynchronizowane. Tak jest w tym przypadku - pierwszy obraz - LarsenBerra.jpg to zdjęcie Dona Larsena, jednocześnie Don Larsen to odpowiedź na pierwsze pytanie (Kto był doskonałym miotaczem w World Series?). <br />
Przetestuj zmodyfikowane zachowanie. Czy nowe zdjęcie pojawia się po każdym kliknięciu przycisku NextButton?<br />
<br />
==Ocena udzielanych odpowiedzi==<br />
Teraz dodamy bloki, które określają, czy użytkownik odpowiedział na pytanie prawidłowo, czy też nie. Gracz wprowadza odpowiedź do AnswerText, a następnie klika przycisk AnswerButton. Aplikacja musi porównać wpis użytkownika z odpowiedzią na bieżące pytanie, używając bloku if... then... w celu jej sprawdzenia. Etykieta RightWrongLabel powinna być modyfikowana, aby podawać, czy odpowiedź jest prawidłowa, czy nie.<br />
<br />
Do tego zachowania będą potrzebne następujące bloki:<br />
{| class="wikitable"<br />
!Typ bloku<br />
!Kategoria<br />
!Działanie<br />
|-<br />
|when AnswerButton.Click<br />
|AnswerButton<br />
|zachowanie jest wyzwalane, gdy użytkownik kliknie przycisk AnswerButton<br />
|-<br />
|if... then...<br />
|Control<br />
|Użyj mutatora, aby dodać alternatywę (else). Jeżeli odpowiedź jest prawidłowa - zrób jedno, w przeciwnym razie (else) - zrób coś innego<br />
|-<br />
|= <br />
|Math<br />
|sprawdzenie, czy odpowiedź jest prawidłowa<br />
|-<br />
|AnswerText.Text<br />
|AnswerText<br />
|Odpowiedź użytkownika pojawia się w tym polu tekstowym<br />
|-<br />
|select list item<br />
|Lists<br />
|wybrać bieżącą odpowiedź z listy AnswerList<br />
|-<br />
|get global AnswerList<br />
|Variables<br />
|lista, z której jest wybierany element<br />
|-<br />
|get global currentQuestionIndex<br />
|Variables<br />
|numer pytania (i numer odpowiedzi), przy którym jest użytkownik<br />
|-<br />
|set RightWrongLabel.Text to<br />
|RightWrongLabel<br />
|tutaj podaj odpowiedź<br />
|-<br />
|Dobrze!<br />
|Text<br />
|jeżeli odpowiedź jest prawidłowa<br />
|-<br />
|set RightWrongLabel.Text to<br />
|RightWrongLabel<br />
|tutaj podaj odpowiedź<br />
|-<br />
|Źle<br />
|Text<br />
|jeżeli odpowiedź jest nieprawidłowa<br />
|}<br />
Bloki powinny wyglądać następująco:<br />
<br />
[[Plik:t6-15.png]]<br />
<br />
===Jak działają bloki?===<br />
Test if sprawdza, czy odpowiedź użytkownika (AnswerText.Text) jest taka sama, jak element na liście AnswerList o indeksie równym wartości zmiennej CurrentQuestionIndex. Jeżeli zmienna CurrentQuestionIndex ma wartość 1, aplikacja porównuje odpowiedź użytkownika z pierwszą pozycją na liście AnswerList, (Don Larsen). Jeżeli zmienna CurrentQuestionIndex zmieni wartość na 2, program zestawia odpowiedź z drugą pozycją na liście, czyli Dallas Branden. Jeśli wynik porównania jest pozytywny, przeprowadzane są bloki then, a treść etykiety RightWrongLabel zostaje ustawiona na Dobrze!. Jeżeli wynik testu jest negatywny (fałszywy), przeprowadzane są bloki alternatywy (else), a treść etykiety RightWrongLabel zostaje ustawiona na Źle.<br />
<br />
Przetestuj zmodyfikowaną aplikację. Spróbuj odpowiedzieć na jedno z pytań. Powinna pojawić się ocena, czy odpowiedź była dokładnie taka sama, jak na liście AnswerList. Sprawdź zarówno prawidłowe, jak i nieprawidłowe odpowiedzi (Uwaga - uwzględniana jest wielkość liter!). Kliknij przycisk NextButton i odpowiedz na drugie pytanie. Czy aplikacja nadal działa? Powinna, ale zauważ, że gdy klikniesz przycisk NextButton, tekst Dobrze! lub Źle oraz poprzednia odpowiedź nadal będą wyświetlane. Choć nie wpływa to zasadniczo na naszą grę, to takie szczegóły interfejsu z pewnością zostaną zauważone przez użytkowników Twojej aplikacji.<br />
<br />
Aby wyzerować etykietę RightWrongLabel i AnswerText, umieść poniższe bloki w bloku obsługi zdarzeń When NextButton.click:<br />
{| class="wikitable"<br />
!Typ bloku<br />
!Kategoria<br />
!Działanie<br />
|-<br />
|set RightWrongLabel.Text to<br />
|RightWrongLabel<br />
|Ustawia wartość etykiety na…<br />
|-<br />
|„ „<br />
|Text<br />
|pusty tekst<br />
|-<br />
|set AnswerText.Text to<br />
|AnswerText<br />
|Ustawia wartość etykiety na…<br />
|-<br />
|„ „<br />
|Text<br />
|pusty tekst<br />
|}<br />
Bloki powinny wyglądać następująco:<br />
<br />
[[Plik:t6-16.png]]<br />
<br />
===Jak działają bloki?===<br />
Po kliknięciu przycisku NextButton użytkownik przechodzi do następnego pytania, dlatego początkowe wiersze bloku obsługi zdarzeń zerują etykietę RightWrongLabel i pole AnswerText.<br />
Przetestuj to zachowanie Odpowiedz na pytanie i kliknij przycisk Wyślij, a następnie - NextButton. Czy Twoja poprzednia odpowiedź i jej ocena zniknęły?<br />
<br />
==Ostateczna postać programu==<br />
Oto gotowa aplikacja QuizMe:<br />
<br />
[[Plik:t6-17.png]]<br />
<br />
Utwórz wykonywalną wersję aplikacji, wybierając menu Build/App (provide QR code for .apk). Gdy pojawi się kod kreskowy, użyj czytnika kodów w telefonie, aby pobrać i zainstalować aplikację.<br />
<br />
===Modyfikacje===<br />
Quiz w tej wersji jest już gotowy. Czy masz ochotę przemyśleć pewne zmiany?<br />
<br />
Zamiast wyświetlać zdjęcie dla każdego pytania, spróbuj odtworzyć dźwięk lub krótkie wideo. Za pomocą dźwięku możesz zmienić quiz w aplikację Jaka to melodia?.<br />
<br />
Quiz akceptuje ściśle określone odpowiedzi. Jeśli gracz odpowiedziałby, lekko przekształcając tekst (np. podając inicjał zamiast imienia), program uzna to za błąd. Można to zmienić na kilka różnych sposobów. Jednym z nich jest użycie bloku text.contains, aby sprawdzić, czy odpowiedź użytkownika zawiera prawidłową odpowiedź. Inny sposób to dostarczenie wielu odpowiedzi na każde pytanie i sprawdzenie przez iterację (użycie bloku for each), czy któraś z nich pasuje.<br />
<br />
Przekształć quiz tak, aby przedstawiał odpowiedzi do wyboru. Lista odpowiedzi będzie musiała być listą list, a każda podrzędna lista będzie musiała zawierać opcje odpowiedzi. Użyj komponentu ListPicker, aby umożliwić użytkownikowi wybranie odpowiedzi.<br />
<br />
<br />
==Podsumowanie==<br />
Oto niektóre koncepcje omówione w tym przewodniku:<br />
<ul><li>Aplikacje można tworzyć w sposób ogólny, aby pracować z dowolną listą danych.</li><br />
<li>Zmienne indeksu są wykorzystywane do śledzenia bieżącej pozycji na liście. Zwiększając wartość zmiennej indeksu, należy uważać na przekroczenie końca listy.</li></ul><br />
<br />
==Zeskanuj próbną aplikację do telefonu==<br />
Aby zainstalować i uruchomić aplikację próbną, zeskanuj poniższy kod kreskowy:<br />
<br />
==Pobierz kod źródłowy==<br />
Jeżeli chcesz pracować z tą próbką w programie App Inventor:<br />
<ul><li>pobierz na komputer kod źródłowy: [http://appinventor.mit.edu/explore/sites/all/files/ai2tutorials/QuizMe/QuizMe_MIT.aia http://appinventor.mit.edu/explore/sites/all/files/ai2tutorials/QuizMe/QuizMe_MIT.aia]</li><br />
<li>otwórz program App Inventor,</li><br />
<li>kliknij opcję My Projects,</li><br />
<li>wybierz Import project (.aia) from my computer...</li><br />
<li>znajdź i zatwierdź pobrany kod źródłowy.</li></ul></div>M Kelniarzhttp://wiki.mistrzowiekodowania.pl/index.php?title=QuizMeQuizMe2015-03-15T18:39:53Z<p>M Kelniarz: /* Ocena udzielanych odpowiedzi */</p>
<hr />
<div>=Aplikacja QuizMe dla App Inventor 2=<br />
<br />
==Co tworzysz?==<br />
[[Plik:t6-1.png|right]]QuizMe to gra dotycząca ciekawostek baseballowych, ale można jej użyć jako szablonu do tworzenia quizów z dowolnej dziedziny. W aplikacji użytkownik odpowiada na szereg pytań, otrzymując następnie informację zwrotną, czy udzielił poprawnej, czy błędnej odpowiedzi. Gracz przechodzi do kolejnego pytania, klikając przycisk.<br />
<br />
W grze QuizMe dysponujemy zamkniętym zbiorem pytań, chyba że programista je zmieni. W następnym etapie można utworzyć MakeQuiz & TakeQuiz – aplikację, która pozwala użytkownikom na tworzenie i modyfikowanie pytań.<br />
<br />
Poradnik ten zakłada, że znasz już podstawy tworzenia aplikacji w App Inventorze – korzystanie z Projektanta komponentów w celu utworzenia interfejsu użytkownika i z Edytora bloków, aby określić obsługę zdarzeń. Jeżeli potrzebujesz przypomnienia, spróbuj popracować z poradnikami podstawowymi zanim przejdziesz dalej.<br />
<br />
==Zaczynamy!==<br />
Połącz się z witryną internetową App Inventor i załóż nowy projekt. Nazwij go QuizMe, ustaw taki sam tytuł ekranu (Title). Za pomocą MIT AI2 Companion połącz program z urządzeniem mobilnym. Pobierz poniższe zdjęcia baseballistów i zapisz je w komputerze. Później załadujesz je do projektu.<br />
<ul><li> [http://beta.appinventor.mit.edu/learn/tutorials/quizme/QuizMeAssets/Larsenberra.jpg Larsenberra.jpg]</li><br />
<li> [http://beta.appinventor.mit.edu/learn/tutorials/quizme/QuizMeAssets/dallasbraden.jpg Dallasbraden.jpg]</li><br />
<li> [http://beta.appinventor.mit.edu/learn/tutorials/quizme/QuizMeAssets/cyyoung.jpg Cyyoung.jpg]</li><br />
<li> [http://beta.appinventor.mit.edu/learn/tutorials/quizme/QuizMeAssets/nolanryan.jpg Nolanryan.jpg]</li></ul><br />
<br />
==Wstęp==<br />
Zaprojektujesz grę typu quiz, w której użytkownik będzie przechodził do kolejnych pytań, klikając przycisk Dalej, a następnie otrzymywał prostą ocenę Dobrze/Źle dla każdej odpowiedzi.<br />
<br />
W tym przewodniku omówimy:<br />
<ul><li>definiowanie i wyświetlanie listy informacji;</li><br />
<li>przechodzenie przez listę za pomocą zmiennej indeksującej – zmiennej, która śledzi pozycję na liście;</li><br />
<li>zachowania warunkowe – wykonywanie określonych operacji tylko wtedy, gdy spełniony jest określony warunek;</li><br />
<li>Zmianę zdjęcia w zależności od sytuacji.</li></ul><br />
<br />
==Projektowanie aplikacji==<br />
Użyj Projektanta komponentów do utworzenia interfejsu dla aplikacji QuizMe. <br />
Aby utworzyć interfejs, najpierw załaduj do projektu pobrane zdjęcia. Kliknij przycisk Prześlij plik (Upload File...) w obszarze Media i wybierz jeden z pobranych wcześniej plików (np. Larsenberra.jpg). Następnie zrób to samo z pozostałymi trzema zdjęciami.<br />
Utwórz następujące komponenty, przeciągając je z Palety (Palette) do Przeglądarki (Viewer) i ustaw właściwości komponentów zgodnie z poniższym opisem:<br />
{|class="wikitable"<br />
! Typ komponentu<br />
! Kategoria<br />
! Jaką nadać jej nazwę<br />
! Działanie<br />
! Działanie komponentu<br />
|-<br />
|Image<br />
|User interface<br />
|Image1<br />
|Ustaw właściwość zdjęcia (Picture) na Larsenberra.jpg. Jest to pierwsze wyświetlane zdjęcie.<br />
|Obrazkowa część pytania<br />
|-<br />
|Label<br />
|User interface<br />
|QuestionLabel<br />
|Zmień właściwość tekstu (Text) na Pytanie:<br />
|Wyświetla bieżące pytanie<br />
|-<br />
|HorizontalArrangement<br />
|Layout<br />
|HorizontalArrangement1<br />
| <br />
|Organizuje komponenty AnswerPrompt i Text (podaj odpowiedź i tekst)<br />
|-<br />
|Label<br />
|User interface<br />
|AnswerPromptLabel<br />
|Zmień właściwość tekstu (Text) na Podaj odpowiedź:. Na ekranie przeglądarki przesuń tę etykietę do HorizontalArrangement1.<br />
|Wyświetla tekst prośby o odpowiedź.<br />
|-<br />
|TextBox<br />
|User interface<br />
|AnswerText<br />
|Zmień wskazówkę (Hint) na Podaj odpowiedź. Na ekranie przeglądarki przenieś AnswerText do komponentu HorizontalArrangement1.<br />
|Tutaj użytkownik podaje odpowiedź.<br />
|-<br />
|Label<br />
|User interface <br />
|RightWrongLabel<br />
|Zmień właściwość tekstu (Text) na Dobrze/Źle.<br />
|Tutaj wyświetlana jest ocena Dobrze/Źle.<br />
|-<br />
|HorizontalArrangement<br />
|Layout<br />
|HorizontalArrangement2<br />
|<br />
|Organizuje przyciski AnswerButton i NextButton (przycisk odpowiedzi i przycisk dalej).<br />
|-<br />
|Przycisk<br />
|User interface<br />
|AnswerButton<br />
|Zmień właściwość tekstu (Text) na Wyślij. Na ekranie przeglądarki przesuń ten przycisk do HorizontalArrangment2.<br />
|Użytkownik klika, aby przesłać odpowiedź.<br />
|-<br />
|Przycisk<br />
|User interface<br />
|NextButton<br />
|Zmień właściwość tekstu (Text) na Dalej. Przenieś ten przycisk do HorizontalArrangement2.<br />
|Użytkownik klika, aby przejść do następnego pytania.<br />
|} <br />
Po zakończeniu powinien on wyglądać jak poniższa ilustracja (pod nią znajdują się również bardziej szczegółowe informacje).<br />
[[Plik:t6-2.png]]<br />
<br />
==Programowanie aplikacji==<br />
Otwórz Edytor bloków, aby zaprogramować działanie komponentów. Najpierw zdefiniuj dwie zmienne - listy: zmienną QuestionList, zawierającą listę pytań i zmienną AnswerList z listą odpowiedzi na te pytania.<br />
<br />
Aby zdefiniować te dwie zmienne listy, potrzebujesz następujących bloków:<br />
{| class="wikitable"<br />
!Typ bloku<br />
!Kategoria<br />
!Działanie<br />
|-<br />
|initialize global name to<br />
|Variables<br />
|Definiuje zmienną QuestionList (zmień jej nazwę)<br />
|-<br />
|initialize global name to<br />
|Variables<br />
|Definiuje zmienną AnswerList (zmień jej nazwę)<br />
|-<br />
|make a list<br />
|Lists<br />
|Służy do dodawania elementów do zmiennej QuestionList<br />
|-<br />
|„ „ (trzykrotnie)<br />
|Lists<br />
|Służy do wpisania pytań<br />
|-<br />
|make a list<br />
|Lists<br />
|Służy do dodawania elementów do zmiennej AnswerList<br />
|-<br />
|„ „ (trzykrotnie)<br />
|Text<br />
|Służy do wpisania odpowiedzi<br />
|}<br />
Utwórz zmienne całościowe, przeciągając z kategorii zmiennych (Variables) na obszar roboczy blok Initialize global name to. Kliknij dwukrotnie domyślną nazwę name, aby ją zmienić. Blok Initialize global name to zawiera pole na początkową wartość zmiennej. Zmienna może zawierać liczbę, tekst, a nawet listę – aby ją utworzyć, podłącz blok Make a list do definicji zmiennej.<br />
<br />
Bloki powinny wyglądać następująco:<br />
<br />
[[Plik:t6-3.png]]<br />
===Zdefiniuj ukrytą zmienną Index===<br />
Za każdym razem, gdy użytkownik kliknie przycisk NextButton, aby przejść dalej, aplikacja musi pamiętać, przy którym pytaniu jest obecnie gracz. W języku programowania, aby coś zapamiętać, trzeba zdefiniować nową zmienną. W tym przypadku aplikacja musi zapamiętać bieżący numer pytania – indeks listy QuestionList.<br />
Aby zdefiniować zmienną currentQuestionIndex, potrzebujesz następujących bloków:<br />
{| class="wikitable"<br />
!Typ bloku<br />
!Kategoria<br />
!Działanie<br />
|-<br />
|initialize global name to<br />
|Variables<br />
|Definiuje zmienną currentQuestionIndex (zmień nazwę)<br />
|-<br />
|0 (1)<br />
|Math<br />
|Ustaw wartość początkową currentQuestionIndex na 1 (zmień liczbę)<br />
|}<br />
Bloki powinny wyglądać następująco:<br />
<br />
[[Plik:t6-4.png]]<br />
<br />
===Wyświetl pierwsze pytanie===<br />
Odłóż na razie kwestię odpowiedzi i skup się na zaprogramowaniu sekwencyjnego przejścia przez pytania. Pożądane zachowanie jest następujące: po uruchomieniu aplikacji na etykiecie o nazwie QuestionLabel pojawia się pierwsze pytanie. Gdy użytkownik kliknie NextButton, wyświetlone zostaje drugie pytanie. Po ponownym kliknięciu pojawia się trzecie pytanie. Po dotarciu do ostatniego pytania kliknięcie przycisku NextButton powoduje ponowne pojawienie się pierwszego pytania w etykiecie QuestionLabel.<br />
<br />
W programie App Inventor określone pozycje na liście są wybierane za pomocą bloku select list item. W tym bloku trzeba podać listę i indeks – pozycję na liście. Jeżeli na liście są trzy pozycje, prawidłowe indeksy to 1, 2 i 3.<br />
<br />
Po uruchomieniu aplikacja QuizMe powinna wybrać pierwsze pytanie z listy i wyświetlić je w komponencie QuestionLabel. Do tego zachowania inicjalizującego działanie aplikacji potrzebne są następujące bloki:<br />
<br />
{| class="wikitable"<br />
!Typ bloku<br />
!Kategoria<br />
!Działanie<br />
|-<br />
|when Screen1.Initialize<br />
|Screen1<br />
|Podczas uruchamiania aplikacji zainicjowana jest ta obsługa zdarzenia<br />
|-<br />
|set QuestionLabel.Text to<br />
|QuestionLabel<br />
|Umieszcza pierwsze pytanie w etykiecie QuestionLabel<br />
|-<br />
|select list item<br />
|Lists<br />
|Wybiera pierwsze pytanie z etykiety QuestionLabel<br />
|-<br />
|get <br />
|Variables<br />
|Ustala listę, z której jest wybierany element. Tutaj: Global QuestionList<br />
|-<br />
|0 (1)<br />
|Math<br />
|Wybiera pierwsze pytanie za pomocą indeksu 1. Ustaw wartość na 1.<br />
|}<br />
Bloki powinny wyglądać następująco:<br />
<br />
[[Plik:t6-5.png]]<br />
<br />
===Jak działają bloki?===<br />
Zdarzenie when Screen1.Initialize jest wyzwalane podczas uruchomienia aplikacji. Pierwsza pozycja zmiennej QuestionList zostaje wybrana i umieszczona w bloku set QuestionLabel.Text. Gdy aplikacja zostanie uruchomiona, użytkownik zobaczy pierwsze pytanie.<br />
===Przetestuj to zachowanie===<br />
Jeśli dotychczas nie skomunikowałeś urządzenia mobilnego z programem, zrób to teraz. Co pojawia się na urządzeniu? Jeżeli utworzono listę QuestionList tak, jak wskazano powyżej, w etykiecie QuestionLabel powinna pojawić się pierwsza pozycja tej listy (Kto był doskonałym miotaczem w World Series?).<br />
<br />
==Iteracja pytań==<br />
Zdefiniowałeś już zmienną CurrentQuestionIndex, zapamiętującą pytanie, przy którym znajduje się użytkownik. Zaprogramuj teraz zachowanie przycisku NextButton. Gdy zostanie on kliknięty, aplikacja zwiększy wartość zmiennej, np. zmieni ją z 1 na 2 lub z 2 na 3 itd., a następnie użyje tej wartości do zaznaczenia nowego bieżącego pytania. Do tego zachowania potrzebne są następujące bloki:<br />
{| class="wikitable"<br />
!Typ bloku<br />
!Kategoria<br />
!Działanie<br />
|-<br />
|when NextButton.Click<br />
|NextButton<br />
|Uruchamia obsługę zdarzeń po kliknięciu przycisku<br />
|-<br />
|set currentQuestionIndex to<br />
|Zmienne<br />
|Decyduje o ustawieniu indeksu wybranej listy<br />
|-<br />
|+ <br />
|Math<br />
|Służy do zwiększania wartości zmiennej currentQuestionIndex<br />
|-<br />
|get global currentQuestionIndex<br />
|Zmienne<br />
|Tworzy nową wartość poprzez zwiększenie poprzedniej wartości o 1<br />
|-<br />
|0 (1)<br />
|Math<br />
|Dla + 1<br />
|-<br />
|set QuestionLabel.Text to<br />
|QuestionLabel<br />
|Wyświetla kolejne pytanie<br />
|-<br />
|select list item<br />
|Listy<br />
|Ustawia element listy jako wartość QuestionLabel<br />
|-<br />
|get global QuestionList<br />
|Zmienne<br />
|Wskazuje, która lista będzie wybrana<br />
|-<br />
|get global currentQuestionIndex<br />
|Zmienne<br />
|Wskazuje, który element wybranej listy będzie wybrany<br />
|}<br />
Bloki powinny wyglądać następująco:<br />
<br />
[[Plik:t6-6.png]]<br />
<br />
===Jak działają bloki?===<br />
Pierwszy wiersz polecenia zwiększa wartość zmiennej currentQuestionIndex o 1 (jeżeli zmienna zawiera wartość 1, zostaje ona zmieniona na 2, z 2 na 3 itd.). Następnie wykorzystuje nową wartość do wyboru pytania o tym indeksie.<br />
<br />
Przypomnijmy, że w bloku obsługi zdarzeń Screen.Initialize aplikacja wybrała pierwsze do wyświetlenia pytanie:<br />
<br />
[[Plik:t6-7.png]]<br />
<br />
Po kliknięciu przycisku NextButton aplikacja nie wybiera konkretnie pierwszej, drugiej czy trzeciej pozycji na liście, tylko pozycję o n-tej wartości zmiennej currentQuestionIndex.<br />
<br />
[[Plik:t6-8.png]]<br />
<br />
Polecenia w blokach są wykonywane od prawej do lewej, tzn. aplikacja najpierw określa wartość parametru z bloku Select list item, którym jest zmienna CurrentQuestionIndex. Liczba zawarta w tej zmiennej zostaje użyta jako indeks podczas wykonania poleceń zawartych w bloku Select list item.<br />
<br />
[[Plik:info.png|left]]''Po pierwszym kliknięciu przycisku NextButton, wartość zmiennej currentQuestionIndex przeskoczy z 1 na 2, aby aplikacja wybrała drugą pozycję z listy QuestionList (Kto był pierwszym doskonałym miotaczem w 2010?). Po drugim kliknięciu przycisku NextButton, wartość zmiennej currentQuestionIndex zostanie zmieniona z 2 na 3, a aplikacja wybierze trzecie pytanie z listy (Kto był pierwszym doskonałym miotaczem nowej ery?).''<br />
<br />
<br />
===Przetestuj to zachowanie===<br />
Przetestuj zachowanie przycisku NextButton, aby sprawdzić, czy aplikacja działa poprawnie. Wciel się w rolę użytkownika i kliknij przycisk NextButton w telefonie. Czy urządzenie wyświetliło drugie pytanie: Kto był pierwszym doskonałym miotaczem w 2010?? Trzecie pytanie powinno pojawić się po kolejnym kliknięciu przycisku. Jeżeli aplikacja działa, pogratuluj sobie i przejdź dalej. Kliknij przycisk NextButton ponownie (po raz trzeci). Powinien zostać wyświetlony błąd: Próba uzyskania elementu 4 z listy o długości 3. Czy wiesz, na czym polega problem?<br />
<br />
Problem z aplikacją polega na tym, że zawsze po kliknięciu przycisku NextButton zwiększa ona zmienną CurrentQuestionIndex o 1. Gdy wartość zmiennej wynosi już 3, a użytkownik kolejny raz kliknie przycisk NextButton, aplikacja zmieni wartość zmiennej z 3 na 4, następnie wywoła blok Select list item, aby odczytać pozycję o aktualnym indeksie CurrentQuestionIndex, czyli w tym przypadku czwartą pozycję. Ponieważ zmienna QuestionList zawiera tylko trzy elementy, Android wykaże błąd.<br />
<br />
Aplikacja musi zadawać pytanie - sprawdzać warunek - gdy nastąpi kliknięcie przycisku NextButton i realizować polecenia zawarte w różnych blokach w zależności od odpowiedzi. Elementem do sprawdzenia jest to, czy zmienna CurrentQuestionIndex już ma wartość 3. Jeżeli tak - należy ustawić CurrentQuestionIndex z powrotem na 0, aby użytkownik wrócił do pierwszego pytania.<br />
<br />
Będziesz potrzebował następujących bloków:<br />
{| class="wikitable"<br />
!Typ bloku<br />
!Kategoria<br />
!Działanie<br />
|-<br />
|if then<br />
|Control<br />
|sprawdzenie, czy użytkownik jest na etapie ostatniego pytania<br />
|-<br />
|= <br />
|Math<br />
|sprawdzenie, czy currentQuestionIndex ma wartość 3<br />
|-<br />
|get global currentQuestionIndex<br />
|Variables<br />
|<br />
|-<br />
|0 (3)<br />
|Math<br />
|3 to numer na liście<br />
|-<br />
|set currentQuestionIndex to<br />
|Variables<br />
|ustawienie na 0, aby wrócić do pierwszego pytania<br />
|-<br />
|0<br />
|Math<br />
|ustawienie na 0, ponieważ kolejne bloki zwiększą wartość do 1<br />
|}<br />
Zmodyfikowany blok obsługi zdarzenia When NextButton.Click powinien wyglądać następująco:<br />
<br />
[[Plik:t6-9.png]]<br />
<br />
===Jak działają bloki===<br />
Po kliknięciu przycisku NextButton aplikacja najpierw sprawdza, czy currentQuestionIndex ma wartość 3. Jeżeli tak, wartość tej zmiennej jest ustawiana na 0, aby po zwiększeniu jej w dalszych krokach jej wartość wyniosła 1. Wtedy quiz wróci do pierwszego pytania. Zauważ, że tylko bloki osadzone w bloku if-then są zależne od warunku. Blok zwiększenia wartości i blok Set QuestionLabel.Text to są wykonywane bez względu na jakikolwiek warunek.<br />
<br />
==Aplikacja modyfikowalna: Ułatwianie modyfikowania pytań==<br />
Teraz zmodyfikujemy aplikację, aby można było łatwo dodawać i usuwać elementy z listy. Zmień bloki tak, aby działały na liście o dowolnej długości, a nie tylko liście z dokładnie trzema pozycjami. <br />
Na początek dodaj czwarte pytanie do zmiennej QuestionList i kolejną odpowiedź do AnswerList. W tym celu musisz najpierw zwiększyć liczbę dostępnych pól za pomocą przycisku modyfikującego (mutatora). Aby dowiedzieć się więcej o tym elemencie, zobacz: http://appinventor.mit.edu/explore/ai2/support/concepts/mutators. Bloki powinny wyglądać następująco:<br />
<br />
[[Plik:t6-10.png]]<br />
<br />
===Przetestuj zmodyfikowaną aplikację.===<br />
Kliknij przycisk NextButton kilka razy. Zauważysz, że czwarte pytanie nigdy się nie pojawia, bez względu na to, ile razy klikniesz przycisk.<br />
<br />
Problemem jest to, że test sprawdzający, czy użytkownik znajduje się przy ostatnim pytaniu, jest zbyt szczegółowy: pyta, czy zmienna CurrentQuestionIndex ma wartość 3:<br />
<br />
[[Plik:t6-11.png]]<br />
<br />
Możesz po prostu zmienić liczbę z 3 na 4, a aplikacja będzie znów działać poprawnie. Problem polega jednak na tym, że za każdym razem, gdy zmodyfikujesz liczbę pytań i odpowiedzi, będziesz musiał pamiętać, aby dokonać także tej zmiany. Takie zależności w programie komputerowym często prowadzą do błędów, w szczególności gdy aplikacja staje się bardziej złożona. Znacznie lepiej jest przygotować program w taki sposób, aby działał niezależnie od liczby pytań. Takie uogólnienie jest jeszcze ważniejsze, gdy lista, z którą pracujesz, zmienia się dynamicznie, na przykład w aplikacji z quizem, gdzie użytkownik może dodawać nowe pytania.<br />
<br />
Lepszym rozwiązaniem jest sprawdzenie warunku w sposób bardziej ogólny. Tak naprawdę chcesz wiedzieć, czy bieżące pytanie – czyli wartość zmiennej currentQuestionIndex jest tak duża, jak ilość elementów w zmiennej QuestionList. Jeżeli aplikacja sprawdzi warunek w bardziej ogólny sposób, to będzie działać, nawet jeżeli dodasz lub usuniesz elementy ze zmiennej QuestionList. Aby zmienić blok obsługi zdarzenia When NextButton.Click, zmień poprzedni test sprawdzający, który odnosił się bezpośrednio do 3. Będziesz potrzebował następujących bloków:<br />
{| class="wikitable"<br />
!Typ bloku<br />
!Szuflada<br />
!Działanie<br />
|-<br />
|length of list<br />
|Lists<br />
|Pyta, ile elementów jest w zmiennej QuestionList<br />
|-<br />
|get global QuestionList<br />
|Variables<br />
|Określa, o którą listę chodzi<br />
|}<br />
Blok obsługi zdarzenia When NextButton.Click powinien teraz wyglądać następująco:<br />
<br />
[[Plik:t6-12.png]]<br />
<br />
<br />
<br />
===Jak działają bloki?===<br />
Warunek if porównuje teraz wartość zmiennej CurrentQuestionIndex z długością zmiennej QuestionList. Zatem jeżeli zmienna CurrentQuestionIndex ma wartość 4, a długość zmiennej QuestionList wynosi 4, to wartość zmiennej currentQuestionIndex zostanie ustawiona na 0 (a następnie na 1, 2 itd.). Zauważ - bloki nie odwołują się już do 3 ani żadnej innej określonej wartości, dlatego instrukcja będzie działać bez względu na liczbę elementów listy.<br />
<br />
Przetestuj zmodyfikowane zachowanie. Czy po kliknięciu przycisku NextButton aplikacja przechodzi teraz przez cztery pytania, wracając po ostatnim do pierwszego?<br />
<br />
==Przełączanie zdjęcia dla każdego pytania==<br />
Na razie aplikacja wyświetla to samo zdjęcie, bez względu na to, jakie pytanie zostaje zadane. Możesz to zmienić tak, aby po kliknięciu przycisku NextButton pojawiała się fotografia dotycząca danego pytania. W obszarze Media dostępne są cztery dodane wcześniej zdjęcia. Teraz utworzymy trzecią listę - PictureList, której elementami będą nazwy plików zdjęć, a następnie zmodyfikujemy blok obsługi zdarzenia When NextButton.Click, aby program po każdym pytaniu przełączał zdjęcie.<br />
Najpierw utwórz listę PictureList i zainicjuj ją nazwami plików graficznych. Upewnij się, czy nazwy są dokładnie takie same jak nazwy plików, które zostały załadowane do obszaru Media. Oto jak powinien wyglądać blok dla listy PictureList:<br />
<br />
[[Plik:t6-13.png]]<br />
<br />
Następnie zmodyfikuj blok obsługi zdarzeń When NextButton.Click, aby zmieniał wyświetlane zdjęcie w zależności od zadanego pytania. Jeżeli ustawisz właściwość Image.Picture na nazwę pliku zdjęcia, które zostało załadowane, właśnie ta fotografia zostanie wyświetlona. Aby zmodyfikować blok When NextButton.Click, potrzebujesz następujących bloków:<br />
{| class="wikitable"<br />
!Typ bloku<br />
!Kategoria<br />
!Działanie<br />
|-<br />
|set Image1.Picture to<br />
|Image1<br />
|ustaw, aby zmieniać zdjęcie<br />
|-<br />
|select list item<br />
|Lists<br />
|należy wybrać zdjęcie odpowiadające na aktualne pytanie<br />
|-<br />
|get global PictureList<br />
|Variables<br />
|wybierz nazwę pliku z tej listy<br />
|-<br />
|get global currentQuestionIndex<br />
|Variables<br />
|wybierz element o n-tym indeksie currentQuestionIndex<br />
|}<br />
Oto jak powinny wyglądać bloki:<br />
<br />
[[Plik:t6-14.png]]<br />
<br />
===Jak działają bloki?===<br />
Zmienna CurrentQuestionIndex służy jako indeks dla zmiennej QuestionList. Wartość CurrentQuestionIndex wynosi 1, aplikacja wybiera pierwsze pytanie i pierwsze zdjęcie. Gdy CurrentQuestionIndex wynosi 2, aplikacja wybiera drugie pytanie i drugie zdjęcie. Oczywiście takie działanie zależy od tego, czy listy są ze sobą zsynchronizowane. Tak jest w tym przypadku - pierwszy obraz - LarsenBerra.jpg to zdjęcie Dona Larsena, jednocześnie Don Larsen to odpowiedź na pierwsze pytanie (Kto był doskonałym miotaczem w World Series?). <br />
Przetestuj zmodyfikowane zachowanie. Czy nowe zdjęcie pojawia się po każdym kliknięciu przycisku NextButton?<br />
<br />
==Ocena udzielanych odpowiedzi==<br />
Teraz dodamy bloki, które określają, czy użytkownik odpowiedział na pytanie prawidłowo, czy też nie. Gracz wprowadza odpowiedź do AnswerText, a następnie klika przycisk AnswerButton. Aplikacja musi porównać wpis użytkownika z odpowiedzią na bieżące pytanie, używając bloku if... then... w celu jej sprawdzenia. Etykieta RightWrongLabel powinna być modyfikowana, aby podawać, czy odpowiedź jest prawidłowa, czy nie.<br />
<br />
Do tego zachowania będą potrzebne następujące bloki:<br />
{| class="wikitable"<br />
!Typ bloku<br />
!Kategoria<br />
!Działanie<br />
|-<br />
|when AnswerButton.Click<br />
|AnswerButton<br />
|zachowanie jest wyzwalane, gdy użytkownik kliknie przycisk AnswerButton<br />
|-<br />
|if... then...<br />
|Control<br />
|Użyj mutatora, aby dodać alternatywę (else). Jeżeli odpowiedź jest prawidłowa - zrób jedno, w przeciwnym razie (else) - zrób coś innego<br />
|-<br />
|= <br />
|Math<br />
|sprawdzenie, czy odpowiedź jest prawidłowa<br />
|-<br />
|AnswerText.Text<br />
|AnswerText<br />
|Odpowiedź użytkownika pojawia się w tym polu tekstowym<br />
|-<br />
|select list item<br />
|Lists<br />
|wybrać bieżącą odpowiedź z listy AnswerList<br />
|-<br />
|get global AnswerList<br />
|Variables<br />
|lista, z której jest wybierany element<br />
|-<br />
|get global currentQuestionIndex<br />
|Variables<br />
|numer pytania (i numer odpowiedzi), przy którym jest użytkownik<br />
|-<br />
|set RightWrongLabel.Text to<br />
|RightWrongLabel<br />
|tutaj podaj odpowiedź<br />
|-<br />
|Dobrze!<br />
|Text<br />
|jeżeli odpowiedź jest prawidłowa<br />
|-<br />
|set RightWrongLabel.Text to<br />
|RightWrongLabel<br />
|tutaj podaj odpowiedź<br />
|-<br />
|Źle<br />
|Text<br />
|jeżeli odpowiedź jest nieprawidłowa<br />
|}<br />
Bloki powinny wyglądać następująco:<br />
<br />
[[Plik:t6-15.png]]<br />
<br />
===Jak działają bloki?===<br />
Test if sprawdza, czy odpowiedź użytkownika (AnswerText.Text) jest taka sama, jak element na liście AnswerList o indeksie równym wartości zmiennej CurrentQuestionIndex. Jeżeli zmienna CurrentQuestionIndex ma wartość 1, aplikacja porównuje odpowiedź użytkownika z pierwszą pozycją na liście AnswerList, (Don Larsen). Jeżeli zmienna CurrentQuestionIndex zmieni wartość na 2, program zestawia odpowiedź z drugą pozycją na liście, czyli Dallas Branden. Jeśli wynik porównania jest pozytywny, przeprowadzane są bloki then, a treść etykiety RightWrongLabel zostaje ustawiona na Dobrze!. Jeżeli wynik testu jest negatywny (fałszywy), przeprowadzane są bloki alternatywy (else), a treść etykiety RightWrongLabel zostaje ustawiona na Źle.<br />
<br />
Przetestuj zmodyfikowaną aplikację. Spróbuj odpowiedzieć na jedno z pytań. Powinna pojawić się ocena, czy odpowiedź była dokładnie taka sama, jak na liście AnswerList. Sprawdź zarówno prawidłowe, jak i nieprawidłowe odpowiedzi (Uwaga - uwzględniana jest wielkość liter!). Kliknij przycisk NextButton i odpowiedz na drugie pytanie. Czy aplikacja nadal działa? Powinna, ale zauważ, że gdy klikniesz przycisk NextButton, tekst Dobrze! lub Źle oraz poprzednia odpowiedź nadal będą wyświetlane. Choć nie wpływa to zasadniczo na naszą grę, to takie szczegóły interfejsu z pewnością zostaną zauważone przez użytkowników Twojej aplikacji.<br />
<br />
Aby wyzerować etykietę RightWrongLabel i AnswerText, umieść poniższe bloki w bloku obsługi zdarzeń When NextButton.click:<br />
{| class="wikitable"<br />
!Typ bloku<br />
!Kategoria<br />
!Działanie<br />
|-<br />
|set RightWrongLabel.Text to<br />
|RightWrongLabel<br />
|Ustawia wartość etykiety na…<br />
|-<br />
|„ „<br />
|Text<br />
|pusty tekst<br />
|-<br />
|set AnswerText.Text to<br />
|AnswerText<br />
|Ustawia wartość etykiety na…<br />
|-<br />
|„ „<br />
|Text<br />
|pusty tekst<br />
|}<br />
Bloki powinny wyglądać następująco:<br />
<br />
[[Plik:t6-16.png]]<br />
<br />
===Jak działają bloki?===<br />
Po kliknięciu przycisku NextButton użytkownik przechodzi do następnego pytania, dlatego początkowe wiersze bloku obsługi zdarzeń zerują etykietę RightWrongLabel i pole AnswerText.<br />
Przetestuj to zachowanie Odpowiedz na pytanie i kliknij przycisk Wyślij, a następnie - NextButton. Czy Twoja poprzednia odpowiedź i jej ocena zniknęły?<br />
<br />
==Ostateczna postać programu==<br />
Oto gotowa aplikacja QuizMe:<br />
<br />
Utwórz wykonywalną wersję aplikacji, wybierając menu Build/App (provide QR code for .apk). Gdy pojawi się kod kreskowy, użyj czytnika kodów w telefonie, aby pobrać i zainstalować aplikację.<br />
<br />
===Modyfikacje===<br />
Quiz w tej wersji jest już gotowy. Czy masz ochotę przemyśleć pewne zmiany?<br />
<br />
Zamiast wyświetlać zdjęcie dla każdego pytania, spróbuj odtworzyć dźwięk lub krótkie wideo. Za pomocą dźwięku możesz zmienić quiz w aplikację Jaka to melodia?.<br />
<br />
Quiz akceptuje ściśle określone odpowiedzi. Jeśli gracz odpowiedziałby, lekko przekształcając tekst (np. podając inicjał zamiast imienia), program uzna to za błąd. Można to zmienić na kilka różnych sposobów. Jednym z nich jest użycie bloku text.contains, aby sprawdzić, czy odpowiedź użytkownika zawiera prawidłową odpowiedź. Inny sposób to dostarczenie wielu odpowiedzi na każde pytanie i sprawdzenie przez iterację (użycie bloku for each), czy któraś z nich pasuje.<br />
<br />
Przekształć quiz tak, aby przedstawiał odpowiedzi do wyboru. Lista odpowiedzi będzie musiała być listą list, a każda podrzędna lista będzie musiała zawierać opcje odpowiedzi. Użyj komponentu ListPicker, aby umożliwić użytkownikowi wybranie odpowiedzi.<br />
<br />
<br />
==Podsumowanie==<br />
Oto niektóre koncepcje omówione w tym przewodniku:<br />
<ul><li>Aplikacje można tworzyć w sposób ogólny, aby pracować z dowolną listą danych.</li><br />
<li>Zmienne indeksu są wykorzystywane do śledzenia bieżącej pozycji na liście. Zwiększając wartość zmiennej indeksu, należy uważać na przekroczenie końca listy.</li></ul><br />
<br />
==Zeskanuj próbną aplikację do telefonu==<br />
Aby zainstalować i uruchomić aplikację próbną, zeskanuj poniższy kod kreskowy:<br />
<br />
==Pobierz kod źródłowy==<br />
Jeżeli chcesz pracować z tą próbką w programie App Inventor:<br />
<ul><li>pobierz na komputer kod źródłowy: [http://appinventor.mit.edu/explore/sites/all/files/ai2tutorials/QuizMe/QuizMe_MIT.aia http://appinventor.mit.edu/explore/sites/all/files/ai2tutorials/QuizMe/QuizMe_MIT.aia]</li><br />
<li>otwórz program App Inventor,</li><br />
<li>kliknij opcję My Projects,</li><br />
<li>wybierz Import project (.aia) from my computer...</li><br />
<li>znajdź i zatwierdź pobrany kod źródłowy.</li></ul></div>M Kelniarzhttp://wiki.mistrzowiekodowania.pl/index.php?title=QuizMeQuizMe2015-03-15T18:38:14Z<p>M Kelniarz: /* Przełączanie zdjęcia dla każdego pytania */</p>
<hr />
<div>=Aplikacja QuizMe dla App Inventor 2=<br />
<br />
==Co tworzysz?==<br />
[[Plik:t6-1.png|right]]QuizMe to gra dotycząca ciekawostek baseballowych, ale można jej użyć jako szablonu do tworzenia quizów z dowolnej dziedziny. W aplikacji użytkownik odpowiada na szereg pytań, otrzymując następnie informację zwrotną, czy udzielił poprawnej, czy błędnej odpowiedzi. Gracz przechodzi do kolejnego pytania, klikając przycisk.<br />
<br />
W grze QuizMe dysponujemy zamkniętym zbiorem pytań, chyba że programista je zmieni. W następnym etapie można utworzyć MakeQuiz & TakeQuiz – aplikację, która pozwala użytkownikom na tworzenie i modyfikowanie pytań.<br />
<br />
Poradnik ten zakłada, że znasz już podstawy tworzenia aplikacji w App Inventorze – korzystanie z Projektanta komponentów w celu utworzenia interfejsu użytkownika i z Edytora bloków, aby określić obsługę zdarzeń. Jeżeli potrzebujesz przypomnienia, spróbuj popracować z poradnikami podstawowymi zanim przejdziesz dalej.<br />
<br />
==Zaczynamy!==<br />
Połącz się z witryną internetową App Inventor i załóż nowy projekt. Nazwij go QuizMe, ustaw taki sam tytuł ekranu (Title). Za pomocą MIT AI2 Companion połącz program z urządzeniem mobilnym. Pobierz poniższe zdjęcia baseballistów i zapisz je w komputerze. Później załadujesz je do projektu.<br />
<ul><li> [http://beta.appinventor.mit.edu/learn/tutorials/quizme/QuizMeAssets/Larsenberra.jpg Larsenberra.jpg]</li><br />
<li> [http://beta.appinventor.mit.edu/learn/tutorials/quizme/QuizMeAssets/dallasbraden.jpg Dallasbraden.jpg]</li><br />
<li> [http://beta.appinventor.mit.edu/learn/tutorials/quizme/QuizMeAssets/cyyoung.jpg Cyyoung.jpg]</li><br />
<li> [http://beta.appinventor.mit.edu/learn/tutorials/quizme/QuizMeAssets/nolanryan.jpg Nolanryan.jpg]</li></ul><br />
<br />
==Wstęp==<br />
Zaprojektujesz grę typu quiz, w której użytkownik będzie przechodził do kolejnych pytań, klikając przycisk Dalej, a następnie otrzymywał prostą ocenę Dobrze/Źle dla każdej odpowiedzi.<br />
<br />
W tym przewodniku omówimy:<br />
<ul><li>definiowanie i wyświetlanie listy informacji;</li><br />
<li>przechodzenie przez listę za pomocą zmiennej indeksującej – zmiennej, która śledzi pozycję na liście;</li><br />
<li>zachowania warunkowe – wykonywanie określonych operacji tylko wtedy, gdy spełniony jest określony warunek;</li><br />
<li>Zmianę zdjęcia w zależności od sytuacji.</li></ul><br />
<br />
==Projektowanie aplikacji==<br />
Użyj Projektanta komponentów do utworzenia interfejsu dla aplikacji QuizMe. <br />
Aby utworzyć interfejs, najpierw załaduj do projektu pobrane zdjęcia. Kliknij przycisk Prześlij plik (Upload File...) w obszarze Media i wybierz jeden z pobranych wcześniej plików (np. Larsenberra.jpg). Następnie zrób to samo z pozostałymi trzema zdjęciami.<br />
Utwórz następujące komponenty, przeciągając je z Palety (Palette) do Przeglądarki (Viewer) i ustaw właściwości komponentów zgodnie z poniższym opisem:<br />
{|class="wikitable"<br />
! Typ komponentu<br />
! Kategoria<br />
! Jaką nadać jej nazwę<br />
! Działanie<br />
! Działanie komponentu<br />
|-<br />
|Image<br />
|User interface<br />
|Image1<br />
|Ustaw właściwość zdjęcia (Picture) na Larsenberra.jpg. Jest to pierwsze wyświetlane zdjęcie.<br />
|Obrazkowa część pytania<br />
|-<br />
|Label<br />
|User interface<br />
|QuestionLabel<br />
|Zmień właściwość tekstu (Text) na Pytanie:<br />
|Wyświetla bieżące pytanie<br />
|-<br />
|HorizontalArrangement<br />
|Layout<br />
|HorizontalArrangement1<br />
| <br />
|Organizuje komponenty AnswerPrompt i Text (podaj odpowiedź i tekst)<br />
|-<br />
|Label<br />
|User interface<br />
|AnswerPromptLabel<br />
|Zmień właściwość tekstu (Text) na Podaj odpowiedź:. Na ekranie przeglądarki przesuń tę etykietę do HorizontalArrangement1.<br />
|Wyświetla tekst prośby o odpowiedź.<br />
|-<br />
|TextBox<br />
|User interface<br />
|AnswerText<br />
|Zmień wskazówkę (Hint) na Podaj odpowiedź. Na ekranie przeglądarki przenieś AnswerText do komponentu HorizontalArrangement1.<br />
|Tutaj użytkownik podaje odpowiedź.<br />
|-<br />
|Label<br />
|User interface <br />
|RightWrongLabel<br />
|Zmień właściwość tekstu (Text) na Dobrze/Źle.<br />
|Tutaj wyświetlana jest ocena Dobrze/Źle.<br />
|-<br />
|HorizontalArrangement<br />
|Layout<br />
|HorizontalArrangement2<br />
|<br />
|Organizuje przyciski AnswerButton i NextButton (przycisk odpowiedzi i przycisk dalej).<br />
|-<br />
|Przycisk<br />
|User interface<br />
|AnswerButton<br />
|Zmień właściwość tekstu (Text) na Wyślij. Na ekranie przeglądarki przesuń ten przycisk do HorizontalArrangment2.<br />
|Użytkownik klika, aby przesłać odpowiedź.<br />
|-<br />
|Przycisk<br />
|User interface<br />
|NextButton<br />
|Zmień właściwość tekstu (Text) na Dalej. Przenieś ten przycisk do HorizontalArrangement2.<br />
|Użytkownik klika, aby przejść do następnego pytania.<br />
|} <br />
Po zakończeniu powinien on wyglądać jak poniższa ilustracja (pod nią znajdują się również bardziej szczegółowe informacje).<br />
[[Plik:t6-2.png]]<br />
<br />
==Programowanie aplikacji==<br />
Otwórz Edytor bloków, aby zaprogramować działanie komponentów. Najpierw zdefiniuj dwie zmienne - listy: zmienną QuestionList, zawierającą listę pytań i zmienną AnswerList z listą odpowiedzi na te pytania.<br />
<br />
Aby zdefiniować te dwie zmienne listy, potrzebujesz następujących bloków:<br />
{| class="wikitable"<br />
!Typ bloku<br />
!Kategoria<br />
!Działanie<br />
|-<br />
|initialize global name to<br />
|Variables<br />
|Definiuje zmienną QuestionList (zmień jej nazwę)<br />
|-<br />
|initialize global name to<br />
|Variables<br />
|Definiuje zmienną AnswerList (zmień jej nazwę)<br />
|-<br />
|make a list<br />
|Lists<br />
|Służy do dodawania elementów do zmiennej QuestionList<br />
|-<br />
|„ „ (trzykrotnie)<br />
|Lists<br />
|Służy do wpisania pytań<br />
|-<br />
|make a list<br />
|Lists<br />
|Służy do dodawania elementów do zmiennej AnswerList<br />
|-<br />
|„ „ (trzykrotnie)<br />
|Text<br />
|Służy do wpisania odpowiedzi<br />
|}<br />
Utwórz zmienne całościowe, przeciągając z kategorii zmiennych (Variables) na obszar roboczy blok Initialize global name to. Kliknij dwukrotnie domyślną nazwę name, aby ją zmienić. Blok Initialize global name to zawiera pole na początkową wartość zmiennej. Zmienna może zawierać liczbę, tekst, a nawet listę – aby ją utworzyć, podłącz blok Make a list do definicji zmiennej.<br />
<br />
Bloki powinny wyglądać następująco:<br />
<br />
[[Plik:t6-3.png]]<br />
===Zdefiniuj ukrytą zmienną Index===<br />
Za każdym razem, gdy użytkownik kliknie przycisk NextButton, aby przejść dalej, aplikacja musi pamiętać, przy którym pytaniu jest obecnie gracz. W języku programowania, aby coś zapamiętać, trzeba zdefiniować nową zmienną. W tym przypadku aplikacja musi zapamiętać bieżący numer pytania – indeks listy QuestionList.<br />
Aby zdefiniować zmienną currentQuestionIndex, potrzebujesz następujących bloków:<br />
{| class="wikitable"<br />
!Typ bloku<br />
!Kategoria<br />
!Działanie<br />
|-<br />
|initialize global name to<br />
|Variables<br />
|Definiuje zmienną currentQuestionIndex (zmień nazwę)<br />
|-<br />
|0 (1)<br />
|Math<br />
|Ustaw wartość początkową currentQuestionIndex na 1 (zmień liczbę)<br />
|}<br />
Bloki powinny wyglądać następująco:<br />
<br />
[[Plik:t6-4.png]]<br />
<br />
===Wyświetl pierwsze pytanie===<br />
Odłóż na razie kwestię odpowiedzi i skup się na zaprogramowaniu sekwencyjnego przejścia przez pytania. Pożądane zachowanie jest następujące: po uruchomieniu aplikacji na etykiecie o nazwie QuestionLabel pojawia się pierwsze pytanie. Gdy użytkownik kliknie NextButton, wyświetlone zostaje drugie pytanie. Po ponownym kliknięciu pojawia się trzecie pytanie. Po dotarciu do ostatniego pytania kliknięcie przycisku NextButton powoduje ponowne pojawienie się pierwszego pytania w etykiecie QuestionLabel.<br />
<br />
W programie App Inventor określone pozycje na liście są wybierane za pomocą bloku select list item. W tym bloku trzeba podać listę i indeks – pozycję na liście. Jeżeli na liście są trzy pozycje, prawidłowe indeksy to 1, 2 i 3.<br />
<br />
Po uruchomieniu aplikacja QuizMe powinna wybrać pierwsze pytanie z listy i wyświetlić je w komponencie QuestionLabel. Do tego zachowania inicjalizującego działanie aplikacji potrzebne są następujące bloki:<br />
<br />
{| class="wikitable"<br />
!Typ bloku<br />
!Kategoria<br />
!Działanie<br />
|-<br />
|when Screen1.Initialize<br />
|Screen1<br />
|Podczas uruchamiania aplikacji zainicjowana jest ta obsługa zdarzenia<br />
|-<br />
|set QuestionLabel.Text to<br />
|QuestionLabel<br />
|Umieszcza pierwsze pytanie w etykiecie QuestionLabel<br />
|-<br />
|select list item<br />
|Lists<br />
|Wybiera pierwsze pytanie z etykiety QuestionLabel<br />
|-<br />
|get <br />
|Variables<br />
|Ustala listę, z której jest wybierany element. Tutaj: Global QuestionList<br />
|-<br />
|0 (1)<br />
|Math<br />
|Wybiera pierwsze pytanie za pomocą indeksu 1. Ustaw wartość na 1.<br />
|}<br />
Bloki powinny wyglądać następująco:<br />
<br />
[[Plik:t6-5.png]]<br />
<br />
===Jak działają bloki?===<br />
Zdarzenie when Screen1.Initialize jest wyzwalane podczas uruchomienia aplikacji. Pierwsza pozycja zmiennej QuestionList zostaje wybrana i umieszczona w bloku set QuestionLabel.Text. Gdy aplikacja zostanie uruchomiona, użytkownik zobaczy pierwsze pytanie.<br />
===Przetestuj to zachowanie===<br />
Jeśli dotychczas nie skomunikowałeś urządzenia mobilnego z programem, zrób to teraz. Co pojawia się na urządzeniu? Jeżeli utworzono listę QuestionList tak, jak wskazano powyżej, w etykiecie QuestionLabel powinna pojawić się pierwsza pozycja tej listy (Kto był doskonałym miotaczem w World Series?).<br />
<br />
==Iteracja pytań==<br />
Zdefiniowałeś już zmienną CurrentQuestionIndex, zapamiętującą pytanie, przy którym znajduje się użytkownik. Zaprogramuj teraz zachowanie przycisku NextButton. Gdy zostanie on kliknięty, aplikacja zwiększy wartość zmiennej, np. zmieni ją z 1 na 2 lub z 2 na 3 itd., a następnie użyje tej wartości do zaznaczenia nowego bieżącego pytania. Do tego zachowania potrzebne są następujące bloki:<br />
{| class="wikitable"<br />
!Typ bloku<br />
!Kategoria<br />
!Działanie<br />
|-<br />
|when NextButton.Click<br />
|NextButton<br />
|Uruchamia obsługę zdarzeń po kliknięciu przycisku<br />
|-<br />
|set currentQuestionIndex to<br />
|Zmienne<br />
|Decyduje o ustawieniu indeksu wybranej listy<br />
|-<br />
|+ <br />
|Math<br />
|Służy do zwiększania wartości zmiennej currentQuestionIndex<br />
|-<br />
|get global currentQuestionIndex<br />
|Zmienne<br />
|Tworzy nową wartość poprzez zwiększenie poprzedniej wartości o 1<br />
|-<br />
|0 (1)<br />
|Math<br />
|Dla + 1<br />
|-<br />
|set QuestionLabel.Text to<br />
|QuestionLabel<br />
|Wyświetla kolejne pytanie<br />
|-<br />
|select list item<br />
|Listy<br />
|Ustawia element listy jako wartość QuestionLabel<br />
|-<br />
|get global QuestionList<br />
|Zmienne<br />
|Wskazuje, która lista będzie wybrana<br />
|-<br />
|get global currentQuestionIndex<br />
|Zmienne<br />
|Wskazuje, który element wybranej listy będzie wybrany<br />
|}<br />
Bloki powinny wyglądać następująco:<br />
<br />
[[Plik:t6-6.png]]<br />
<br />
===Jak działają bloki?===<br />
Pierwszy wiersz polecenia zwiększa wartość zmiennej currentQuestionIndex o 1 (jeżeli zmienna zawiera wartość 1, zostaje ona zmieniona na 2, z 2 na 3 itd.). Następnie wykorzystuje nową wartość do wyboru pytania o tym indeksie.<br />
<br />
Przypomnijmy, że w bloku obsługi zdarzeń Screen.Initialize aplikacja wybrała pierwsze do wyświetlenia pytanie:<br />
<br />
[[Plik:t6-7.png]]<br />
<br />
Po kliknięciu przycisku NextButton aplikacja nie wybiera konkretnie pierwszej, drugiej czy trzeciej pozycji na liście, tylko pozycję o n-tej wartości zmiennej currentQuestionIndex.<br />
<br />
[[Plik:t6-8.png]]<br />
<br />
Polecenia w blokach są wykonywane od prawej do lewej, tzn. aplikacja najpierw określa wartość parametru z bloku Select list item, którym jest zmienna CurrentQuestionIndex. Liczba zawarta w tej zmiennej zostaje użyta jako indeks podczas wykonania poleceń zawartych w bloku Select list item.<br />
<br />
[[Plik:info.png|left]]''Po pierwszym kliknięciu przycisku NextButton, wartość zmiennej currentQuestionIndex przeskoczy z 1 na 2, aby aplikacja wybrała drugą pozycję z listy QuestionList (Kto był pierwszym doskonałym miotaczem w 2010?). Po drugim kliknięciu przycisku NextButton, wartość zmiennej currentQuestionIndex zostanie zmieniona z 2 na 3, a aplikacja wybierze trzecie pytanie z listy (Kto był pierwszym doskonałym miotaczem nowej ery?).''<br />
<br />
<br />
===Przetestuj to zachowanie===<br />
Przetestuj zachowanie przycisku NextButton, aby sprawdzić, czy aplikacja działa poprawnie. Wciel się w rolę użytkownika i kliknij przycisk NextButton w telefonie. Czy urządzenie wyświetliło drugie pytanie: Kto był pierwszym doskonałym miotaczem w 2010?? Trzecie pytanie powinno pojawić się po kolejnym kliknięciu przycisku. Jeżeli aplikacja działa, pogratuluj sobie i przejdź dalej. Kliknij przycisk NextButton ponownie (po raz trzeci). Powinien zostać wyświetlony błąd: Próba uzyskania elementu 4 z listy o długości 3. Czy wiesz, na czym polega problem?<br />
<br />
Problem z aplikacją polega na tym, że zawsze po kliknięciu przycisku NextButton zwiększa ona zmienną CurrentQuestionIndex o 1. Gdy wartość zmiennej wynosi już 3, a użytkownik kolejny raz kliknie przycisk NextButton, aplikacja zmieni wartość zmiennej z 3 na 4, następnie wywoła blok Select list item, aby odczytać pozycję o aktualnym indeksie CurrentQuestionIndex, czyli w tym przypadku czwartą pozycję. Ponieważ zmienna QuestionList zawiera tylko trzy elementy, Android wykaże błąd.<br />
<br />
Aplikacja musi zadawać pytanie - sprawdzać warunek - gdy nastąpi kliknięcie przycisku NextButton i realizować polecenia zawarte w różnych blokach w zależności od odpowiedzi. Elementem do sprawdzenia jest to, czy zmienna CurrentQuestionIndex już ma wartość 3. Jeżeli tak - należy ustawić CurrentQuestionIndex z powrotem na 0, aby użytkownik wrócił do pierwszego pytania.<br />
<br />
Będziesz potrzebował następujących bloków:<br />
{| class="wikitable"<br />
!Typ bloku<br />
!Kategoria<br />
!Działanie<br />
|-<br />
|if then<br />
|Control<br />
|sprawdzenie, czy użytkownik jest na etapie ostatniego pytania<br />
|-<br />
|= <br />
|Math<br />
|sprawdzenie, czy currentQuestionIndex ma wartość 3<br />
|-<br />
|get global currentQuestionIndex<br />
|Variables<br />
|<br />
|-<br />
|0 (3)<br />
|Math<br />
|3 to numer na liście<br />
|-<br />
|set currentQuestionIndex to<br />
|Variables<br />
|ustawienie na 0, aby wrócić do pierwszego pytania<br />
|-<br />
|0<br />
|Math<br />
|ustawienie na 0, ponieważ kolejne bloki zwiększą wartość do 1<br />
|}<br />
Zmodyfikowany blok obsługi zdarzenia When NextButton.Click powinien wyglądać następująco:<br />
<br />
[[Plik:t6-9.png]]<br />
<br />
===Jak działają bloki===<br />
Po kliknięciu przycisku NextButton aplikacja najpierw sprawdza, czy currentQuestionIndex ma wartość 3. Jeżeli tak, wartość tej zmiennej jest ustawiana na 0, aby po zwiększeniu jej w dalszych krokach jej wartość wyniosła 1. Wtedy quiz wróci do pierwszego pytania. Zauważ, że tylko bloki osadzone w bloku if-then są zależne od warunku. Blok zwiększenia wartości i blok Set QuestionLabel.Text to są wykonywane bez względu na jakikolwiek warunek.<br />
<br />
==Aplikacja modyfikowalna: Ułatwianie modyfikowania pytań==<br />
Teraz zmodyfikujemy aplikację, aby można było łatwo dodawać i usuwać elementy z listy. Zmień bloki tak, aby działały na liście o dowolnej długości, a nie tylko liście z dokładnie trzema pozycjami. <br />
Na początek dodaj czwarte pytanie do zmiennej QuestionList i kolejną odpowiedź do AnswerList. W tym celu musisz najpierw zwiększyć liczbę dostępnych pól za pomocą przycisku modyfikującego (mutatora). Aby dowiedzieć się więcej o tym elemencie, zobacz: http://appinventor.mit.edu/explore/ai2/support/concepts/mutators. Bloki powinny wyglądać następująco:<br />
<br />
[[Plik:t6-10.png]]<br />
<br />
===Przetestuj zmodyfikowaną aplikację.===<br />
Kliknij przycisk NextButton kilka razy. Zauważysz, że czwarte pytanie nigdy się nie pojawia, bez względu na to, ile razy klikniesz przycisk.<br />
<br />
Problemem jest to, że test sprawdzający, czy użytkownik znajduje się przy ostatnim pytaniu, jest zbyt szczegółowy: pyta, czy zmienna CurrentQuestionIndex ma wartość 3:<br />
<br />
[[Plik:t6-11.png]]<br />
<br />
Możesz po prostu zmienić liczbę z 3 na 4, a aplikacja będzie znów działać poprawnie. Problem polega jednak na tym, że za każdym razem, gdy zmodyfikujesz liczbę pytań i odpowiedzi, będziesz musiał pamiętać, aby dokonać także tej zmiany. Takie zależności w programie komputerowym często prowadzą do błędów, w szczególności gdy aplikacja staje się bardziej złożona. Znacznie lepiej jest przygotować program w taki sposób, aby działał niezależnie od liczby pytań. Takie uogólnienie jest jeszcze ważniejsze, gdy lista, z którą pracujesz, zmienia się dynamicznie, na przykład w aplikacji z quizem, gdzie użytkownik może dodawać nowe pytania.<br />
<br />
Lepszym rozwiązaniem jest sprawdzenie warunku w sposób bardziej ogólny. Tak naprawdę chcesz wiedzieć, czy bieżące pytanie – czyli wartość zmiennej currentQuestionIndex jest tak duża, jak ilość elementów w zmiennej QuestionList. Jeżeli aplikacja sprawdzi warunek w bardziej ogólny sposób, to będzie działać, nawet jeżeli dodasz lub usuniesz elementy ze zmiennej QuestionList. Aby zmienić blok obsługi zdarzenia When NextButton.Click, zmień poprzedni test sprawdzający, który odnosił się bezpośrednio do 3. Będziesz potrzebował następujących bloków:<br />
{| class="wikitable"<br />
!Typ bloku<br />
!Szuflada<br />
!Działanie<br />
|-<br />
|length of list<br />
|Lists<br />
|Pyta, ile elementów jest w zmiennej QuestionList<br />
|-<br />
|get global QuestionList<br />
|Variables<br />
|Określa, o którą listę chodzi<br />
|}<br />
Blok obsługi zdarzenia When NextButton.Click powinien teraz wyglądać następująco:<br />
<br />
[[Plik:t6-12.png]]<br />
<br />
<br />
<br />
===Jak działają bloki?===<br />
Warunek if porównuje teraz wartość zmiennej CurrentQuestionIndex z długością zmiennej QuestionList. Zatem jeżeli zmienna CurrentQuestionIndex ma wartość 4, a długość zmiennej QuestionList wynosi 4, to wartość zmiennej currentQuestionIndex zostanie ustawiona na 0 (a następnie na 1, 2 itd.). Zauważ - bloki nie odwołują się już do 3 ani żadnej innej określonej wartości, dlatego instrukcja będzie działać bez względu na liczbę elementów listy.<br />
<br />
Przetestuj zmodyfikowane zachowanie. Czy po kliknięciu przycisku NextButton aplikacja przechodzi teraz przez cztery pytania, wracając po ostatnim do pierwszego?<br />
<br />
==Przełączanie zdjęcia dla każdego pytania==<br />
Na razie aplikacja wyświetla to samo zdjęcie, bez względu na to, jakie pytanie zostaje zadane. Możesz to zmienić tak, aby po kliknięciu przycisku NextButton pojawiała się fotografia dotycząca danego pytania. W obszarze Media dostępne są cztery dodane wcześniej zdjęcia. Teraz utworzymy trzecią listę - PictureList, której elementami będą nazwy plików zdjęć, a następnie zmodyfikujemy blok obsługi zdarzenia When NextButton.Click, aby program po każdym pytaniu przełączał zdjęcie.<br />
Najpierw utwórz listę PictureList i zainicjuj ją nazwami plików graficznych. Upewnij się, czy nazwy są dokładnie takie same jak nazwy plików, które zostały załadowane do obszaru Media. Oto jak powinien wyglądać blok dla listy PictureList:<br />
<br />
[[Plik:t6-13.png]]<br />
<br />
Następnie zmodyfikuj blok obsługi zdarzeń When NextButton.Click, aby zmieniał wyświetlane zdjęcie w zależności od zadanego pytania. Jeżeli ustawisz właściwość Image.Picture na nazwę pliku zdjęcia, które zostało załadowane, właśnie ta fotografia zostanie wyświetlona. Aby zmodyfikować blok When NextButton.Click, potrzebujesz następujących bloków:<br />
{| class="wikitable"<br />
!Typ bloku<br />
!Kategoria<br />
!Działanie<br />
|-<br />
|set Image1.Picture to<br />
|Image1<br />
|ustaw, aby zmieniać zdjęcie<br />
|-<br />
|select list item<br />
|Lists<br />
|należy wybrać zdjęcie odpowiadające na aktualne pytanie<br />
|-<br />
|get global PictureList<br />
|Variables<br />
|wybierz nazwę pliku z tej listy<br />
|-<br />
|get global currentQuestionIndex<br />
|Variables<br />
|wybierz element o n-tym indeksie currentQuestionIndex<br />
|}<br />
Oto jak powinny wyglądać bloki:<br />
<br />
[[Plik:t6-14.png]]<br />
<br />
===Jak działają bloki?===<br />
Zmienna CurrentQuestionIndex służy jako indeks dla zmiennej QuestionList. Wartość CurrentQuestionIndex wynosi 1, aplikacja wybiera pierwsze pytanie i pierwsze zdjęcie. Gdy CurrentQuestionIndex wynosi 2, aplikacja wybiera drugie pytanie i drugie zdjęcie. Oczywiście takie działanie zależy od tego, czy listy są ze sobą zsynchronizowane. Tak jest w tym przypadku - pierwszy obraz - LarsenBerra.jpg to zdjęcie Dona Larsena, jednocześnie Don Larsen to odpowiedź na pierwsze pytanie (Kto był doskonałym miotaczem w World Series?). <br />
Przetestuj zmodyfikowane zachowanie. Czy nowe zdjęcie pojawia się po każdym kliknięciu przycisku NextButton?<br />
<br />
==Ocena udzielanych odpowiedzi==<br />
Teraz dodamy bloki, które określają, czy użytkownik odpowiedział na pytanie prawidłowo, czy też nie. Gracz wprowadza odpowiedź do AnswerText, a następnie klika przycisk AnswerButton. Aplikacja musi porównać wpis użytkownika z odpowiedzią na bieżące pytanie, używając bloku if... then... w celu jej sprawdzenia. Etykieta RightWrongLabel powinna być modyfikowana, aby podawać, czy odpowiedź jest prawidłowa, czy nie.<br />
<br />
Do tego zachowania będą potrzebne następujące bloki:<br />
{| class="wikitable"<br />
!Typ bloku<br />
!Kategoria<br />
!Działanie<br />
|-<br />
|when AnswerButton.Click<br />
|AnswerButton<br />
|zachowanie jest wyzwalane, gdy użytkownik kliknie przycisk AnswerButton<br />
|-<br />
|if... then...<br />
|Control<br />
|Użyj mutatora, aby dodać alternatywę (else). Jeżeli odpowiedź jest prawidłowa - zrób jedno, w przeciwnym razie (else) - zrób coś innego<br />
|-<br />
|= <br />
|Math<br />
|sprawdzenie, czy odpowiedź jest prawidłowa<br />
|-<br />
|AnswerText.Text<br />
|AnswerText<br />
|Odpowiedź użytkownika pojawia się w tym polu tekstowym<br />
|-<br />
|select list item<br />
|Lists<br />
|wybrać bieżącą odpowiedź z listy AnswerList<br />
|-<br />
|get global AnswerList<br />
|Variables<br />
|lista, z której jest wybierany element<br />
|-<br />
|get global currentQuestionIndex<br />
|Variables<br />
|numer pytania (i numer odpowiedzi), przy którym jest użytkownik<br />
|-<br />
|set RightWrongLabel.Text to<br />
|RightWrongLabel<br />
|tutaj podaj odpowiedź<br />
|-<br />
|Dobrze!<br />
|Text<br />
|jeżeli odpowiedź jest prawidłowa<br />
|-<br />
|set RightWrongLabel.Text to<br />
|RightWrongLabel<br />
|tutaj podaj odpowiedź<br />
|-<br />
|Źle<br />
|Text<br />
|jeżeli odpowiedź jest nieprawidłowa<br />
|}<br />
Bloki powinny wyglądać następująco:<br />
<br />
===Jak działają bloki?===<br />
Test if sprawdza, czy odpowiedź użytkownika (AnswerText.Text) jest taka sama, jak element na liście AnswerList o indeksie równym wartości zmiennej CurrentQuestionIndex. Jeżeli zmienna CurrentQuestionIndex ma wartość 1, aplikacja porównuje odpowiedź użytkownika z pierwszą pozycją na liście AnswerList, (Don Larsen). Jeżeli zmienna CurrentQuestionIndex zmieni wartość na 2, program zestawia odpowiedź z drugą pozycją na liście, czyli Dallas Branden. Jeśli wynik porównania jest pozytywny, przeprowadzane są bloki then, a treść etykiety RightWrongLabel zostaje ustawiona na Dobrze!. Jeżeli wynik testu jest negatywny (fałszywy), przeprowadzane są bloki alternatywy (else), a treść etykiety RightWrongLabel zostaje ustawiona na Źle.<br />
<br />
Przetestuj zmodyfikowaną aplikację. Spróbuj odpowiedzieć na jedno z pytań. Powinna pojawić się ocena, czy odpowiedź była dokładnie taka sama, jak na liście AnswerList. Sprawdź zarówno prawidłowe, jak i nieprawidłowe odpowiedzi (Uwaga - uwzględniana jest wielkość liter!). Kliknij przycisk NextButton i odpowiedz na drugie pytanie. Czy aplikacja nadal działa? Powinna, ale zauważ, że gdy klikniesz przycisk NextButton, tekst Dobrze! lub Źle oraz poprzednia odpowiedź nadal będą wyświetlane. Choć nie wpływa to zasadniczo na naszą grę, to takie szczegóły interfejsu z pewnością zostaną zauważone przez użytkowników Twojej aplikacji.<br />
<br />
Aby wyzerować etykietę RightWrongLabel i AnswerText, umieść poniższe bloki w bloku obsługi zdarzeń When NextButton.click:<br />
{| class="wikitable"<br />
!Typ bloku<br />
!Kategoria<br />
!Działanie<br />
|-<br />
|set RightWrongLabel.Text to<br />
|RightWrongLabel<br />
|Ustawia wartość etykiety na…<br />
|-<br />
|„ „<br />
|Text<br />
|pusty tekst<br />
|-<br />
|set AnswerText.Text to<br />
|AnswerText<br />
|Ustawia wartość etykiety na…<br />
|-<br />
|„ „<br />
|Text<br />
|pusty tekst<br />
|}<br />
Bloki powinny wyglądać następująco:<br />
<br />
===Jak działają bloki?===<br />
Po kliknięciu przycisku NextButton użytkownik przechodzi do następnego pytania, dlatego początkowe wiersze bloku obsługi zdarzeń zerują etykietę RightWrongLabel i pole AnswerText.<br />
Przetestuj to zachowanie Odpowiedz na pytanie i kliknij przycisk Wyślij, a następnie - NextButton. Czy Twoja poprzednia odpowiedź i jej ocena zniknęły?<br />
<br />
==Ostateczna postać programu==<br />
Oto gotowa aplikacja QuizMe:<br />
<br />
Utwórz wykonywalną wersję aplikacji, wybierając menu Build/App (provide QR code for .apk). Gdy pojawi się kod kreskowy, użyj czytnika kodów w telefonie, aby pobrać i zainstalować aplikację.<br />
<br />
===Modyfikacje===<br />
Quiz w tej wersji jest już gotowy. Czy masz ochotę przemyśleć pewne zmiany?<br />
<br />
Zamiast wyświetlać zdjęcie dla każdego pytania, spróbuj odtworzyć dźwięk lub krótkie wideo. Za pomocą dźwięku możesz zmienić quiz w aplikację Jaka to melodia?.<br />
<br />
Quiz akceptuje ściśle określone odpowiedzi. Jeśli gracz odpowiedziałby, lekko przekształcając tekst (np. podając inicjał zamiast imienia), program uzna to za błąd. Można to zmienić na kilka różnych sposobów. Jednym z nich jest użycie bloku text.contains, aby sprawdzić, czy odpowiedź użytkownika zawiera prawidłową odpowiedź. Inny sposób to dostarczenie wielu odpowiedzi na każde pytanie i sprawdzenie przez iterację (użycie bloku for each), czy któraś z nich pasuje.<br />
<br />
Przekształć quiz tak, aby przedstawiał odpowiedzi do wyboru. Lista odpowiedzi będzie musiała być listą list, a każda podrzędna lista będzie musiała zawierać opcje odpowiedzi. Użyj komponentu ListPicker, aby umożliwić użytkownikowi wybranie odpowiedzi.<br />
<br />
<br />
==Podsumowanie==<br />
Oto niektóre koncepcje omówione w tym przewodniku:<br />
<ul><li>Aplikacje można tworzyć w sposób ogólny, aby pracować z dowolną listą danych.</li><br />
<li>Zmienne indeksu są wykorzystywane do śledzenia bieżącej pozycji na liście. Zwiększając wartość zmiennej indeksu, należy uważać na przekroczenie końca listy.</li></ul><br />
<br />
==Zeskanuj próbną aplikację do telefonu==<br />
Aby zainstalować i uruchomić aplikację próbną, zeskanuj poniższy kod kreskowy:<br />
<br />
==Pobierz kod źródłowy==<br />
Jeżeli chcesz pracować z tą próbką w programie App Inventor:<br />
<ul><li>pobierz na komputer kod źródłowy: [http://appinventor.mit.edu/explore/sites/all/files/ai2tutorials/QuizMe/QuizMe_MIT.aia http://appinventor.mit.edu/explore/sites/all/files/ai2tutorials/QuizMe/QuizMe_MIT.aia]</li><br />
<li>otwórz program App Inventor,</li><br />
<li>kliknij opcję My Projects,</li><br />
<li>wybierz Import project (.aia) from my computer...</li><br />
<li>znajdź i zatwierdź pobrany kod źródłowy.</li></ul></div>M Kelniarzhttp://wiki.mistrzowiekodowania.pl/index.php?title=QuizMeQuizMe2015-03-15T18:37:03Z<p>M Kelniarz: /* Przetestuj zmodyfikowaną aplikację. */</p>
<hr />
<div>=Aplikacja QuizMe dla App Inventor 2=<br />
<br />
==Co tworzysz?==<br />
[[Plik:t6-1.png|right]]QuizMe to gra dotycząca ciekawostek baseballowych, ale można jej użyć jako szablonu do tworzenia quizów z dowolnej dziedziny. W aplikacji użytkownik odpowiada na szereg pytań, otrzymując następnie informację zwrotną, czy udzielił poprawnej, czy błędnej odpowiedzi. Gracz przechodzi do kolejnego pytania, klikając przycisk.<br />
<br />
W grze QuizMe dysponujemy zamkniętym zbiorem pytań, chyba że programista je zmieni. W następnym etapie można utworzyć MakeQuiz & TakeQuiz – aplikację, która pozwala użytkownikom na tworzenie i modyfikowanie pytań.<br />
<br />
Poradnik ten zakłada, że znasz już podstawy tworzenia aplikacji w App Inventorze – korzystanie z Projektanta komponentów w celu utworzenia interfejsu użytkownika i z Edytora bloków, aby określić obsługę zdarzeń. Jeżeli potrzebujesz przypomnienia, spróbuj popracować z poradnikami podstawowymi zanim przejdziesz dalej.<br />
<br />
==Zaczynamy!==<br />
Połącz się z witryną internetową App Inventor i załóż nowy projekt. Nazwij go QuizMe, ustaw taki sam tytuł ekranu (Title). Za pomocą MIT AI2 Companion połącz program z urządzeniem mobilnym. Pobierz poniższe zdjęcia baseballistów i zapisz je w komputerze. Później załadujesz je do projektu.<br />
<ul><li> [http://beta.appinventor.mit.edu/learn/tutorials/quizme/QuizMeAssets/Larsenberra.jpg Larsenberra.jpg]</li><br />
<li> [http://beta.appinventor.mit.edu/learn/tutorials/quizme/QuizMeAssets/dallasbraden.jpg Dallasbraden.jpg]</li><br />
<li> [http://beta.appinventor.mit.edu/learn/tutorials/quizme/QuizMeAssets/cyyoung.jpg Cyyoung.jpg]</li><br />
<li> [http://beta.appinventor.mit.edu/learn/tutorials/quizme/QuizMeAssets/nolanryan.jpg Nolanryan.jpg]</li></ul><br />
<br />
==Wstęp==<br />
Zaprojektujesz grę typu quiz, w której użytkownik będzie przechodził do kolejnych pytań, klikając przycisk Dalej, a następnie otrzymywał prostą ocenę Dobrze/Źle dla każdej odpowiedzi.<br />
<br />
W tym przewodniku omówimy:<br />
<ul><li>definiowanie i wyświetlanie listy informacji;</li><br />
<li>przechodzenie przez listę za pomocą zmiennej indeksującej – zmiennej, która śledzi pozycję na liście;</li><br />
<li>zachowania warunkowe – wykonywanie określonych operacji tylko wtedy, gdy spełniony jest określony warunek;</li><br />
<li>Zmianę zdjęcia w zależności od sytuacji.</li></ul><br />
<br />
==Projektowanie aplikacji==<br />
Użyj Projektanta komponentów do utworzenia interfejsu dla aplikacji QuizMe. <br />
Aby utworzyć interfejs, najpierw załaduj do projektu pobrane zdjęcia. Kliknij przycisk Prześlij plik (Upload File...) w obszarze Media i wybierz jeden z pobranych wcześniej plików (np. Larsenberra.jpg). Następnie zrób to samo z pozostałymi trzema zdjęciami.<br />
Utwórz następujące komponenty, przeciągając je z Palety (Palette) do Przeglądarki (Viewer) i ustaw właściwości komponentów zgodnie z poniższym opisem:<br />
{|class="wikitable"<br />
! Typ komponentu<br />
! Kategoria<br />
! Jaką nadać jej nazwę<br />
! Działanie<br />
! Działanie komponentu<br />
|-<br />
|Image<br />
|User interface<br />
|Image1<br />
|Ustaw właściwość zdjęcia (Picture) na Larsenberra.jpg. Jest to pierwsze wyświetlane zdjęcie.<br />
|Obrazkowa część pytania<br />
|-<br />
|Label<br />
|User interface<br />
|QuestionLabel<br />
|Zmień właściwość tekstu (Text) na Pytanie:<br />
|Wyświetla bieżące pytanie<br />
|-<br />
|HorizontalArrangement<br />
|Layout<br />
|HorizontalArrangement1<br />
| <br />
|Organizuje komponenty AnswerPrompt i Text (podaj odpowiedź i tekst)<br />
|-<br />
|Label<br />
|User interface<br />
|AnswerPromptLabel<br />
|Zmień właściwość tekstu (Text) na Podaj odpowiedź:. Na ekranie przeglądarki przesuń tę etykietę do HorizontalArrangement1.<br />
|Wyświetla tekst prośby o odpowiedź.<br />
|-<br />
|TextBox<br />
|User interface<br />
|AnswerText<br />
|Zmień wskazówkę (Hint) na Podaj odpowiedź. Na ekranie przeglądarki przenieś AnswerText do komponentu HorizontalArrangement1.<br />
|Tutaj użytkownik podaje odpowiedź.<br />
|-<br />
|Label<br />
|User interface <br />
|RightWrongLabel<br />
|Zmień właściwość tekstu (Text) na Dobrze/Źle.<br />
|Tutaj wyświetlana jest ocena Dobrze/Źle.<br />
|-<br />
|HorizontalArrangement<br />
|Layout<br />
|HorizontalArrangement2<br />
|<br />
|Organizuje przyciski AnswerButton i NextButton (przycisk odpowiedzi i przycisk dalej).<br />
|-<br />
|Przycisk<br />
|User interface<br />
|AnswerButton<br />
|Zmień właściwość tekstu (Text) na Wyślij. Na ekranie przeglądarki przesuń ten przycisk do HorizontalArrangment2.<br />
|Użytkownik klika, aby przesłać odpowiedź.<br />
|-<br />
|Przycisk<br />
|User interface<br />
|NextButton<br />
|Zmień właściwość tekstu (Text) na Dalej. Przenieś ten przycisk do HorizontalArrangement2.<br />
|Użytkownik klika, aby przejść do następnego pytania.<br />
|} <br />
Po zakończeniu powinien on wyglądać jak poniższa ilustracja (pod nią znajdują się również bardziej szczegółowe informacje).<br />
[[Plik:t6-2.png]]<br />
<br />
==Programowanie aplikacji==<br />
Otwórz Edytor bloków, aby zaprogramować działanie komponentów. Najpierw zdefiniuj dwie zmienne - listy: zmienną QuestionList, zawierającą listę pytań i zmienną AnswerList z listą odpowiedzi na te pytania.<br />
<br />
Aby zdefiniować te dwie zmienne listy, potrzebujesz następujących bloków:<br />
{| class="wikitable"<br />
!Typ bloku<br />
!Kategoria<br />
!Działanie<br />
|-<br />
|initialize global name to<br />
|Variables<br />
|Definiuje zmienną QuestionList (zmień jej nazwę)<br />
|-<br />
|initialize global name to<br />
|Variables<br />
|Definiuje zmienną AnswerList (zmień jej nazwę)<br />
|-<br />
|make a list<br />
|Lists<br />
|Służy do dodawania elementów do zmiennej QuestionList<br />
|-<br />
|„ „ (trzykrotnie)<br />
|Lists<br />
|Służy do wpisania pytań<br />
|-<br />
|make a list<br />
|Lists<br />
|Służy do dodawania elementów do zmiennej AnswerList<br />
|-<br />
|„ „ (trzykrotnie)<br />
|Text<br />
|Służy do wpisania odpowiedzi<br />
|}<br />
Utwórz zmienne całościowe, przeciągając z kategorii zmiennych (Variables) na obszar roboczy blok Initialize global name to. Kliknij dwukrotnie domyślną nazwę name, aby ją zmienić. Blok Initialize global name to zawiera pole na początkową wartość zmiennej. Zmienna może zawierać liczbę, tekst, a nawet listę – aby ją utworzyć, podłącz blok Make a list do definicji zmiennej.<br />
<br />
Bloki powinny wyglądać następująco:<br />
<br />
[[Plik:t6-3.png]]<br />
===Zdefiniuj ukrytą zmienną Index===<br />
Za każdym razem, gdy użytkownik kliknie przycisk NextButton, aby przejść dalej, aplikacja musi pamiętać, przy którym pytaniu jest obecnie gracz. W języku programowania, aby coś zapamiętać, trzeba zdefiniować nową zmienną. W tym przypadku aplikacja musi zapamiętać bieżący numer pytania – indeks listy QuestionList.<br />
Aby zdefiniować zmienną currentQuestionIndex, potrzebujesz następujących bloków:<br />
{| class="wikitable"<br />
!Typ bloku<br />
!Kategoria<br />
!Działanie<br />
|-<br />
|initialize global name to<br />
|Variables<br />
|Definiuje zmienną currentQuestionIndex (zmień nazwę)<br />
|-<br />
|0 (1)<br />
|Math<br />
|Ustaw wartość początkową currentQuestionIndex na 1 (zmień liczbę)<br />
|}<br />
Bloki powinny wyglądać następująco:<br />
<br />
[[Plik:t6-4.png]]<br />
<br />
===Wyświetl pierwsze pytanie===<br />
Odłóż na razie kwestię odpowiedzi i skup się na zaprogramowaniu sekwencyjnego przejścia przez pytania. Pożądane zachowanie jest następujące: po uruchomieniu aplikacji na etykiecie o nazwie QuestionLabel pojawia się pierwsze pytanie. Gdy użytkownik kliknie NextButton, wyświetlone zostaje drugie pytanie. Po ponownym kliknięciu pojawia się trzecie pytanie. Po dotarciu do ostatniego pytania kliknięcie przycisku NextButton powoduje ponowne pojawienie się pierwszego pytania w etykiecie QuestionLabel.<br />
<br />
W programie App Inventor określone pozycje na liście są wybierane za pomocą bloku select list item. W tym bloku trzeba podać listę i indeks – pozycję na liście. Jeżeli na liście są trzy pozycje, prawidłowe indeksy to 1, 2 i 3.<br />
<br />
Po uruchomieniu aplikacja QuizMe powinna wybrać pierwsze pytanie z listy i wyświetlić je w komponencie QuestionLabel. Do tego zachowania inicjalizującego działanie aplikacji potrzebne są następujące bloki:<br />
<br />
{| class="wikitable"<br />
!Typ bloku<br />
!Kategoria<br />
!Działanie<br />
|-<br />
|when Screen1.Initialize<br />
|Screen1<br />
|Podczas uruchamiania aplikacji zainicjowana jest ta obsługa zdarzenia<br />
|-<br />
|set QuestionLabel.Text to<br />
|QuestionLabel<br />
|Umieszcza pierwsze pytanie w etykiecie QuestionLabel<br />
|-<br />
|select list item<br />
|Lists<br />
|Wybiera pierwsze pytanie z etykiety QuestionLabel<br />
|-<br />
|get <br />
|Variables<br />
|Ustala listę, z której jest wybierany element. Tutaj: Global QuestionList<br />
|-<br />
|0 (1)<br />
|Math<br />
|Wybiera pierwsze pytanie za pomocą indeksu 1. Ustaw wartość na 1.<br />
|}<br />
Bloki powinny wyglądać następująco:<br />
<br />
[[Plik:t6-5.png]]<br />
<br />
===Jak działają bloki?===<br />
Zdarzenie when Screen1.Initialize jest wyzwalane podczas uruchomienia aplikacji. Pierwsza pozycja zmiennej QuestionList zostaje wybrana i umieszczona w bloku set QuestionLabel.Text. Gdy aplikacja zostanie uruchomiona, użytkownik zobaczy pierwsze pytanie.<br />
===Przetestuj to zachowanie===<br />
Jeśli dotychczas nie skomunikowałeś urządzenia mobilnego z programem, zrób to teraz. Co pojawia się na urządzeniu? Jeżeli utworzono listę QuestionList tak, jak wskazano powyżej, w etykiecie QuestionLabel powinna pojawić się pierwsza pozycja tej listy (Kto był doskonałym miotaczem w World Series?).<br />
<br />
==Iteracja pytań==<br />
Zdefiniowałeś już zmienną CurrentQuestionIndex, zapamiętującą pytanie, przy którym znajduje się użytkownik. Zaprogramuj teraz zachowanie przycisku NextButton. Gdy zostanie on kliknięty, aplikacja zwiększy wartość zmiennej, np. zmieni ją z 1 na 2 lub z 2 na 3 itd., a następnie użyje tej wartości do zaznaczenia nowego bieżącego pytania. Do tego zachowania potrzebne są następujące bloki:<br />
{| class="wikitable"<br />
!Typ bloku<br />
!Kategoria<br />
!Działanie<br />
|-<br />
|when NextButton.Click<br />
|NextButton<br />
|Uruchamia obsługę zdarzeń po kliknięciu przycisku<br />
|-<br />
|set currentQuestionIndex to<br />
|Zmienne<br />
|Decyduje o ustawieniu indeksu wybranej listy<br />
|-<br />
|+ <br />
|Math<br />
|Służy do zwiększania wartości zmiennej currentQuestionIndex<br />
|-<br />
|get global currentQuestionIndex<br />
|Zmienne<br />
|Tworzy nową wartość poprzez zwiększenie poprzedniej wartości o 1<br />
|-<br />
|0 (1)<br />
|Math<br />
|Dla + 1<br />
|-<br />
|set QuestionLabel.Text to<br />
|QuestionLabel<br />
|Wyświetla kolejne pytanie<br />
|-<br />
|select list item<br />
|Listy<br />
|Ustawia element listy jako wartość QuestionLabel<br />
|-<br />
|get global QuestionList<br />
|Zmienne<br />
|Wskazuje, która lista będzie wybrana<br />
|-<br />
|get global currentQuestionIndex<br />
|Zmienne<br />
|Wskazuje, który element wybranej listy będzie wybrany<br />
|}<br />
Bloki powinny wyglądać następująco:<br />
<br />
[[Plik:t6-6.png]]<br />
<br />
===Jak działają bloki?===<br />
Pierwszy wiersz polecenia zwiększa wartość zmiennej currentQuestionIndex o 1 (jeżeli zmienna zawiera wartość 1, zostaje ona zmieniona na 2, z 2 na 3 itd.). Następnie wykorzystuje nową wartość do wyboru pytania o tym indeksie.<br />
<br />
Przypomnijmy, że w bloku obsługi zdarzeń Screen.Initialize aplikacja wybrała pierwsze do wyświetlenia pytanie:<br />
<br />
[[Plik:t6-7.png]]<br />
<br />
Po kliknięciu przycisku NextButton aplikacja nie wybiera konkretnie pierwszej, drugiej czy trzeciej pozycji na liście, tylko pozycję o n-tej wartości zmiennej currentQuestionIndex.<br />
<br />
[[Plik:t6-8.png]]<br />
<br />
Polecenia w blokach są wykonywane od prawej do lewej, tzn. aplikacja najpierw określa wartość parametru z bloku Select list item, którym jest zmienna CurrentQuestionIndex. Liczba zawarta w tej zmiennej zostaje użyta jako indeks podczas wykonania poleceń zawartych w bloku Select list item.<br />
<br />
[[Plik:info.png|left]]''Po pierwszym kliknięciu przycisku NextButton, wartość zmiennej currentQuestionIndex przeskoczy z 1 na 2, aby aplikacja wybrała drugą pozycję z listy QuestionList (Kto był pierwszym doskonałym miotaczem w 2010?). Po drugim kliknięciu przycisku NextButton, wartość zmiennej currentQuestionIndex zostanie zmieniona z 2 na 3, a aplikacja wybierze trzecie pytanie z listy (Kto był pierwszym doskonałym miotaczem nowej ery?).''<br />
<br />
<br />
===Przetestuj to zachowanie===<br />
Przetestuj zachowanie przycisku NextButton, aby sprawdzić, czy aplikacja działa poprawnie. Wciel się w rolę użytkownika i kliknij przycisk NextButton w telefonie. Czy urządzenie wyświetliło drugie pytanie: Kto był pierwszym doskonałym miotaczem w 2010?? Trzecie pytanie powinno pojawić się po kolejnym kliknięciu przycisku. Jeżeli aplikacja działa, pogratuluj sobie i przejdź dalej. Kliknij przycisk NextButton ponownie (po raz trzeci). Powinien zostać wyświetlony błąd: Próba uzyskania elementu 4 z listy o długości 3. Czy wiesz, na czym polega problem?<br />
<br />
Problem z aplikacją polega na tym, że zawsze po kliknięciu przycisku NextButton zwiększa ona zmienną CurrentQuestionIndex o 1. Gdy wartość zmiennej wynosi już 3, a użytkownik kolejny raz kliknie przycisk NextButton, aplikacja zmieni wartość zmiennej z 3 na 4, następnie wywoła blok Select list item, aby odczytać pozycję o aktualnym indeksie CurrentQuestionIndex, czyli w tym przypadku czwartą pozycję. Ponieważ zmienna QuestionList zawiera tylko trzy elementy, Android wykaże błąd.<br />
<br />
Aplikacja musi zadawać pytanie - sprawdzać warunek - gdy nastąpi kliknięcie przycisku NextButton i realizować polecenia zawarte w różnych blokach w zależności od odpowiedzi. Elementem do sprawdzenia jest to, czy zmienna CurrentQuestionIndex już ma wartość 3. Jeżeli tak - należy ustawić CurrentQuestionIndex z powrotem na 0, aby użytkownik wrócił do pierwszego pytania.<br />
<br />
Będziesz potrzebował następujących bloków:<br />
{| class="wikitable"<br />
!Typ bloku<br />
!Kategoria<br />
!Działanie<br />
|-<br />
|if then<br />
|Control<br />
|sprawdzenie, czy użytkownik jest na etapie ostatniego pytania<br />
|-<br />
|= <br />
|Math<br />
|sprawdzenie, czy currentQuestionIndex ma wartość 3<br />
|-<br />
|get global currentQuestionIndex<br />
|Variables<br />
|<br />
|-<br />
|0 (3)<br />
|Math<br />
|3 to numer na liście<br />
|-<br />
|set currentQuestionIndex to<br />
|Variables<br />
|ustawienie na 0, aby wrócić do pierwszego pytania<br />
|-<br />
|0<br />
|Math<br />
|ustawienie na 0, ponieważ kolejne bloki zwiększą wartość do 1<br />
|}<br />
Zmodyfikowany blok obsługi zdarzenia When NextButton.Click powinien wyglądać następująco:<br />
<br />
[[Plik:t6-9.png]]<br />
<br />
===Jak działają bloki===<br />
Po kliknięciu przycisku NextButton aplikacja najpierw sprawdza, czy currentQuestionIndex ma wartość 3. Jeżeli tak, wartość tej zmiennej jest ustawiana na 0, aby po zwiększeniu jej w dalszych krokach jej wartość wyniosła 1. Wtedy quiz wróci do pierwszego pytania. Zauważ, że tylko bloki osadzone w bloku if-then są zależne od warunku. Blok zwiększenia wartości i blok Set QuestionLabel.Text to są wykonywane bez względu na jakikolwiek warunek.<br />
<br />
==Aplikacja modyfikowalna: Ułatwianie modyfikowania pytań==<br />
Teraz zmodyfikujemy aplikację, aby można było łatwo dodawać i usuwać elementy z listy. Zmień bloki tak, aby działały na liście o dowolnej długości, a nie tylko liście z dokładnie trzema pozycjami. <br />
Na początek dodaj czwarte pytanie do zmiennej QuestionList i kolejną odpowiedź do AnswerList. W tym celu musisz najpierw zwiększyć liczbę dostępnych pól za pomocą przycisku modyfikującego (mutatora). Aby dowiedzieć się więcej o tym elemencie, zobacz: http://appinventor.mit.edu/explore/ai2/support/concepts/mutators. Bloki powinny wyglądać następująco:<br />
<br />
[[Plik:t6-10.png]]<br />
<br />
===Przetestuj zmodyfikowaną aplikację.===<br />
Kliknij przycisk NextButton kilka razy. Zauważysz, że czwarte pytanie nigdy się nie pojawia, bez względu na to, ile razy klikniesz przycisk.<br />
<br />
Problemem jest to, że test sprawdzający, czy użytkownik znajduje się przy ostatnim pytaniu, jest zbyt szczegółowy: pyta, czy zmienna CurrentQuestionIndex ma wartość 3:<br />
<br />
[[Plik:t6-11.png]]<br />
<br />
Możesz po prostu zmienić liczbę z 3 na 4, a aplikacja będzie znów działać poprawnie. Problem polega jednak na tym, że za każdym razem, gdy zmodyfikujesz liczbę pytań i odpowiedzi, będziesz musiał pamiętać, aby dokonać także tej zmiany. Takie zależności w programie komputerowym często prowadzą do błędów, w szczególności gdy aplikacja staje się bardziej złożona. Znacznie lepiej jest przygotować program w taki sposób, aby działał niezależnie od liczby pytań. Takie uogólnienie jest jeszcze ważniejsze, gdy lista, z którą pracujesz, zmienia się dynamicznie, na przykład w aplikacji z quizem, gdzie użytkownik może dodawać nowe pytania.<br />
<br />
Lepszym rozwiązaniem jest sprawdzenie warunku w sposób bardziej ogólny. Tak naprawdę chcesz wiedzieć, czy bieżące pytanie – czyli wartość zmiennej currentQuestionIndex jest tak duża, jak ilość elementów w zmiennej QuestionList. Jeżeli aplikacja sprawdzi warunek w bardziej ogólny sposób, to będzie działać, nawet jeżeli dodasz lub usuniesz elementy ze zmiennej QuestionList. Aby zmienić blok obsługi zdarzenia When NextButton.Click, zmień poprzedni test sprawdzający, który odnosił się bezpośrednio do 3. Będziesz potrzebował następujących bloków:<br />
{| class="wikitable"<br />
!Typ bloku<br />
!Szuflada<br />
!Działanie<br />
|-<br />
|length of list<br />
|Lists<br />
|Pyta, ile elementów jest w zmiennej QuestionList<br />
|-<br />
|get global QuestionList<br />
|Variables<br />
|Określa, o którą listę chodzi<br />
|}<br />
Blok obsługi zdarzenia When NextButton.Click powinien teraz wyglądać następująco:<br />
<br />
[[Plik:t6-12.png]]<br />
<br />
<br />
<br />
===Jak działają bloki?===<br />
Warunek if porównuje teraz wartość zmiennej CurrentQuestionIndex z długością zmiennej QuestionList. Zatem jeżeli zmienna CurrentQuestionIndex ma wartość 4, a długość zmiennej QuestionList wynosi 4, to wartość zmiennej currentQuestionIndex zostanie ustawiona na 0 (a następnie na 1, 2 itd.). Zauważ - bloki nie odwołują się już do 3 ani żadnej innej określonej wartości, dlatego instrukcja będzie działać bez względu na liczbę elementów listy.<br />
<br />
Przetestuj zmodyfikowane zachowanie. Czy po kliknięciu przycisku NextButton aplikacja przechodzi teraz przez cztery pytania, wracając po ostatnim do pierwszego?<br />
<br />
==Przełączanie zdjęcia dla każdego pytania==<br />
Na razie aplikacja wyświetla to samo zdjęcie, bez względu na to, jakie pytanie zostaje zadane. Możesz to zmienić tak, aby po kliknięciu przycisku NextButton pojawiała się fotografia dotycząca danego pytania. W obszarze Media dostępne są cztery dodane wcześniej zdjęcia. Teraz utworzymy trzecią listę - PictureList, której elementami będą nazwy plików zdjęć, a następnie zmodyfikujemy blok obsługi zdarzenia When NextButton.Click, aby program po każdym pytaniu przełączał zdjęcie.<br />
Najpierw utwórz listę PictureList i zainicjuj ją nazwami plików graficznych. Upewnij się, czy nazwy są dokładnie takie same jak nazwy plików, które zostały załadowane do obszaru Media. Oto jak powinien wyglądać blok dla listy PictureList:<br />
<br />
Następnie zmodyfikuj blok obsługi zdarzeń When NextButton.Click, aby zmieniał wyświetlane zdjęcie w zależności od zadanego pytania. Jeżeli ustawisz właściwość Image.Picture na nazwę pliku zdjęcia, które zostało załadowane, właśnie ta fotografia zostanie wyświetlona. Aby zmodyfikować blok When NextButton.Click, potrzebujesz następujących bloków:<br />
{| class="wikitable"<br />
!Typ bloku<br />
!Kategoria<br />
!Działanie<br />
|-<br />
|set Image1.Picture to<br />
|Image1<br />
|ustaw, aby zmieniać zdjęcie<br />
|-<br />
|select list item<br />
|Lists<br />
|należy wybrać zdjęcie odpowiadające na aktualne pytanie<br />
|-<br />
|get global PictureList<br />
|Variables<br />
|wybierz nazwę pliku z tej listy<br />
|-<br />
|get global currentQuestionIndex<br />
|Variables<br />
|wybierz element o n-tym indeksie currentQuestionIndex<br />
|}<br />
Oto jak powinny wyglądać bloki:<br />
<br />
===Jak działają bloki?===<br />
Zmienna CurrentQuestionIndex służy jako indeks dla zmiennej QuestionList. Wartość CurrentQuestionIndex wynosi 1, aplikacja wybiera pierwsze pytanie i pierwsze zdjęcie. Gdy CurrentQuestionIndex wynosi 2, aplikacja wybiera drugie pytanie i drugie zdjęcie. Oczywiście takie działanie zależy od tego, czy listy są ze sobą zsynchronizowane. Tak jest w tym przypadku - pierwszy obraz - LarsenBerra.jpg to zdjęcie Dona Larsena, jednocześnie Don Larsen to odpowiedź na pierwsze pytanie (Kto był doskonałym miotaczem w World Series?). <br />
Przetestuj zmodyfikowane zachowanie. Czy nowe zdjęcie pojawia się po każdym kliknięciu przycisku NextButton?<br />
<br />
==Ocena udzielanych odpowiedzi==<br />
Teraz dodamy bloki, które określają, czy użytkownik odpowiedział na pytanie prawidłowo, czy też nie. Gracz wprowadza odpowiedź do AnswerText, a następnie klika przycisk AnswerButton. Aplikacja musi porównać wpis użytkownika z odpowiedzią na bieżące pytanie, używając bloku if... then... w celu jej sprawdzenia. Etykieta RightWrongLabel powinna być modyfikowana, aby podawać, czy odpowiedź jest prawidłowa, czy nie.<br />
<br />
Do tego zachowania będą potrzebne następujące bloki:<br />
{| class="wikitable"<br />
!Typ bloku<br />
!Kategoria<br />
!Działanie<br />
|-<br />
|when AnswerButton.Click<br />
|AnswerButton<br />
|zachowanie jest wyzwalane, gdy użytkownik kliknie przycisk AnswerButton<br />
|-<br />
|if... then...<br />
|Control<br />
|Użyj mutatora, aby dodać alternatywę (else). Jeżeli odpowiedź jest prawidłowa - zrób jedno, w przeciwnym razie (else) - zrób coś innego<br />
|-<br />
|= <br />
|Math<br />
|sprawdzenie, czy odpowiedź jest prawidłowa<br />
|-<br />
|AnswerText.Text<br />
|AnswerText<br />
|Odpowiedź użytkownika pojawia się w tym polu tekstowym<br />
|-<br />
|select list item<br />
|Lists<br />
|wybrać bieżącą odpowiedź z listy AnswerList<br />
|-<br />
|get global AnswerList<br />
|Variables<br />
|lista, z której jest wybierany element<br />
|-<br />
|get global currentQuestionIndex<br />
|Variables<br />
|numer pytania (i numer odpowiedzi), przy którym jest użytkownik<br />
|-<br />
|set RightWrongLabel.Text to<br />
|RightWrongLabel<br />
|tutaj podaj odpowiedź<br />
|-<br />
|Dobrze!<br />
|Text<br />
|jeżeli odpowiedź jest prawidłowa<br />
|-<br />
|set RightWrongLabel.Text to<br />
|RightWrongLabel<br />
|tutaj podaj odpowiedź<br />
|-<br />
|Źle<br />
|Text<br />
|jeżeli odpowiedź jest nieprawidłowa<br />
|}<br />
Bloki powinny wyglądać następująco:<br />
<br />
===Jak działają bloki?===<br />
Test if sprawdza, czy odpowiedź użytkownika (AnswerText.Text) jest taka sama, jak element na liście AnswerList o indeksie równym wartości zmiennej CurrentQuestionIndex. Jeżeli zmienna CurrentQuestionIndex ma wartość 1, aplikacja porównuje odpowiedź użytkownika z pierwszą pozycją na liście AnswerList, (Don Larsen). Jeżeli zmienna CurrentQuestionIndex zmieni wartość na 2, program zestawia odpowiedź z drugą pozycją na liście, czyli Dallas Branden. Jeśli wynik porównania jest pozytywny, przeprowadzane są bloki then, a treść etykiety RightWrongLabel zostaje ustawiona na Dobrze!. Jeżeli wynik testu jest negatywny (fałszywy), przeprowadzane są bloki alternatywy (else), a treść etykiety RightWrongLabel zostaje ustawiona na Źle.<br />
<br />
Przetestuj zmodyfikowaną aplikację. Spróbuj odpowiedzieć na jedno z pytań. Powinna pojawić się ocena, czy odpowiedź była dokładnie taka sama, jak na liście AnswerList. Sprawdź zarówno prawidłowe, jak i nieprawidłowe odpowiedzi (Uwaga - uwzględniana jest wielkość liter!). Kliknij przycisk NextButton i odpowiedz na drugie pytanie. Czy aplikacja nadal działa? Powinna, ale zauważ, że gdy klikniesz przycisk NextButton, tekst Dobrze! lub Źle oraz poprzednia odpowiedź nadal będą wyświetlane. Choć nie wpływa to zasadniczo na naszą grę, to takie szczegóły interfejsu z pewnością zostaną zauważone przez użytkowników Twojej aplikacji.<br />
<br />
Aby wyzerować etykietę RightWrongLabel i AnswerText, umieść poniższe bloki w bloku obsługi zdarzeń When NextButton.click:<br />
{| class="wikitable"<br />
!Typ bloku<br />
!Kategoria<br />
!Działanie<br />
|-<br />
|set RightWrongLabel.Text to<br />
|RightWrongLabel<br />
|Ustawia wartość etykiety na…<br />
|-<br />
|„ „<br />
|Text<br />
|pusty tekst<br />
|-<br />
|set AnswerText.Text to<br />
|AnswerText<br />
|Ustawia wartość etykiety na…<br />
|-<br />
|„ „<br />
|Text<br />
|pusty tekst<br />
|}<br />
Bloki powinny wyglądać następująco:<br />
<br />
===Jak działają bloki?===<br />
Po kliknięciu przycisku NextButton użytkownik przechodzi do następnego pytania, dlatego początkowe wiersze bloku obsługi zdarzeń zerują etykietę RightWrongLabel i pole AnswerText.<br />
Przetestuj to zachowanie Odpowiedz na pytanie i kliknij przycisk Wyślij, a następnie - NextButton. Czy Twoja poprzednia odpowiedź i jej ocena zniknęły?<br />
<br />
==Ostateczna postać programu==<br />
Oto gotowa aplikacja QuizMe:<br />
<br />
Utwórz wykonywalną wersję aplikacji, wybierając menu Build/App (provide QR code for .apk). Gdy pojawi się kod kreskowy, użyj czytnika kodów w telefonie, aby pobrać i zainstalować aplikację.<br />
<br />
===Modyfikacje===<br />
Quiz w tej wersji jest już gotowy. Czy masz ochotę przemyśleć pewne zmiany?<br />
<br />
Zamiast wyświetlać zdjęcie dla każdego pytania, spróbuj odtworzyć dźwięk lub krótkie wideo. Za pomocą dźwięku możesz zmienić quiz w aplikację Jaka to melodia?.<br />
<br />
Quiz akceptuje ściśle określone odpowiedzi. Jeśli gracz odpowiedziałby, lekko przekształcając tekst (np. podając inicjał zamiast imienia), program uzna to za błąd. Można to zmienić na kilka różnych sposobów. Jednym z nich jest użycie bloku text.contains, aby sprawdzić, czy odpowiedź użytkownika zawiera prawidłową odpowiedź. Inny sposób to dostarczenie wielu odpowiedzi na każde pytanie i sprawdzenie przez iterację (użycie bloku for each), czy któraś z nich pasuje.<br />
<br />
Przekształć quiz tak, aby przedstawiał odpowiedzi do wyboru. Lista odpowiedzi będzie musiała być listą list, a każda podrzędna lista będzie musiała zawierać opcje odpowiedzi. Użyj komponentu ListPicker, aby umożliwić użytkownikowi wybranie odpowiedzi.<br />
<br />
<br />
==Podsumowanie==<br />
Oto niektóre koncepcje omówione w tym przewodniku:<br />
<ul><li>Aplikacje można tworzyć w sposób ogólny, aby pracować z dowolną listą danych.</li><br />
<li>Zmienne indeksu są wykorzystywane do śledzenia bieżącej pozycji na liście. Zwiększając wartość zmiennej indeksu, należy uważać na przekroczenie końca listy.</li></ul><br />
<br />
==Zeskanuj próbną aplikację do telefonu==<br />
Aby zainstalować i uruchomić aplikację próbną, zeskanuj poniższy kod kreskowy:<br />
<br />
==Pobierz kod źródłowy==<br />
Jeżeli chcesz pracować z tą próbką w programie App Inventor:<br />
<ul><li>pobierz na komputer kod źródłowy: [http://appinventor.mit.edu/explore/sites/all/files/ai2tutorials/QuizMe/QuizMe_MIT.aia http://appinventor.mit.edu/explore/sites/all/files/ai2tutorials/QuizMe/QuizMe_MIT.aia]</li><br />
<li>otwórz program App Inventor,</li><br />
<li>kliknij opcję My Projects,</li><br />
<li>wybierz Import project (.aia) from my computer...</li><br />
<li>znajdź i zatwierdź pobrany kod źródłowy.</li></ul></div>M Kelniarzhttp://wiki.mistrzowiekodowania.pl/index.php?title=QuizMeQuizMe2015-03-15T18:35:30Z<p>M Kelniarz: /* Aplikacja modyfikowalna: Ułatwianie modyfikowania pytań */</p>
<hr />
<div>=Aplikacja QuizMe dla App Inventor 2=<br />
<br />
==Co tworzysz?==<br />
[[Plik:t6-1.png|right]]QuizMe to gra dotycząca ciekawostek baseballowych, ale można jej użyć jako szablonu do tworzenia quizów z dowolnej dziedziny. W aplikacji użytkownik odpowiada na szereg pytań, otrzymując następnie informację zwrotną, czy udzielił poprawnej, czy błędnej odpowiedzi. Gracz przechodzi do kolejnego pytania, klikając przycisk.<br />
<br />
W grze QuizMe dysponujemy zamkniętym zbiorem pytań, chyba że programista je zmieni. W następnym etapie można utworzyć MakeQuiz & TakeQuiz – aplikację, która pozwala użytkownikom na tworzenie i modyfikowanie pytań.<br />
<br />
Poradnik ten zakłada, że znasz już podstawy tworzenia aplikacji w App Inventorze – korzystanie z Projektanta komponentów w celu utworzenia interfejsu użytkownika i z Edytora bloków, aby określić obsługę zdarzeń. Jeżeli potrzebujesz przypomnienia, spróbuj popracować z poradnikami podstawowymi zanim przejdziesz dalej.<br />
<br />
==Zaczynamy!==<br />
Połącz się z witryną internetową App Inventor i załóż nowy projekt. Nazwij go QuizMe, ustaw taki sam tytuł ekranu (Title). Za pomocą MIT AI2 Companion połącz program z urządzeniem mobilnym. Pobierz poniższe zdjęcia baseballistów i zapisz je w komputerze. Później załadujesz je do projektu.<br />
<ul><li> [http://beta.appinventor.mit.edu/learn/tutorials/quizme/QuizMeAssets/Larsenberra.jpg Larsenberra.jpg]</li><br />
<li> [http://beta.appinventor.mit.edu/learn/tutorials/quizme/QuizMeAssets/dallasbraden.jpg Dallasbraden.jpg]</li><br />
<li> [http://beta.appinventor.mit.edu/learn/tutorials/quizme/QuizMeAssets/cyyoung.jpg Cyyoung.jpg]</li><br />
<li> [http://beta.appinventor.mit.edu/learn/tutorials/quizme/QuizMeAssets/nolanryan.jpg Nolanryan.jpg]</li></ul><br />
<br />
==Wstęp==<br />
Zaprojektujesz grę typu quiz, w której użytkownik będzie przechodził do kolejnych pytań, klikając przycisk Dalej, a następnie otrzymywał prostą ocenę Dobrze/Źle dla każdej odpowiedzi.<br />
<br />
W tym przewodniku omówimy:<br />
<ul><li>definiowanie i wyświetlanie listy informacji;</li><br />
<li>przechodzenie przez listę za pomocą zmiennej indeksującej – zmiennej, która śledzi pozycję na liście;</li><br />
<li>zachowania warunkowe – wykonywanie określonych operacji tylko wtedy, gdy spełniony jest określony warunek;</li><br />
<li>Zmianę zdjęcia w zależności od sytuacji.</li></ul><br />
<br />
==Projektowanie aplikacji==<br />
Użyj Projektanta komponentów do utworzenia interfejsu dla aplikacji QuizMe. <br />
Aby utworzyć interfejs, najpierw załaduj do projektu pobrane zdjęcia. Kliknij przycisk Prześlij plik (Upload File...) w obszarze Media i wybierz jeden z pobranych wcześniej plików (np. Larsenberra.jpg). Następnie zrób to samo z pozostałymi trzema zdjęciami.<br />
Utwórz następujące komponenty, przeciągając je z Palety (Palette) do Przeglądarki (Viewer) i ustaw właściwości komponentów zgodnie z poniższym opisem:<br />
{|class="wikitable"<br />
! Typ komponentu<br />
! Kategoria<br />
! Jaką nadać jej nazwę<br />
! Działanie<br />
! Działanie komponentu<br />
|-<br />
|Image<br />
|User interface<br />
|Image1<br />
|Ustaw właściwość zdjęcia (Picture) na Larsenberra.jpg. Jest to pierwsze wyświetlane zdjęcie.<br />
|Obrazkowa część pytania<br />
|-<br />
|Label<br />
|User interface<br />
|QuestionLabel<br />
|Zmień właściwość tekstu (Text) na Pytanie:<br />
|Wyświetla bieżące pytanie<br />
|-<br />
|HorizontalArrangement<br />
|Layout<br />
|HorizontalArrangement1<br />
| <br />
|Organizuje komponenty AnswerPrompt i Text (podaj odpowiedź i tekst)<br />
|-<br />
|Label<br />
|User interface<br />
|AnswerPromptLabel<br />
|Zmień właściwość tekstu (Text) na Podaj odpowiedź:. Na ekranie przeglądarki przesuń tę etykietę do HorizontalArrangement1.<br />
|Wyświetla tekst prośby o odpowiedź.<br />
|-<br />
|TextBox<br />
|User interface<br />
|AnswerText<br />
|Zmień wskazówkę (Hint) na Podaj odpowiedź. Na ekranie przeglądarki przenieś AnswerText do komponentu HorizontalArrangement1.<br />
|Tutaj użytkownik podaje odpowiedź.<br />
|-<br />
|Label<br />
|User interface <br />
|RightWrongLabel<br />
|Zmień właściwość tekstu (Text) na Dobrze/Źle.<br />
|Tutaj wyświetlana jest ocena Dobrze/Źle.<br />
|-<br />
|HorizontalArrangement<br />
|Layout<br />
|HorizontalArrangement2<br />
|<br />
|Organizuje przyciski AnswerButton i NextButton (przycisk odpowiedzi i przycisk dalej).<br />
|-<br />
|Przycisk<br />
|User interface<br />
|AnswerButton<br />
|Zmień właściwość tekstu (Text) na Wyślij. Na ekranie przeglądarki przesuń ten przycisk do HorizontalArrangment2.<br />
|Użytkownik klika, aby przesłać odpowiedź.<br />
|-<br />
|Przycisk<br />
|User interface<br />
|NextButton<br />
|Zmień właściwość tekstu (Text) na Dalej. Przenieś ten przycisk do HorizontalArrangement2.<br />
|Użytkownik klika, aby przejść do następnego pytania.<br />
|} <br />
Po zakończeniu powinien on wyglądać jak poniższa ilustracja (pod nią znajdują się również bardziej szczegółowe informacje).<br />
[[Plik:t6-2.png]]<br />
<br />
==Programowanie aplikacji==<br />
Otwórz Edytor bloków, aby zaprogramować działanie komponentów. Najpierw zdefiniuj dwie zmienne - listy: zmienną QuestionList, zawierającą listę pytań i zmienną AnswerList z listą odpowiedzi na te pytania.<br />
<br />
Aby zdefiniować te dwie zmienne listy, potrzebujesz następujących bloków:<br />
{| class="wikitable"<br />
!Typ bloku<br />
!Kategoria<br />
!Działanie<br />
|-<br />
|initialize global name to<br />
|Variables<br />
|Definiuje zmienną QuestionList (zmień jej nazwę)<br />
|-<br />
|initialize global name to<br />
|Variables<br />
|Definiuje zmienną AnswerList (zmień jej nazwę)<br />
|-<br />
|make a list<br />
|Lists<br />
|Służy do dodawania elementów do zmiennej QuestionList<br />
|-<br />
|„ „ (trzykrotnie)<br />
|Lists<br />
|Służy do wpisania pytań<br />
|-<br />
|make a list<br />
|Lists<br />
|Służy do dodawania elementów do zmiennej AnswerList<br />
|-<br />
|„ „ (trzykrotnie)<br />
|Text<br />
|Służy do wpisania odpowiedzi<br />
|}<br />
Utwórz zmienne całościowe, przeciągając z kategorii zmiennych (Variables) na obszar roboczy blok Initialize global name to. Kliknij dwukrotnie domyślną nazwę name, aby ją zmienić. Blok Initialize global name to zawiera pole na początkową wartość zmiennej. Zmienna może zawierać liczbę, tekst, a nawet listę – aby ją utworzyć, podłącz blok Make a list do definicji zmiennej.<br />
<br />
Bloki powinny wyglądać następująco:<br />
<br />
[[Plik:t6-3.png]]<br />
===Zdefiniuj ukrytą zmienną Index===<br />
Za każdym razem, gdy użytkownik kliknie przycisk NextButton, aby przejść dalej, aplikacja musi pamiętać, przy którym pytaniu jest obecnie gracz. W języku programowania, aby coś zapamiętać, trzeba zdefiniować nową zmienną. W tym przypadku aplikacja musi zapamiętać bieżący numer pytania – indeks listy QuestionList.<br />
Aby zdefiniować zmienną currentQuestionIndex, potrzebujesz następujących bloków:<br />
{| class="wikitable"<br />
!Typ bloku<br />
!Kategoria<br />
!Działanie<br />
|-<br />
|initialize global name to<br />
|Variables<br />
|Definiuje zmienną currentQuestionIndex (zmień nazwę)<br />
|-<br />
|0 (1)<br />
|Math<br />
|Ustaw wartość początkową currentQuestionIndex na 1 (zmień liczbę)<br />
|}<br />
Bloki powinny wyglądać następująco:<br />
<br />
[[Plik:t6-4.png]]<br />
<br />
===Wyświetl pierwsze pytanie===<br />
Odłóż na razie kwestię odpowiedzi i skup się na zaprogramowaniu sekwencyjnego przejścia przez pytania. Pożądane zachowanie jest następujące: po uruchomieniu aplikacji na etykiecie o nazwie QuestionLabel pojawia się pierwsze pytanie. Gdy użytkownik kliknie NextButton, wyświetlone zostaje drugie pytanie. Po ponownym kliknięciu pojawia się trzecie pytanie. Po dotarciu do ostatniego pytania kliknięcie przycisku NextButton powoduje ponowne pojawienie się pierwszego pytania w etykiecie QuestionLabel.<br />
<br />
W programie App Inventor określone pozycje na liście są wybierane za pomocą bloku select list item. W tym bloku trzeba podać listę i indeks – pozycję na liście. Jeżeli na liście są trzy pozycje, prawidłowe indeksy to 1, 2 i 3.<br />
<br />
Po uruchomieniu aplikacja QuizMe powinna wybrać pierwsze pytanie z listy i wyświetlić je w komponencie QuestionLabel. Do tego zachowania inicjalizującego działanie aplikacji potrzebne są następujące bloki:<br />
<br />
{| class="wikitable"<br />
!Typ bloku<br />
!Kategoria<br />
!Działanie<br />
|-<br />
|when Screen1.Initialize<br />
|Screen1<br />
|Podczas uruchamiania aplikacji zainicjowana jest ta obsługa zdarzenia<br />
|-<br />
|set QuestionLabel.Text to<br />
|QuestionLabel<br />
|Umieszcza pierwsze pytanie w etykiecie QuestionLabel<br />
|-<br />
|select list item<br />
|Lists<br />
|Wybiera pierwsze pytanie z etykiety QuestionLabel<br />
|-<br />
|get <br />
|Variables<br />
|Ustala listę, z której jest wybierany element. Tutaj: Global QuestionList<br />
|-<br />
|0 (1)<br />
|Math<br />
|Wybiera pierwsze pytanie za pomocą indeksu 1. Ustaw wartość na 1.<br />
|}<br />
Bloki powinny wyglądać następująco:<br />
<br />
[[Plik:t6-5.png]]<br />
<br />
===Jak działają bloki?===<br />
Zdarzenie when Screen1.Initialize jest wyzwalane podczas uruchomienia aplikacji. Pierwsza pozycja zmiennej QuestionList zostaje wybrana i umieszczona w bloku set QuestionLabel.Text. Gdy aplikacja zostanie uruchomiona, użytkownik zobaczy pierwsze pytanie.<br />
===Przetestuj to zachowanie===<br />
Jeśli dotychczas nie skomunikowałeś urządzenia mobilnego z programem, zrób to teraz. Co pojawia się na urządzeniu? Jeżeli utworzono listę QuestionList tak, jak wskazano powyżej, w etykiecie QuestionLabel powinna pojawić się pierwsza pozycja tej listy (Kto był doskonałym miotaczem w World Series?).<br />
<br />
==Iteracja pytań==<br />
Zdefiniowałeś już zmienną CurrentQuestionIndex, zapamiętującą pytanie, przy którym znajduje się użytkownik. Zaprogramuj teraz zachowanie przycisku NextButton. Gdy zostanie on kliknięty, aplikacja zwiększy wartość zmiennej, np. zmieni ją z 1 na 2 lub z 2 na 3 itd., a następnie użyje tej wartości do zaznaczenia nowego bieżącego pytania. Do tego zachowania potrzebne są następujące bloki:<br />
{| class="wikitable"<br />
!Typ bloku<br />
!Kategoria<br />
!Działanie<br />
|-<br />
|when NextButton.Click<br />
|NextButton<br />
|Uruchamia obsługę zdarzeń po kliknięciu przycisku<br />
|-<br />
|set currentQuestionIndex to<br />
|Zmienne<br />
|Decyduje o ustawieniu indeksu wybranej listy<br />
|-<br />
|+ <br />
|Math<br />
|Służy do zwiększania wartości zmiennej currentQuestionIndex<br />
|-<br />
|get global currentQuestionIndex<br />
|Zmienne<br />
|Tworzy nową wartość poprzez zwiększenie poprzedniej wartości o 1<br />
|-<br />
|0 (1)<br />
|Math<br />
|Dla + 1<br />
|-<br />
|set QuestionLabel.Text to<br />
|QuestionLabel<br />
|Wyświetla kolejne pytanie<br />
|-<br />
|select list item<br />
|Listy<br />
|Ustawia element listy jako wartość QuestionLabel<br />
|-<br />
|get global QuestionList<br />
|Zmienne<br />
|Wskazuje, która lista będzie wybrana<br />
|-<br />
|get global currentQuestionIndex<br />
|Zmienne<br />
|Wskazuje, który element wybranej listy będzie wybrany<br />
|}<br />
Bloki powinny wyglądać następująco:<br />
<br />
[[Plik:t6-6.png]]<br />
<br />
===Jak działają bloki?===<br />
Pierwszy wiersz polecenia zwiększa wartość zmiennej currentQuestionIndex o 1 (jeżeli zmienna zawiera wartość 1, zostaje ona zmieniona na 2, z 2 na 3 itd.). Następnie wykorzystuje nową wartość do wyboru pytania o tym indeksie.<br />
<br />
Przypomnijmy, że w bloku obsługi zdarzeń Screen.Initialize aplikacja wybrała pierwsze do wyświetlenia pytanie:<br />
<br />
[[Plik:t6-7.png]]<br />
<br />
Po kliknięciu przycisku NextButton aplikacja nie wybiera konkretnie pierwszej, drugiej czy trzeciej pozycji na liście, tylko pozycję o n-tej wartości zmiennej currentQuestionIndex.<br />
<br />
[[Plik:t6-8.png]]<br />
<br />
Polecenia w blokach są wykonywane od prawej do lewej, tzn. aplikacja najpierw określa wartość parametru z bloku Select list item, którym jest zmienna CurrentQuestionIndex. Liczba zawarta w tej zmiennej zostaje użyta jako indeks podczas wykonania poleceń zawartych w bloku Select list item.<br />
<br />
[[Plik:info.png|left]]''Po pierwszym kliknięciu przycisku NextButton, wartość zmiennej currentQuestionIndex przeskoczy z 1 na 2, aby aplikacja wybrała drugą pozycję z listy QuestionList (Kto był pierwszym doskonałym miotaczem w 2010?). Po drugim kliknięciu przycisku NextButton, wartość zmiennej currentQuestionIndex zostanie zmieniona z 2 na 3, a aplikacja wybierze trzecie pytanie z listy (Kto był pierwszym doskonałym miotaczem nowej ery?).''<br />
<br />
<br />
===Przetestuj to zachowanie===<br />
Przetestuj zachowanie przycisku NextButton, aby sprawdzić, czy aplikacja działa poprawnie. Wciel się w rolę użytkownika i kliknij przycisk NextButton w telefonie. Czy urządzenie wyświetliło drugie pytanie: Kto był pierwszym doskonałym miotaczem w 2010?? Trzecie pytanie powinno pojawić się po kolejnym kliknięciu przycisku. Jeżeli aplikacja działa, pogratuluj sobie i przejdź dalej. Kliknij przycisk NextButton ponownie (po raz trzeci). Powinien zostać wyświetlony błąd: Próba uzyskania elementu 4 z listy o długości 3. Czy wiesz, na czym polega problem?<br />
<br />
Problem z aplikacją polega na tym, że zawsze po kliknięciu przycisku NextButton zwiększa ona zmienną CurrentQuestionIndex o 1. Gdy wartość zmiennej wynosi już 3, a użytkownik kolejny raz kliknie przycisk NextButton, aplikacja zmieni wartość zmiennej z 3 na 4, następnie wywoła blok Select list item, aby odczytać pozycję o aktualnym indeksie CurrentQuestionIndex, czyli w tym przypadku czwartą pozycję. Ponieważ zmienna QuestionList zawiera tylko trzy elementy, Android wykaże błąd.<br />
<br />
Aplikacja musi zadawać pytanie - sprawdzać warunek - gdy nastąpi kliknięcie przycisku NextButton i realizować polecenia zawarte w różnych blokach w zależności od odpowiedzi. Elementem do sprawdzenia jest to, czy zmienna CurrentQuestionIndex już ma wartość 3. Jeżeli tak - należy ustawić CurrentQuestionIndex z powrotem na 0, aby użytkownik wrócił do pierwszego pytania.<br />
<br />
Będziesz potrzebował następujących bloków:<br />
{| class="wikitable"<br />
!Typ bloku<br />
!Kategoria<br />
!Działanie<br />
|-<br />
|if then<br />
|Control<br />
|sprawdzenie, czy użytkownik jest na etapie ostatniego pytania<br />
|-<br />
|= <br />
|Math<br />
|sprawdzenie, czy currentQuestionIndex ma wartość 3<br />
|-<br />
|get global currentQuestionIndex<br />
|Variables<br />
|<br />
|-<br />
|0 (3)<br />
|Math<br />
|3 to numer na liście<br />
|-<br />
|set currentQuestionIndex to<br />
|Variables<br />
|ustawienie na 0, aby wrócić do pierwszego pytania<br />
|-<br />
|0<br />
|Math<br />
|ustawienie na 0, ponieważ kolejne bloki zwiększą wartość do 1<br />
|}<br />
Zmodyfikowany blok obsługi zdarzenia When NextButton.Click powinien wyglądać następująco:<br />
<br />
[[Plik:t6-9.png]]<br />
<br />
===Jak działają bloki===<br />
Po kliknięciu przycisku NextButton aplikacja najpierw sprawdza, czy currentQuestionIndex ma wartość 3. Jeżeli tak, wartość tej zmiennej jest ustawiana na 0, aby po zwiększeniu jej w dalszych krokach jej wartość wyniosła 1. Wtedy quiz wróci do pierwszego pytania. Zauważ, że tylko bloki osadzone w bloku if-then są zależne od warunku. Blok zwiększenia wartości i blok Set QuestionLabel.Text to są wykonywane bez względu na jakikolwiek warunek.<br />
<br />
==Aplikacja modyfikowalna: Ułatwianie modyfikowania pytań==<br />
Teraz zmodyfikujemy aplikację, aby można było łatwo dodawać i usuwać elementy z listy. Zmień bloki tak, aby działały na liście o dowolnej długości, a nie tylko liście z dokładnie trzema pozycjami. <br />
Na początek dodaj czwarte pytanie do zmiennej QuestionList i kolejną odpowiedź do AnswerList. W tym celu musisz najpierw zwiększyć liczbę dostępnych pól za pomocą przycisku modyfikującego (mutatora). Aby dowiedzieć się więcej o tym elemencie, zobacz: http://appinventor.mit.edu/explore/ai2/support/concepts/mutators. Bloki powinny wyglądać następująco:<br />
<br />
[[Plik:t6-10.png]]<br />
<br />
===Przetestuj zmodyfikowaną aplikację.===<br />
Kliknij przycisk NextButton kilka razy. Zauważysz, że czwarte pytanie nigdy się nie pojawia, bez względu na to, ile razy klikniesz przycisk.<br />
<br />
Problemem jest to, że test sprawdzający, czy użytkownik znajduje się przy ostatnim pytaniu, jest zbyt szczegółowy: pyta, czy zmienna CurrentQuestionIndex ma wartość 3:<br />
<br />
Możesz po prostu zmienić liczbę z 3 na 4, a aplikacja będzie znów działać poprawnie. Problem polega jednak na tym, że za każdym razem, gdy zmodyfikujesz liczbę pytań i odpowiedzi, będziesz musiał pamiętać, aby dokonać także tej zmiany. Takie zależności w programie komputerowym często prowadzą do błędów, w szczególności gdy aplikacja staje się bardziej złożona. Znacznie lepiej jest przygotować program w taki sposób, aby działał niezależnie od liczby pytań. Takie uogólnienie jest jeszcze ważniejsze, gdy lista, z którą pracujesz, zmienia się dynamicznie, na przykład w aplikacji z quizem, gdzie użytkownik może dodawać nowe pytania.<br />
<br />
Lepszym rozwiązaniem jest sprawdzenie warunku w sposób bardziej ogólny. Tak naprawdę chcesz wiedzieć, czy bieżące pytanie – czyli wartość zmiennej currentQuestionIndex jest tak duża, jak ilość elementów w zmiennej QuestionList. Jeżeli aplikacja sprawdzi warunek w bardziej ogólny sposób, to będzie działać, nawet jeżeli dodasz lub usuniesz elementy ze zmiennej QuestionList. Aby zmienić blok obsługi zdarzenia When NextButton.Click, zmień poprzedni test sprawdzający, który odnosił się bezpośrednio do 3. Będziesz potrzebował następujących bloków:<br />
{| class="wikitable"<br />
!Typ bloku<br />
!Szuflada<br />
!Działanie<br />
|-<br />
|length of list<br />
|Lists<br />
|Pyta, ile elementów jest w zmiennej QuestionList<br />
|-<br />
|get global QuestionList<br />
|Variables<br />
|Określa, o którą listę chodzi<br />
|}<br />
Blok obsługi zdarzenia When NextButton.Click powinien teraz wyglądać następująco:<br />
<br />
<br />
===Jak działają bloki?===<br />
Warunek if porównuje teraz wartość zmiennej CurrentQuestionIndex z długością zmiennej QuestionList. Zatem jeżeli zmienna CurrentQuestionIndex ma wartość 4, a długość zmiennej QuestionList wynosi 4, to wartość zmiennej currentQuestionIndex zostanie ustawiona na 0 (a następnie na 1, 2 itd.). Zauważ - bloki nie odwołują się już do 3 ani żadnej innej określonej wartości, dlatego instrukcja będzie działać bez względu na liczbę elementów listy.<br />
<br />
Przetestuj zmodyfikowane zachowanie. Czy po kliknięciu przycisku NextButton aplikacja przechodzi teraz przez cztery pytania, wracając po ostatnim do pierwszego?<br />
<br />
==Przełączanie zdjęcia dla każdego pytania==<br />
Na razie aplikacja wyświetla to samo zdjęcie, bez względu na to, jakie pytanie zostaje zadane. Możesz to zmienić tak, aby po kliknięciu przycisku NextButton pojawiała się fotografia dotycząca danego pytania. W obszarze Media dostępne są cztery dodane wcześniej zdjęcia. Teraz utworzymy trzecią listę - PictureList, której elementami będą nazwy plików zdjęć, a następnie zmodyfikujemy blok obsługi zdarzenia When NextButton.Click, aby program po każdym pytaniu przełączał zdjęcie.<br />
Najpierw utwórz listę PictureList i zainicjuj ją nazwami plików graficznych. Upewnij się, czy nazwy są dokładnie takie same jak nazwy plików, które zostały załadowane do obszaru Media. Oto jak powinien wyglądać blok dla listy PictureList:<br />
<br />
Następnie zmodyfikuj blok obsługi zdarzeń When NextButton.Click, aby zmieniał wyświetlane zdjęcie w zależności od zadanego pytania. Jeżeli ustawisz właściwość Image.Picture na nazwę pliku zdjęcia, które zostało załadowane, właśnie ta fotografia zostanie wyświetlona. Aby zmodyfikować blok When NextButton.Click, potrzebujesz następujących bloków:<br />
{| class="wikitable"<br />
!Typ bloku<br />
!Kategoria<br />
!Działanie<br />
|-<br />
|set Image1.Picture to<br />
|Image1<br />
|ustaw, aby zmieniać zdjęcie<br />
|-<br />
|select list item<br />
|Lists<br />
|należy wybrać zdjęcie odpowiadające na aktualne pytanie<br />
|-<br />
|get global PictureList<br />
|Variables<br />
|wybierz nazwę pliku z tej listy<br />
|-<br />
|get global currentQuestionIndex<br />
|Variables<br />
|wybierz element o n-tym indeksie currentQuestionIndex<br />
|}<br />
Oto jak powinny wyglądać bloki:<br />
<br />
===Jak działają bloki?===<br />
Zmienna CurrentQuestionIndex służy jako indeks dla zmiennej QuestionList. Wartość CurrentQuestionIndex wynosi 1, aplikacja wybiera pierwsze pytanie i pierwsze zdjęcie. Gdy CurrentQuestionIndex wynosi 2, aplikacja wybiera drugie pytanie i drugie zdjęcie. Oczywiście takie działanie zależy od tego, czy listy są ze sobą zsynchronizowane. Tak jest w tym przypadku - pierwszy obraz - LarsenBerra.jpg to zdjęcie Dona Larsena, jednocześnie Don Larsen to odpowiedź na pierwsze pytanie (Kto był doskonałym miotaczem w World Series?). <br />
Przetestuj zmodyfikowane zachowanie. Czy nowe zdjęcie pojawia się po każdym kliknięciu przycisku NextButton?<br />
<br />
==Ocena udzielanych odpowiedzi==<br />
Teraz dodamy bloki, które określają, czy użytkownik odpowiedział na pytanie prawidłowo, czy też nie. Gracz wprowadza odpowiedź do AnswerText, a następnie klika przycisk AnswerButton. Aplikacja musi porównać wpis użytkownika z odpowiedzią na bieżące pytanie, używając bloku if... then... w celu jej sprawdzenia. Etykieta RightWrongLabel powinna być modyfikowana, aby podawać, czy odpowiedź jest prawidłowa, czy nie.<br />
<br />
Do tego zachowania będą potrzebne następujące bloki:<br />
{| class="wikitable"<br />
!Typ bloku<br />
!Kategoria<br />
!Działanie<br />
|-<br />
|when AnswerButton.Click<br />
|AnswerButton<br />
|zachowanie jest wyzwalane, gdy użytkownik kliknie przycisk AnswerButton<br />
|-<br />
|if... then...<br />
|Control<br />
|Użyj mutatora, aby dodać alternatywę (else). Jeżeli odpowiedź jest prawidłowa - zrób jedno, w przeciwnym razie (else) - zrób coś innego<br />
|-<br />
|= <br />
|Math<br />
|sprawdzenie, czy odpowiedź jest prawidłowa<br />
|-<br />
|AnswerText.Text<br />
|AnswerText<br />
|Odpowiedź użytkownika pojawia się w tym polu tekstowym<br />
|-<br />
|select list item<br />
|Lists<br />
|wybrać bieżącą odpowiedź z listy AnswerList<br />
|-<br />
|get global AnswerList<br />
|Variables<br />
|lista, z której jest wybierany element<br />
|-<br />
|get global currentQuestionIndex<br />
|Variables<br />
|numer pytania (i numer odpowiedzi), przy którym jest użytkownik<br />
|-<br />
|set RightWrongLabel.Text to<br />
|RightWrongLabel<br />
|tutaj podaj odpowiedź<br />
|-<br />
|Dobrze!<br />
|Text<br />
|jeżeli odpowiedź jest prawidłowa<br />
|-<br />
|set RightWrongLabel.Text to<br />
|RightWrongLabel<br />
|tutaj podaj odpowiedź<br />
|-<br />
|Źle<br />
|Text<br />
|jeżeli odpowiedź jest nieprawidłowa<br />
|}<br />
Bloki powinny wyglądać następująco:<br />
<br />
===Jak działają bloki?===<br />
Test if sprawdza, czy odpowiedź użytkownika (AnswerText.Text) jest taka sama, jak element na liście AnswerList o indeksie równym wartości zmiennej CurrentQuestionIndex. Jeżeli zmienna CurrentQuestionIndex ma wartość 1, aplikacja porównuje odpowiedź użytkownika z pierwszą pozycją na liście AnswerList, (Don Larsen). Jeżeli zmienna CurrentQuestionIndex zmieni wartość na 2, program zestawia odpowiedź z drugą pozycją na liście, czyli Dallas Branden. Jeśli wynik porównania jest pozytywny, przeprowadzane są bloki then, a treść etykiety RightWrongLabel zostaje ustawiona na Dobrze!. Jeżeli wynik testu jest negatywny (fałszywy), przeprowadzane są bloki alternatywy (else), a treść etykiety RightWrongLabel zostaje ustawiona na Źle.<br />
<br />
Przetestuj zmodyfikowaną aplikację. Spróbuj odpowiedzieć na jedno z pytań. Powinna pojawić się ocena, czy odpowiedź była dokładnie taka sama, jak na liście AnswerList. Sprawdź zarówno prawidłowe, jak i nieprawidłowe odpowiedzi (Uwaga - uwzględniana jest wielkość liter!). Kliknij przycisk NextButton i odpowiedz na drugie pytanie. Czy aplikacja nadal działa? Powinna, ale zauważ, że gdy klikniesz przycisk NextButton, tekst Dobrze! lub Źle oraz poprzednia odpowiedź nadal będą wyświetlane. Choć nie wpływa to zasadniczo na naszą grę, to takie szczegóły interfejsu z pewnością zostaną zauważone przez użytkowników Twojej aplikacji.<br />
<br />
Aby wyzerować etykietę RightWrongLabel i AnswerText, umieść poniższe bloki w bloku obsługi zdarzeń When NextButton.click:<br />
{| class="wikitable"<br />
!Typ bloku<br />
!Kategoria<br />
!Działanie<br />
|-<br />
|set RightWrongLabel.Text to<br />
|RightWrongLabel<br />
|Ustawia wartość etykiety na…<br />
|-<br />
|„ „<br />
|Text<br />
|pusty tekst<br />
|-<br />
|set AnswerText.Text to<br />
|AnswerText<br />
|Ustawia wartość etykiety na…<br />
|-<br />
|„ „<br />
|Text<br />
|pusty tekst<br />
|}<br />
Bloki powinny wyglądać następująco:<br />
<br />
===Jak działają bloki?===<br />
Po kliknięciu przycisku NextButton użytkownik przechodzi do następnego pytania, dlatego początkowe wiersze bloku obsługi zdarzeń zerują etykietę RightWrongLabel i pole AnswerText.<br />
Przetestuj to zachowanie Odpowiedz na pytanie i kliknij przycisk Wyślij, a następnie - NextButton. Czy Twoja poprzednia odpowiedź i jej ocena zniknęły?<br />
<br />
==Ostateczna postać programu==<br />
Oto gotowa aplikacja QuizMe:<br />
<br />
Utwórz wykonywalną wersję aplikacji, wybierając menu Build/App (provide QR code for .apk). Gdy pojawi się kod kreskowy, użyj czytnika kodów w telefonie, aby pobrać i zainstalować aplikację.<br />
<br />
===Modyfikacje===<br />
Quiz w tej wersji jest już gotowy. Czy masz ochotę przemyśleć pewne zmiany?<br />
<br />
Zamiast wyświetlać zdjęcie dla każdego pytania, spróbuj odtworzyć dźwięk lub krótkie wideo. Za pomocą dźwięku możesz zmienić quiz w aplikację Jaka to melodia?.<br />
<br />
Quiz akceptuje ściśle określone odpowiedzi. Jeśli gracz odpowiedziałby, lekko przekształcając tekst (np. podając inicjał zamiast imienia), program uzna to za błąd. Można to zmienić na kilka różnych sposobów. Jednym z nich jest użycie bloku text.contains, aby sprawdzić, czy odpowiedź użytkownika zawiera prawidłową odpowiedź. Inny sposób to dostarczenie wielu odpowiedzi na każde pytanie i sprawdzenie przez iterację (użycie bloku for each), czy któraś z nich pasuje.<br />
<br />
Przekształć quiz tak, aby przedstawiał odpowiedzi do wyboru. Lista odpowiedzi będzie musiała być listą list, a każda podrzędna lista będzie musiała zawierać opcje odpowiedzi. Użyj komponentu ListPicker, aby umożliwić użytkownikowi wybranie odpowiedzi.<br />
<br />
<br />
==Podsumowanie==<br />
Oto niektóre koncepcje omówione w tym przewodniku:<br />
<ul><li>Aplikacje można tworzyć w sposób ogólny, aby pracować z dowolną listą danych.</li><br />
<li>Zmienne indeksu są wykorzystywane do śledzenia bieżącej pozycji na liście. Zwiększając wartość zmiennej indeksu, należy uważać na przekroczenie końca listy.</li></ul><br />
<br />
==Zeskanuj próbną aplikację do telefonu==<br />
Aby zainstalować i uruchomić aplikację próbną, zeskanuj poniższy kod kreskowy:<br />
<br />
==Pobierz kod źródłowy==<br />
Jeżeli chcesz pracować z tą próbką w programie App Inventor:<br />
<ul><li>pobierz na komputer kod źródłowy: [http://appinventor.mit.edu/explore/sites/all/files/ai2tutorials/QuizMe/QuizMe_MIT.aia http://appinventor.mit.edu/explore/sites/all/files/ai2tutorials/QuizMe/QuizMe_MIT.aia]</li><br />
<li>otwórz program App Inventor,</li><br />
<li>kliknij opcję My Projects,</li><br />
<li>wybierz Import project (.aia) from my computer...</li><br />
<li>znajdź i zatwierdź pobrany kod źródłowy.</li></ul></div>M Kelniarzhttp://wiki.mistrzowiekodowania.pl/index.php?title=QuizMeQuizMe2015-03-15T18:33:45Z<p>M Kelniarz: /* Iteracja pytań */</p>
<hr />
<div>=Aplikacja QuizMe dla App Inventor 2=<br />
<br />
==Co tworzysz?==<br />
[[Plik:t6-1.png|right]]QuizMe to gra dotycząca ciekawostek baseballowych, ale można jej użyć jako szablonu do tworzenia quizów z dowolnej dziedziny. W aplikacji użytkownik odpowiada na szereg pytań, otrzymując następnie informację zwrotną, czy udzielił poprawnej, czy błędnej odpowiedzi. Gracz przechodzi do kolejnego pytania, klikając przycisk.<br />
<br />
W grze QuizMe dysponujemy zamkniętym zbiorem pytań, chyba że programista je zmieni. W następnym etapie można utworzyć MakeQuiz & TakeQuiz – aplikację, która pozwala użytkownikom na tworzenie i modyfikowanie pytań.<br />
<br />
Poradnik ten zakłada, że znasz już podstawy tworzenia aplikacji w App Inventorze – korzystanie z Projektanta komponentów w celu utworzenia interfejsu użytkownika i z Edytora bloków, aby określić obsługę zdarzeń. Jeżeli potrzebujesz przypomnienia, spróbuj popracować z poradnikami podstawowymi zanim przejdziesz dalej.<br />
<br />
==Zaczynamy!==<br />
Połącz się z witryną internetową App Inventor i załóż nowy projekt. Nazwij go QuizMe, ustaw taki sam tytuł ekranu (Title). Za pomocą MIT AI2 Companion połącz program z urządzeniem mobilnym. Pobierz poniższe zdjęcia baseballistów i zapisz je w komputerze. Później załadujesz je do projektu.<br />
<ul><li> [http://beta.appinventor.mit.edu/learn/tutorials/quizme/QuizMeAssets/Larsenberra.jpg Larsenberra.jpg]</li><br />
<li> [http://beta.appinventor.mit.edu/learn/tutorials/quizme/QuizMeAssets/dallasbraden.jpg Dallasbraden.jpg]</li><br />
<li> [http://beta.appinventor.mit.edu/learn/tutorials/quizme/QuizMeAssets/cyyoung.jpg Cyyoung.jpg]</li><br />
<li> [http://beta.appinventor.mit.edu/learn/tutorials/quizme/QuizMeAssets/nolanryan.jpg Nolanryan.jpg]</li></ul><br />
<br />
==Wstęp==<br />
Zaprojektujesz grę typu quiz, w której użytkownik będzie przechodził do kolejnych pytań, klikając przycisk Dalej, a następnie otrzymywał prostą ocenę Dobrze/Źle dla każdej odpowiedzi.<br />
<br />
W tym przewodniku omówimy:<br />
<ul><li>definiowanie i wyświetlanie listy informacji;</li><br />
<li>przechodzenie przez listę za pomocą zmiennej indeksującej – zmiennej, która śledzi pozycję na liście;</li><br />
<li>zachowania warunkowe – wykonywanie określonych operacji tylko wtedy, gdy spełniony jest określony warunek;</li><br />
<li>Zmianę zdjęcia w zależności od sytuacji.</li></ul><br />
<br />
==Projektowanie aplikacji==<br />
Użyj Projektanta komponentów do utworzenia interfejsu dla aplikacji QuizMe. <br />
Aby utworzyć interfejs, najpierw załaduj do projektu pobrane zdjęcia. Kliknij przycisk Prześlij plik (Upload File...) w obszarze Media i wybierz jeden z pobranych wcześniej plików (np. Larsenberra.jpg). Następnie zrób to samo z pozostałymi trzema zdjęciami.<br />
Utwórz następujące komponenty, przeciągając je z Palety (Palette) do Przeglądarki (Viewer) i ustaw właściwości komponentów zgodnie z poniższym opisem:<br />
{|class="wikitable"<br />
! Typ komponentu<br />
! Kategoria<br />
! Jaką nadać jej nazwę<br />
! Działanie<br />
! Działanie komponentu<br />
|-<br />
|Image<br />
|User interface<br />
|Image1<br />
|Ustaw właściwość zdjęcia (Picture) na Larsenberra.jpg. Jest to pierwsze wyświetlane zdjęcie.<br />
|Obrazkowa część pytania<br />
|-<br />
|Label<br />
|User interface<br />
|QuestionLabel<br />
|Zmień właściwość tekstu (Text) na Pytanie:<br />
|Wyświetla bieżące pytanie<br />
|-<br />
|HorizontalArrangement<br />
|Layout<br />
|HorizontalArrangement1<br />
| <br />
|Organizuje komponenty AnswerPrompt i Text (podaj odpowiedź i tekst)<br />
|-<br />
|Label<br />
|User interface<br />
|AnswerPromptLabel<br />
|Zmień właściwość tekstu (Text) na Podaj odpowiedź:. Na ekranie przeglądarki przesuń tę etykietę do HorizontalArrangement1.<br />
|Wyświetla tekst prośby o odpowiedź.<br />
|-<br />
|TextBox<br />
|User interface<br />
|AnswerText<br />
|Zmień wskazówkę (Hint) na Podaj odpowiedź. Na ekranie przeglądarki przenieś AnswerText do komponentu HorizontalArrangement1.<br />
|Tutaj użytkownik podaje odpowiedź.<br />
|-<br />
|Label<br />
|User interface <br />
|RightWrongLabel<br />
|Zmień właściwość tekstu (Text) na Dobrze/Źle.<br />
|Tutaj wyświetlana jest ocena Dobrze/Źle.<br />
|-<br />
|HorizontalArrangement<br />
|Layout<br />
|HorizontalArrangement2<br />
|<br />
|Organizuje przyciski AnswerButton i NextButton (przycisk odpowiedzi i przycisk dalej).<br />
|-<br />
|Przycisk<br />
|User interface<br />
|AnswerButton<br />
|Zmień właściwość tekstu (Text) na Wyślij. Na ekranie przeglądarki przesuń ten przycisk do HorizontalArrangment2.<br />
|Użytkownik klika, aby przesłać odpowiedź.<br />
|-<br />
|Przycisk<br />
|User interface<br />
|NextButton<br />
|Zmień właściwość tekstu (Text) na Dalej. Przenieś ten przycisk do HorizontalArrangement2.<br />
|Użytkownik klika, aby przejść do następnego pytania.<br />
|} <br />
Po zakończeniu powinien on wyglądać jak poniższa ilustracja (pod nią znajdują się również bardziej szczegółowe informacje).<br />
[[Plik:t6-2.png]]<br />
<br />
==Programowanie aplikacji==<br />
Otwórz Edytor bloków, aby zaprogramować działanie komponentów. Najpierw zdefiniuj dwie zmienne - listy: zmienną QuestionList, zawierającą listę pytań i zmienną AnswerList z listą odpowiedzi na te pytania.<br />
<br />
Aby zdefiniować te dwie zmienne listy, potrzebujesz następujących bloków:<br />
{| class="wikitable"<br />
!Typ bloku<br />
!Kategoria<br />
!Działanie<br />
|-<br />
|initialize global name to<br />
|Variables<br />
|Definiuje zmienną QuestionList (zmień jej nazwę)<br />
|-<br />
|initialize global name to<br />
|Variables<br />
|Definiuje zmienną AnswerList (zmień jej nazwę)<br />
|-<br />
|make a list<br />
|Lists<br />
|Służy do dodawania elementów do zmiennej QuestionList<br />
|-<br />
|„ „ (trzykrotnie)<br />
|Lists<br />
|Służy do wpisania pytań<br />
|-<br />
|make a list<br />
|Lists<br />
|Służy do dodawania elementów do zmiennej AnswerList<br />
|-<br />
|„ „ (trzykrotnie)<br />
|Text<br />
|Służy do wpisania odpowiedzi<br />
|}<br />
Utwórz zmienne całościowe, przeciągając z kategorii zmiennych (Variables) na obszar roboczy blok Initialize global name to. Kliknij dwukrotnie domyślną nazwę name, aby ją zmienić. Blok Initialize global name to zawiera pole na początkową wartość zmiennej. Zmienna może zawierać liczbę, tekst, a nawet listę – aby ją utworzyć, podłącz blok Make a list do definicji zmiennej.<br />
<br />
Bloki powinny wyglądać następująco:<br />
<br />
[[Plik:t6-3.png]]<br />
===Zdefiniuj ukrytą zmienną Index===<br />
Za każdym razem, gdy użytkownik kliknie przycisk NextButton, aby przejść dalej, aplikacja musi pamiętać, przy którym pytaniu jest obecnie gracz. W języku programowania, aby coś zapamiętać, trzeba zdefiniować nową zmienną. W tym przypadku aplikacja musi zapamiętać bieżący numer pytania – indeks listy QuestionList.<br />
Aby zdefiniować zmienną currentQuestionIndex, potrzebujesz następujących bloków:<br />
{| class="wikitable"<br />
!Typ bloku<br />
!Kategoria<br />
!Działanie<br />
|-<br />
|initialize global name to<br />
|Variables<br />
|Definiuje zmienną currentQuestionIndex (zmień nazwę)<br />
|-<br />
|0 (1)<br />
|Math<br />
|Ustaw wartość początkową currentQuestionIndex na 1 (zmień liczbę)<br />
|}<br />
Bloki powinny wyglądać następująco:<br />
<br />
[[Plik:t6-4.png]]<br />
<br />
===Wyświetl pierwsze pytanie===<br />
Odłóż na razie kwestię odpowiedzi i skup się na zaprogramowaniu sekwencyjnego przejścia przez pytania. Pożądane zachowanie jest następujące: po uruchomieniu aplikacji na etykiecie o nazwie QuestionLabel pojawia się pierwsze pytanie. Gdy użytkownik kliknie NextButton, wyświetlone zostaje drugie pytanie. Po ponownym kliknięciu pojawia się trzecie pytanie. Po dotarciu do ostatniego pytania kliknięcie przycisku NextButton powoduje ponowne pojawienie się pierwszego pytania w etykiecie QuestionLabel.<br />
<br />
W programie App Inventor określone pozycje na liście są wybierane za pomocą bloku select list item. W tym bloku trzeba podać listę i indeks – pozycję na liście. Jeżeli na liście są trzy pozycje, prawidłowe indeksy to 1, 2 i 3.<br />
<br />
Po uruchomieniu aplikacja QuizMe powinna wybrać pierwsze pytanie z listy i wyświetlić je w komponencie QuestionLabel. Do tego zachowania inicjalizującego działanie aplikacji potrzebne są następujące bloki:<br />
<br />
{| class="wikitable"<br />
!Typ bloku<br />
!Kategoria<br />
!Działanie<br />
|-<br />
|when Screen1.Initialize<br />
|Screen1<br />
|Podczas uruchamiania aplikacji zainicjowana jest ta obsługa zdarzenia<br />
|-<br />
|set QuestionLabel.Text to<br />
|QuestionLabel<br />
|Umieszcza pierwsze pytanie w etykiecie QuestionLabel<br />
|-<br />
|select list item<br />
|Lists<br />
|Wybiera pierwsze pytanie z etykiety QuestionLabel<br />
|-<br />
|get <br />
|Variables<br />
|Ustala listę, z której jest wybierany element. Tutaj: Global QuestionList<br />
|-<br />
|0 (1)<br />
|Math<br />
|Wybiera pierwsze pytanie za pomocą indeksu 1. Ustaw wartość na 1.<br />
|}<br />
Bloki powinny wyglądać następująco:<br />
<br />
[[Plik:t6-5.png]]<br />
<br />
===Jak działają bloki?===<br />
Zdarzenie when Screen1.Initialize jest wyzwalane podczas uruchomienia aplikacji. Pierwsza pozycja zmiennej QuestionList zostaje wybrana i umieszczona w bloku set QuestionLabel.Text. Gdy aplikacja zostanie uruchomiona, użytkownik zobaczy pierwsze pytanie.<br />
===Przetestuj to zachowanie===<br />
Jeśli dotychczas nie skomunikowałeś urządzenia mobilnego z programem, zrób to teraz. Co pojawia się na urządzeniu? Jeżeli utworzono listę QuestionList tak, jak wskazano powyżej, w etykiecie QuestionLabel powinna pojawić się pierwsza pozycja tej listy (Kto był doskonałym miotaczem w World Series?).<br />
<br />
==Iteracja pytań==<br />
Zdefiniowałeś już zmienną CurrentQuestionIndex, zapamiętującą pytanie, przy którym znajduje się użytkownik. Zaprogramuj teraz zachowanie przycisku NextButton. Gdy zostanie on kliknięty, aplikacja zwiększy wartość zmiennej, np. zmieni ją z 1 na 2 lub z 2 na 3 itd., a następnie użyje tej wartości do zaznaczenia nowego bieżącego pytania. Do tego zachowania potrzebne są następujące bloki:<br />
{| class="wikitable"<br />
!Typ bloku<br />
!Kategoria<br />
!Działanie<br />
|-<br />
|when NextButton.Click<br />
|NextButton<br />
|Uruchamia obsługę zdarzeń po kliknięciu przycisku<br />
|-<br />
|set currentQuestionIndex to<br />
|Zmienne<br />
|Decyduje o ustawieniu indeksu wybranej listy<br />
|-<br />
|+ <br />
|Math<br />
|Służy do zwiększania wartości zmiennej currentQuestionIndex<br />
|-<br />
|get global currentQuestionIndex<br />
|Zmienne<br />
|Tworzy nową wartość poprzez zwiększenie poprzedniej wartości o 1<br />
|-<br />
|0 (1)<br />
|Math<br />
|Dla + 1<br />
|-<br />
|set QuestionLabel.Text to<br />
|QuestionLabel<br />
|Wyświetla kolejne pytanie<br />
|-<br />
|select list item<br />
|Listy<br />
|Ustawia element listy jako wartość QuestionLabel<br />
|-<br />
|get global QuestionList<br />
|Zmienne<br />
|Wskazuje, która lista będzie wybrana<br />
|-<br />
|get global currentQuestionIndex<br />
|Zmienne<br />
|Wskazuje, który element wybranej listy będzie wybrany<br />
|}<br />
Bloki powinny wyglądać następująco:<br />
<br />
[[Plik:t6-6.png]]<br />
<br />
===Jak działają bloki?===<br />
Pierwszy wiersz polecenia zwiększa wartość zmiennej currentQuestionIndex o 1 (jeżeli zmienna zawiera wartość 1, zostaje ona zmieniona na 2, z 2 na 3 itd.). Następnie wykorzystuje nową wartość do wyboru pytania o tym indeksie.<br />
<br />
Przypomnijmy, że w bloku obsługi zdarzeń Screen.Initialize aplikacja wybrała pierwsze do wyświetlenia pytanie:<br />
<br />
[[Plik:t6-7.png]]<br />
<br />
Po kliknięciu przycisku NextButton aplikacja nie wybiera konkretnie pierwszej, drugiej czy trzeciej pozycji na liście, tylko pozycję o n-tej wartości zmiennej currentQuestionIndex.<br />
<br />
[[Plik:t6-8.png]]<br />
<br />
Polecenia w blokach są wykonywane od prawej do lewej, tzn. aplikacja najpierw określa wartość parametru z bloku Select list item, którym jest zmienna CurrentQuestionIndex. Liczba zawarta w tej zmiennej zostaje użyta jako indeks podczas wykonania poleceń zawartych w bloku Select list item.<br />
<br />
[[Plik:info.png|left]]''Po pierwszym kliknięciu przycisku NextButton, wartość zmiennej currentQuestionIndex przeskoczy z 1 na 2, aby aplikacja wybrała drugą pozycję z listy QuestionList (Kto był pierwszym doskonałym miotaczem w 2010?). Po drugim kliknięciu przycisku NextButton, wartość zmiennej currentQuestionIndex zostanie zmieniona z 2 na 3, a aplikacja wybierze trzecie pytanie z listy (Kto był pierwszym doskonałym miotaczem nowej ery?).''<br />
<br />
<br />
===Przetestuj to zachowanie===<br />
Przetestuj zachowanie przycisku NextButton, aby sprawdzić, czy aplikacja działa poprawnie. Wciel się w rolę użytkownika i kliknij przycisk NextButton w telefonie. Czy urządzenie wyświetliło drugie pytanie: Kto był pierwszym doskonałym miotaczem w 2010?? Trzecie pytanie powinno pojawić się po kolejnym kliknięciu przycisku. Jeżeli aplikacja działa, pogratuluj sobie i przejdź dalej. Kliknij przycisk NextButton ponownie (po raz trzeci). Powinien zostać wyświetlony błąd: Próba uzyskania elementu 4 z listy o długości 3. Czy wiesz, na czym polega problem?<br />
<br />
Problem z aplikacją polega na tym, że zawsze po kliknięciu przycisku NextButton zwiększa ona zmienną CurrentQuestionIndex o 1. Gdy wartość zmiennej wynosi już 3, a użytkownik kolejny raz kliknie przycisk NextButton, aplikacja zmieni wartość zmiennej z 3 na 4, następnie wywoła blok Select list item, aby odczytać pozycję o aktualnym indeksie CurrentQuestionIndex, czyli w tym przypadku czwartą pozycję. Ponieważ zmienna QuestionList zawiera tylko trzy elementy, Android wykaże błąd.<br />
<br />
Aplikacja musi zadawać pytanie - sprawdzać warunek - gdy nastąpi kliknięcie przycisku NextButton i realizować polecenia zawarte w różnych blokach w zależności od odpowiedzi. Elementem do sprawdzenia jest to, czy zmienna CurrentQuestionIndex już ma wartość 3. Jeżeli tak - należy ustawić CurrentQuestionIndex z powrotem na 0, aby użytkownik wrócił do pierwszego pytania.<br />
<br />
Będziesz potrzebował następujących bloków:<br />
{| class="wikitable"<br />
!Typ bloku<br />
!Kategoria<br />
!Działanie<br />
|-<br />
|if then<br />
|Control<br />
|sprawdzenie, czy użytkownik jest na etapie ostatniego pytania<br />
|-<br />
|= <br />
|Math<br />
|sprawdzenie, czy currentQuestionIndex ma wartość 3<br />
|-<br />
|get global currentQuestionIndex<br />
|Variables<br />
|<br />
|-<br />
|0 (3)<br />
|Math<br />
|3 to numer na liście<br />
|-<br />
|set currentQuestionIndex to<br />
|Variables<br />
|ustawienie na 0, aby wrócić do pierwszego pytania<br />
|-<br />
|0<br />
|Math<br />
|ustawienie na 0, ponieważ kolejne bloki zwiększą wartość do 1<br />
|}<br />
Zmodyfikowany blok obsługi zdarzenia When NextButton.Click powinien wyglądać następująco:<br />
<br />
[[Plik:t6-9.png]]<br />
<br />
===Jak działają bloki===<br />
Po kliknięciu przycisku NextButton aplikacja najpierw sprawdza, czy currentQuestionIndex ma wartość 3. Jeżeli tak, wartość tej zmiennej jest ustawiana na 0, aby po zwiększeniu jej w dalszych krokach jej wartość wyniosła 1. Wtedy quiz wróci do pierwszego pytania. Zauważ, że tylko bloki osadzone w bloku if-then są zależne od warunku. Blok zwiększenia wartości i blok Set QuestionLabel.Text to są wykonywane bez względu na jakikolwiek warunek.<br />
<br />
==Aplikacja modyfikowalna: Ułatwianie modyfikowania pytań==<br />
Teraz zmodyfikujemy aplikację, aby można było łatwo dodawać i usuwać elementy z listy. Zmień bloki tak, aby działały na liście o dowolnej długości, a nie tylko liście z dokładnie trzema pozycjami. <br />
Na początek dodaj czwarte pytanie do zmiennej QuestionList i kolejną odpowiedź do AnswerList. W tym celu musisz najpierw zwiększyć liczbę dostępnych pól za pomocą przycisku modyfikującego (mutatora). Aby dowiedzieć się więcej o tym elemencie, zobacz: http://appinventor.mit.edu/explore/ai2/support/concepts/mutators. Bloki powinny wyglądać następująco:<br />
<br />
===Przetestuj zmodyfikowaną aplikację.===<br />
Kliknij przycisk NextButton kilka razy. Zauważysz, że czwarte pytanie nigdy się nie pojawia, bez względu na to, ile razy klikniesz przycisk.<br />
<br />
Problemem jest to, że test sprawdzający, czy użytkownik znajduje się przy ostatnim pytaniu, jest zbyt szczegółowy: pyta, czy zmienna CurrentQuestionIndex ma wartość 3:<br />
<br />
Możesz po prostu zmienić liczbę z 3 na 4, a aplikacja będzie znów działać poprawnie. Problem polega jednak na tym, że za każdym razem, gdy zmodyfikujesz liczbę pytań i odpowiedzi, będziesz musiał pamiętać, aby dokonać także tej zmiany. Takie zależności w programie komputerowym często prowadzą do błędów, w szczególności gdy aplikacja staje się bardziej złożona. Znacznie lepiej jest przygotować program w taki sposób, aby działał niezależnie od liczby pytań. Takie uogólnienie jest jeszcze ważniejsze, gdy lista, z którą pracujesz, zmienia się dynamicznie, na przykład w aplikacji z quizem, gdzie użytkownik może dodawać nowe pytania.<br />
<br />
Lepszym rozwiązaniem jest sprawdzenie warunku w sposób bardziej ogólny. Tak naprawdę chcesz wiedzieć, czy bieżące pytanie – czyli wartość zmiennej currentQuestionIndex jest tak duża, jak ilość elementów w zmiennej QuestionList. Jeżeli aplikacja sprawdzi warunek w bardziej ogólny sposób, to będzie działać, nawet jeżeli dodasz lub usuniesz elementy ze zmiennej QuestionList. Aby zmienić blok obsługi zdarzenia When NextButton.Click, zmień poprzedni test sprawdzający, który odnosił się bezpośrednio do 3. Będziesz potrzebował następujących bloków:<br />
{| class="wikitable"<br />
!Typ bloku<br />
!Szuflada<br />
!Działanie<br />
|-<br />
|length of list<br />
|Lists<br />
|Pyta, ile elementów jest w zmiennej QuestionList<br />
|-<br />
|get global QuestionList<br />
|Variables<br />
|Określa, o którą listę chodzi<br />
|}<br />
Blok obsługi zdarzenia When NextButton.Click powinien teraz wyglądać następująco:<br />
<br />
<br />
===Jak działają bloki?===<br />
Warunek if porównuje teraz wartość zmiennej CurrentQuestionIndex z długością zmiennej QuestionList. Zatem jeżeli zmienna CurrentQuestionIndex ma wartość 4, a długość zmiennej QuestionList wynosi 4, to wartość zmiennej currentQuestionIndex zostanie ustawiona na 0 (a następnie na 1, 2 itd.). Zauważ - bloki nie odwołują się już do 3 ani żadnej innej określonej wartości, dlatego instrukcja będzie działać bez względu na liczbę elementów listy.<br />
<br />
Przetestuj zmodyfikowane zachowanie. Czy po kliknięciu przycisku NextButton aplikacja przechodzi teraz przez cztery pytania, wracając po ostatnim do pierwszego?<br />
<br />
==Przełączanie zdjęcia dla każdego pytania==<br />
Na razie aplikacja wyświetla to samo zdjęcie, bez względu na to, jakie pytanie zostaje zadane. Możesz to zmienić tak, aby po kliknięciu przycisku NextButton pojawiała się fotografia dotycząca danego pytania. W obszarze Media dostępne są cztery dodane wcześniej zdjęcia. Teraz utworzymy trzecią listę - PictureList, której elementami będą nazwy plików zdjęć, a następnie zmodyfikujemy blok obsługi zdarzenia When NextButton.Click, aby program po każdym pytaniu przełączał zdjęcie.<br />
Najpierw utwórz listę PictureList i zainicjuj ją nazwami plików graficznych. Upewnij się, czy nazwy są dokładnie takie same jak nazwy plików, które zostały załadowane do obszaru Media. Oto jak powinien wyglądać blok dla listy PictureList:<br />
<br />
Następnie zmodyfikuj blok obsługi zdarzeń When NextButton.Click, aby zmieniał wyświetlane zdjęcie w zależności od zadanego pytania. Jeżeli ustawisz właściwość Image.Picture na nazwę pliku zdjęcia, które zostało załadowane, właśnie ta fotografia zostanie wyświetlona. Aby zmodyfikować blok When NextButton.Click, potrzebujesz następujących bloków:<br />
{| class="wikitable"<br />
!Typ bloku<br />
!Kategoria<br />
!Działanie<br />
|-<br />
|set Image1.Picture to<br />
|Image1<br />
|ustaw, aby zmieniać zdjęcie<br />
|-<br />
|select list item<br />
|Lists<br />
|należy wybrać zdjęcie odpowiadające na aktualne pytanie<br />
|-<br />
|get global PictureList<br />
|Variables<br />
|wybierz nazwę pliku z tej listy<br />
|-<br />
|get global currentQuestionIndex<br />
|Variables<br />
|wybierz element o n-tym indeksie currentQuestionIndex<br />
|}<br />
Oto jak powinny wyglądać bloki:<br />
<br />
===Jak działają bloki?===<br />
Zmienna CurrentQuestionIndex służy jako indeks dla zmiennej QuestionList. Wartość CurrentQuestionIndex wynosi 1, aplikacja wybiera pierwsze pytanie i pierwsze zdjęcie. Gdy CurrentQuestionIndex wynosi 2, aplikacja wybiera drugie pytanie i drugie zdjęcie. Oczywiście takie działanie zależy od tego, czy listy są ze sobą zsynchronizowane. Tak jest w tym przypadku - pierwszy obraz - LarsenBerra.jpg to zdjęcie Dona Larsena, jednocześnie Don Larsen to odpowiedź na pierwsze pytanie (Kto był doskonałym miotaczem w World Series?). <br />
Przetestuj zmodyfikowane zachowanie. Czy nowe zdjęcie pojawia się po każdym kliknięciu przycisku NextButton?<br />
<br />
==Ocena udzielanych odpowiedzi==<br />
Teraz dodamy bloki, które określają, czy użytkownik odpowiedział na pytanie prawidłowo, czy też nie. Gracz wprowadza odpowiedź do AnswerText, a następnie klika przycisk AnswerButton. Aplikacja musi porównać wpis użytkownika z odpowiedzią na bieżące pytanie, używając bloku if... then... w celu jej sprawdzenia. Etykieta RightWrongLabel powinna być modyfikowana, aby podawać, czy odpowiedź jest prawidłowa, czy nie.<br />
<br />
Do tego zachowania będą potrzebne następujące bloki:<br />
{| class="wikitable"<br />
!Typ bloku<br />
!Kategoria<br />
!Działanie<br />
|-<br />
|when AnswerButton.Click<br />
|AnswerButton<br />
|zachowanie jest wyzwalane, gdy użytkownik kliknie przycisk AnswerButton<br />
|-<br />
|if... then...<br />
|Control<br />
|Użyj mutatora, aby dodać alternatywę (else). Jeżeli odpowiedź jest prawidłowa - zrób jedno, w przeciwnym razie (else) - zrób coś innego<br />
|-<br />
|= <br />
|Math<br />
|sprawdzenie, czy odpowiedź jest prawidłowa<br />
|-<br />
|AnswerText.Text<br />
|AnswerText<br />
|Odpowiedź użytkownika pojawia się w tym polu tekstowym<br />
|-<br />
|select list item<br />
|Lists<br />
|wybrać bieżącą odpowiedź z listy AnswerList<br />
|-<br />
|get global AnswerList<br />
|Variables<br />
|lista, z której jest wybierany element<br />
|-<br />
|get global currentQuestionIndex<br />
|Variables<br />
|numer pytania (i numer odpowiedzi), przy którym jest użytkownik<br />
|-<br />
|set RightWrongLabel.Text to<br />
|RightWrongLabel<br />
|tutaj podaj odpowiedź<br />
|-<br />
|Dobrze!<br />
|Text<br />
|jeżeli odpowiedź jest prawidłowa<br />
|-<br />
|set RightWrongLabel.Text to<br />
|RightWrongLabel<br />
|tutaj podaj odpowiedź<br />
|-<br />
|Źle<br />
|Text<br />
|jeżeli odpowiedź jest nieprawidłowa<br />
|}<br />
Bloki powinny wyglądać następująco:<br />
<br />
===Jak działają bloki?===<br />
Test if sprawdza, czy odpowiedź użytkownika (AnswerText.Text) jest taka sama, jak element na liście AnswerList o indeksie równym wartości zmiennej CurrentQuestionIndex. Jeżeli zmienna CurrentQuestionIndex ma wartość 1, aplikacja porównuje odpowiedź użytkownika z pierwszą pozycją na liście AnswerList, (Don Larsen). Jeżeli zmienna CurrentQuestionIndex zmieni wartość na 2, program zestawia odpowiedź z drugą pozycją na liście, czyli Dallas Branden. Jeśli wynik porównania jest pozytywny, przeprowadzane są bloki then, a treść etykiety RightWrongLabel zostaje ustawiona na Dobrze!. Jeżeli wynik testu jest negatywny (fałszywy), przeprowadzane są bloki alternatywy (else), a treść etykiety RightWrongLabel zostaje ustawiona na Źle.<br />
<br />
Przetestuj zmodyfikowaną aplikację. Spróbuj odpowiedzieć na jedno z pytań. Powinna pojawić się ocena, czy odpowiedź była dokładnie taka sama, jak na liście AnswerList. Sprawdź zarówno prawidłowe, jak i nieprawidłowe odpowiedzi (Uwaga - uwzględniana jest wielkość liter!). Kliknij przycisk NextButton i odpowiedz na drugie pytanie. Czy aplikacja nadal działa? Powinna, ale zauważ, że gdy klikniesz przycisk NextButton, tekst Dobrze! lub Źle oraz poprzednia odpowiedź nadal będą wyświetlane. Choć nie wpływa to zasadniczo na naszą grę, to takie szczegóły interfejsu z pewnością zostaną zauważone przez użytkowników Twojej aplikacji.<br />
<br />
Aby wyzerować etykietę RightWrongLabel i AnswerText, umieść poniższe bloki w bloku obsługi zdarzeń When NextButton.click:<br />
{| class="wikitable"<br />
!Typ bloku<br />
!Kategoria<br />
!Działanie<br />
|-<br />
|set RightWrongLabel.Text to<br />
|RightWrongLabel<br />
|Ustawia wartość etykiety na…<br />
|-<br />
|„ „<br />
|Text<br />
|pusty tekst<br />
|-<br />
|set AnswerText.Text to<br />
|AnswerText<br />
|Ustawia wartość etykiety na…<br />
|-<br />
|„ „<br />
|Text<br />
|pusty tekst<br />
|}<br />
Bloki powinny wyglądać następująco:<br />
<br />
===Jak działają bloki?===<br />
Po kliknięciu przycisku NextButton użytkownik przechodzi do następnego pytania, dlatego początkowe wiersze bloku obsługi zdarzeń zerują etykietę RightWrongLabel i pole AnswerText.<br />
Przetestuj to zachowanie Odpowiedz na pytanie i kliknij przycisk Wyślij, a następnie - NextButton. Czy Twoja poprzednia odpowiedź i jej ocena zniknęły?<br />
<br />
==Ostateczna postać programu==<br />
Oto gotowa aplikacja QuizMe:<br />
<br />
Utwórz wykonywalną wersję aplikacji, wybierając menu Build/App (provide QR code for .apk). Gdy pojawi się kod kreskowy, użyj czytnika kodów w telefonie, aby pobrać i zainstalować aplikację.<br />
<br />
===Modyfikacje===<br />
Quiz w tej wersji jest już gotowy. Czy masz ochotę przemyśleć pewne zmiany?<br />
<br />
Zamiast wyświetlać zdjęcie dla każdego pytania, spróbuj odtworzyć dźwięk lub krótkie wideo. Za pomocą dźwięku możesz zmienić quiz w aplikację Jaka to melodia?.<br />
<br />
Quiz akceptuje ściśle określone odpowiedzi. Jeśli gracz odpowiedziałby, lekko przekształcając tekst (np. podając inicjał zamiast imienia), program uzna to za błąd. Można to zmienić na kilka różnych sposobów. Jednym z nich jest użycie bloku text.contains, aby sprawdzić, czy odpowiedź użytkownika zawiera prawidłową odpowiedź. Inny sposób to dostarczenie wielu odpowiedzi na każde pytanie i sprawdzenie przez iterację (użycie bloku for each), czy któraś z nich pasuje.<br />
<br />
Przekształć quiz tak, aby przedstawiał odpowiedzi do wyboru. Lista odpowiedzi będzie musiała być listą list, a każda podrzędna lista będzie musiała zawierać opcje odpowiedzi. Użyj komponentu ListPicker, aby umożliwić użytkownikowi wybranie odpowiedzi.<br />
<br />
<br />
==Podsumowanie==<br />
Oto niektóre koncepcje omówione w tym przewodniku:<br />
<ul><li>Aplikacje można tworzyć w sposób ogólny, aby pracować z dowolną listą danych.</li><br />
<li>Zmienne indeksu są wykorzystywane do śledzenia bieżącej pozycji na liście. Zwiększając wartość zmiennej indeksu, należy uważać na przekroczenie końca listy.</li></ul><br />
<br />
==Zeskanuj próbną aplikację do telefonu==<br />
Aby zainstalować i uruchomić aplikację próbną, zeskanuj poniższy kod kreskowy:<br />
<br />
==Pobierz kod źródłowy==<br />
Jeżeli chcesz pracować z tą próbką w programie App Inventor:<br />
<ul><li>pobierz na komputer kod źródłowy: [http://appinventor.mit.edu/explore/sites/all/files/ai2tutorials/QuizMe/QuizMe_MIT.aia http://appinventor.mit.edu/explore/sites/all/files/ai2tutorials/QuizMe/QuizMe_MIT.aia]</li><br />
<li>otwórz program App Inventor,</li><br />
<li>kliknij opcję My Projects,</li><br />
<li>wybierz Import project (.aia) from my computer...</li><br />
<li>znajdź i zatwierdź pobrany kod źródłowy.</li></ul></div>M Kelniarzhttp://wiki.mistrzowiekodowania.pl/index.php?title=QuizMeQuizMe2015-03-15T18:32:41Z<p>M Kelniarz: /* Jak działają bloki? */</p>
<hr />
<div>=Aplikacja QuizMe dla App Inventor 2=<br />
<br />
==Co tworzysz?==<br />
[[Plik:t6-1.png|right]]QuizMe to gra dotycząca ciekawostek baseballowych, ale można jej użyć jako szablonu do tworzenia quizów z dowolnej dziedziny. W aplikacji użytkownik odpowiada na szereg pytań, otrzymując następnie informację zwrotną, czy udzielił poprawnej, czy błędnej odpowiedzi. Gracz przechodzi do kolejnego pytania, klikając przycisk.<br />
<br />
W grze QuizMe dysponujemy zamkniętym zbiorem pytań, chyba że programista je zmieni. W następnym etapie można utworzyć MakeQuiz & TakeQuiz – aplikację, która pozwala użytkownikom na tworzenie i modyfikowanie pytań.<br />
<br />
Poradnik ten zakłada, że znasz już podstawy tworzenia aplikacji w App Inventorze – korzystanie z Projektanta komponentów w celu utworzenia interfejsu użytkownika i z Edytora bloków, aby określić obsługę zdarzeń. Jeżeli potrzebujesz przypomnienia, spróbuj popracować z poradnikami podstawowymi zanim przejdziesz dalej.<br />
<br />
==Zaczynamy!==<br />
Połącz się z witryną internetową App Inventor i załóż nowy projekt. Nazwij go QuizMe, ustaw taki sam tytuł ekranu (Title). Za pomocą MIT AI2 Companion połącz program z urządzeniem mobilnym. Pobierz poniższe zdjęcia baseballistów i zapisz je w komputerze. Później załadujesz je do projektu.<br />
<ul><li> [http://beta.appinventor.mit.edu/learn/tutorials/quizme/QuizMeAssets/Larsenberra.jpg Larsenberra.jpg]</li><br />
<li> [http://beta.appinventor.mit.edu/learn/tutorials/quizme/QuizMeAssets/dallasbraden.jpg Dallasbraden.jpg]</li><br />
<li> [http://beta.appinventor.mit.edu/learn/tutorials/quizme/QuizMeAssets/cyyoung.jpg Cyyoung.jpg]</li><br />
<li> [http://beta.appinventor.mit.edu/learn/tutorials/quizme/QuizMeAssets/nolanryan.jpg Nolanryan.jpg]</li></ul><br />
<br />
==Wstęp==<br />
Zaprojektujesz grę typu quiz, w której użytkownik będzie przechodził do kolejnych pytań, klikając przycisk Dalej, a następnie otrzymywał prostą ocenę Dobrze/Źle dla każdej odpowiedzi.<br />
<br />
W tym przewodniku omówimy:<br />
<ul><li>definiowanie i wyświetlanie listy informacji;</li><br />
<li>przechodzenie przez listę za pomocą zmiennej indeksującej – zmiennej, która śledzi pozycję na liście;</li><br />
<li>zachowania warunkowe – wykonywanie określonych operacji tylko wtedy, gdy spełniony jest określony warunek;</li><br />
<li>Zmianę zdjęcia w zależności od sytuacji.</li></ul><br />
<br />
==Projektowanie aplikacji==<br />
Użyj Projektanta komponentów do utworzenia interfejsu dla aplikacji QuizMe. <br />
Aby utworzyć interfejs, najpierw załaduj do projektu pobrane zdjęcia. Kliknij przycisk Prześlij plik (Upload File...) w obszarze Media i wybierz jeden z pobranych wcześniej plików (np. Larsenberra.jpg). Następnie zrób to samo z pozostałymi trzema zdjęciami.<br />
Utwórz następujące komponenty, przeciągając je z Palety (Palette) do Przeglądarki (Viewer) i ustaw właściwości komponentów zgodnie z poniższym opisem:<br />
{|class="wikitable"<br />
! Typ komponentu<br />
! Kategoria<br />
! Jaką nadać jej nazwę<br />
! Działanie<br />
! Działanie komponentu<br />
|-<br />
|Image<br />
|User interface<br />
|Image1<br />
|Ustaw właściwość zdjęcia (Picture) na Larsenberra.jpg. Jest to pierwsze wyświetlane zdjęcie.<br />
|Obrazkowa część pytania<br />
|-<br />
|Label<br />
|User interface<br />
|QuestionLabel<br />
|Zmień właściwość tekstu (Text) na Pytanie:<br />
|Wyświetla bieżące pytanie<br />
|-<br />
|HorizontalArrangement<br />
|Layout<br />
|HorizontalArrangement1<br />
| <br />
|Organizuje komponenty AnswerPrompt i Text (podaj odpowiedź i tekst)<br />
|-<br />
|Label<br />
|User interface<br />
|AnswerPromptLabel<br />
|Zmień właściwość tekstu (Text) na Podaj odpowiedź:. Na ekranie przeglądarki przesuń tę etykietę do HorizontalArrangement1.<br />
|Wyświetla tekst prośby o odpowiedź.<br />
|-<br />
|TextBox<br />
|User interface<br />
|AnswerText<br />
|Zmień wskazówkę (Hint) na Podaj odpowiedź. Na ekranie przeglądarki przenieś AnswerText do komponentu HorizontalArrangement1.<br />
|Tutaj użytkownik podaje odpowiedź.<br />
|-<br />
|Label<br />
|User interface <br />
|RightWrongLabel<br />
|Zmień właściwość tekstu (Text) na Dobrze/Źle.<br />
|Tutaj wyświetlana jest ocena Dobrze/Źle.<br />
|-<br />
|HorizontalArrangement<br />
|Layout<br />
|HorizontalArrangement2<br />
|<br />
|Organizuje przyciski AnswerButton i NextButton (przycisk odpowiedzi i przycisk dalej).<br />
|-<br />
|Przycisk<br />
|User interface<br />
|AnswerButton<br />
|Zmień właściwość tekstu (Text) na Wyślij. Na ekranie przeglądarki przesuń ten przycisk do HorizontalArrangment2.<br />
|Użytkownik klika, aby przesłać odpowiedź.<br />
|-<br />
|Przycisk<br />
|User interface<br />
|NextButton<br />
|Zmień właściwość tekstu (Text) na Dalej. Przenieś ten przycisk do HorizontalArrangement2.<br />
|Użytkownik klika, aby przejść do następnego pytania.<br />
|} <br />
Po zakończeniu powinien on wyglądać jak poniższa ilustracja (pod nią znajdują się również bardziej szczegółowe informacje).<br />
[[Plik:t6-2.png]]<br />
<br />
==Programowanie aplikacji==<br />
Otwórz Edytor bloków, aby zaprogramować działanie komponentów. Najpierw zdefiniuj dwie zmienne - listy: zmienną QuestionList, zawierającą listę pytań i zmienną AnswerList z listą odpowiedzi na te pytania.<br />
<br />
Aby zdefiniować te dwie zmienne listy, potrzebujesz następujących bloków:<br />
{| class="wikitable"<br />
!Typ bloku<br />
!Kategoria<br />
!Działanie<br />
|-<br />
|initialize global name to<br />
|Variables<br />
|Definiuje zmienną QuestionList (zmień jej nazwę)<br />
|-<br />
|initialize global name to<br />
|Variables<br />
|Definiuje zmienną AnswerList (zmień jej nazwę)<br />
|-<br />
|make a list<br />
|Lists<br />
|Służy do dodawania elementów do zmiennej QuestionList<br />
|-<br />
|„ „ (trzykrotnie)<br />
|Lists<br />
|Służy do wpisania pytań<br />
|-<br />
|make a list<br />
|Lists<br />
|Służy do dodawania elementów do zmiennej AnswerList<br />
|-<br />
|„ „ (trzykrotnie)<br />
|Text<br />
|Służy do wpisania odpowiedzi<br />
|}<br />
Utwórz zmienne całościowe, przeciągając z kategorii zmiennych (Variables) na obszar roboczy blok Initialize global name to. Kliknij dwukrotnie domyślną nazwę name, aby ją zmienić. Blok Initialize global name to zawiera pole na początkową wartość zmiennej. Zmienna może zawierać liczbę, tekst, a nawet listę – aby ją utworzyć, podłącz blok Make a list do definicji zmiennej.<br />
<br />
Bloki powinny wyglądać następująco:<br />
<br />
[[Plik:t6-3.png]]<br />
===Zdefiniuj ukrytą zmienną Index===<br />
Za każdym razem, gdy użytkownik kliknie przycisk NextButton, aby przejść dalej, aplikacja musi pamiętać, przy którym pytaniu jest obecnie gracz. W języku programowania, aby coś zapamiętać, trzeba zdefiniować nową zmienną. W tym przypadku aplikacja musi zapamiętać bieżący numer pytania – indeks listy QuestionList.<br />
Aby zdefiniować zmienną currentQuestionIndex, potrzebujesz następujących bloków:<br />
{| class="wikitable"<br />
!Typ bloku<br />
!Kategoria<br />
!Działanie<br />
|-<br />
|initialize global name to<br />
|Variables<br />
|Definiuje zmienną currentQuestionIndex (zmień nazwę)<br />
|-<br />
|0 (1)<br />
|Math<br />
|Ustaw wartość początkową currentQuestionIndex na 1 (zmień liczbę)<br />
|}<br />
Bloki powinny wyglądać następująco:<br />
<br />
[[Plik:t6-4.png]]<br />
<br />
===Wyświetl pierwsze pytanie===<br />
Odłóż na razie kwestię odpowiedzi i skup się na zaprogramowaniu sekwencyjnego przejścia przez pytania. Pożądane zachowanie jest następujące: po uruchomieniu aplikacji na etykiecie o nazwie QuestionLabel pojawia się pierwsze pytanie. Gdy użytkownik kliknie NextButton, wyświetlone zostaje drugie pytanie. Po ponownym kliknięciu pojawia się trzecie pytanie. Po dotarciu do ostatniego pytania kliknięcie przycisku NextButton powoduje ponowne pojawienie się pierwszego pytania w etykiecie QuestionLabel.<br />
<br />
W programie App Inventor określone pozycje na liście są wybierane za pomocą bloku select list item. W tym bloku trzeba podać listę i indeks – pozycję na liście. Jeżeli na liście są trzy pozycje, prawidłowe indeksy to 1, 2 i 3.<br />
<br />
Po uruchomieniu aplikacja QuizMe powinna wybrać pierwsze pytanie z listy i wyświetlić je w komponencie QuestionLabel. Do tego zachowania inicjalizującego działanie aplikacji potrzebne są następujące bloki:<br />
<br />
{| class="wikitable"<br />
!Typ bloku<br />
!Kategoria<br />
!Działanie<br />
|-<br />
|when Screen1.Initialize<br />
|Screen1<br />
|Podczas uruchamiania aplikacji zainicjowana jest ta obsługa zdarzenia<br />
|-<br />
|set QuestionLabel.Text to<br />
|QuestionLabel<br />
|Umieszcza pierwsze pytanie w etykiecie QuestionLabel<br />
|-<br />
|select list item<br />
|Lists<br />
|Wybiera pierwsze pytanie z etykiety QuestionLabel<br />
|-<br />
|get <br />
|Variables<br />
|Ustala listę, z której jest wybierany element. Tutaj: Global QuestionList<br />
|-<br />
|0 (1)<br />
|Math<br />
|Wybiera pierwsze pytanie za pomocą indeksu 1. Ustaw wartość na 1.<br />
|}<br />
Bloki powinny wyglądać następująco:<br />
<br />
[[Plik:t6-5.png]]<br />
<br />
===Jak działają bloki?===<br />
Zdarzenie when Screen1.Initialize jest wyzwalane podczas uruchomienia aplikacji. Pierwsza pozycja zmiennej QuestionList zostaje wybrana i umieszczona w bloku set QuestionLabel.Text. Gdy aplikacja zostanie uruchomiona, użytkownik zobaczy pierwsze pytanie.<br />
===Przetestuj to zachowanie===<br />
Jeśli dotychczas nie skomunikowałeś urządzenia mobilnego z programem, zrób to teraz. Co pojawia się na urządzeniu? Jeżeli utworzono listę QuestionList tak, jak wskazano powyżej, w etykiecie QuestionLabel powinna pojawić się pierwsza pozycja tej listy (Kto był doskonałym miotaczem w World Series?).<br />
<br />
==Iteracja pytań==<br />
Zdefiniowałeś już zmienną CurrentQuestionIndex, zapamiętującą pytanie, przy którym znajduje się użytkownik. Zaprogramuj teraz zachowanie przycisku NextButton. Gdy zostanie on kliknięty, aplikacja zwiększy wartość zmiennej, np. zmieni ją z 1 na 2 lub z 2 na 3 itd., a następnie użyje tej wartości do zaznaczenia nowego bieżącego pytania. Do tego zachowania potrzebne są następujące bloki:<br />
{| class="wikitable"<br />
!Typ bloku<br />
!Kategoria<br />
!Działanie<br />
|-<br />
|when NextButton.Click<br />
|NextButton<br />
|Uruchamia obsługę zdarzeń po kliknięciu przycisku<br />
|-<br />
|set currentQuestionIndex to<br />
|Zmienne<br />
|Decyduje o ustawieniu indeksu wybranej listy<br />
|-<br />
|+ <br />
|Math<br />
|Służy do zwiększania wartości zmiennej currentQuestionIndex<br />
|-<br />
|get global currentQuestionIndex<br />
|Zmienne<br />
|Tworzy nową wartość poprzez zwiększenie poprzedniej wartości o 1<br />
|-<br />
|0 (1)<br />
|Math<br />
|Dla + 1<br />
|-<br />
|set QuestionLabel.Text to<br />
|QuestionLabel<br />
|Wyświetla kolejne pytanie<br />
|-<br />
|select list item<br />
|Listy<br />
|Ustawia element listy jako wartość QuestionLabel<br />
|-<br />
|get global QuestionList<br />
|Zmienne<br />
|Wskazuje, która lista będzie wybrana<br />
|-<br />
|get global currentQuestionIndex<br />
|Zmienne<br />
|Wskazuje, który element wybranej listy będzie wybrany<br />
|}<br />
Bloki powinny wyglądać następująco:<br />
<br />
[[Plik:t6-6.png]]<br />
<br />
===Jak działają bloki?===<br />
Pierwszy wiersz polecenia zwiększa wartość zmiennej currentQuestionIndex o 1 (jeżeli zmienna zawiera wartość 1, zostaje ona zmieniona na 2, z 2 na 3 itd.). Następnie wykorzystuje nową wartość do wyboru pytania o tym indeksie.<br />
<br />
Przypomnijmy, że w bloku obsługi zdarzeń Screen.Initialize aplikacja wybrała pierwsze do wyświetlenia pytanie:<br />
<br />
[[Plik:t6-7.png]]<br />
<br />
Po kliknięciu przycisku NextButton aplikacja nie wybiera konkretnie pierwszej, drugiej czy trzeciej pozycji na liście, tylko pozycję o n-tej wartości zmiennej currentQuestionIndex.<br />
<br />
[[Plik:t6-8.png]]<br />
<br />
Polecenia w blokach są wykonywane od prawej do lewej, tzn. aplikacja najpierw określa wartość parametru z bloku Select list item, którym jest zmienna CurrentQuestionIndex. Liczba zawarta w tej zmiennej zostaje użyta jako indeks podczas wykonania poleceń zawartych w bloku Select list item.<br />
<br />
[[Plik:info.png|left]]''Po pierwszym kliknięciu przycisku NextButton, wartość zmiennej currentQuestionIndex przeskoczy z 1 na 2, aby aplikacja wybrała drugą pozycję z listy QuestionList (Kto był pierwszym doskonałym miotaczem w 2010?). Po drugim kliknięciu przycisku NextButton, wartość zmiennej currentQuestionIndex zostanie zmieniona z 2 na 3, a aplikacja wybierze trzecie pytanie z listy (Kto był pierwszym doskonałym miotaczem nowej ery?).''<br />
<br />
===Przetestuj to zachowanie===<br />
Przetestuj zachowanie przycisku NextButton, aby sprawdzić, czy aplikacja działa poprawnie. Wciel się w rolę użytkownika i kliknij przycisk NextButton w telefonie. Czy urządzenie wyświetliło drugie pytanie: Kto był pierwszym doskonałym miotaczem w 2010?? Trzecie pytanie powinno pojawić się po kolejnym kliknięciu przycisku. Jeżeli aplikacja działa, pogratuluj sobie i przejdź dalej. Kliknij przycisk NextButton ponownie (po raz trzeci). Powinien zostać wyświetlony błąd: Próba uzyskania elementu 4 z listy o długości 3. Czy wiesz, na czym polega problem?<br />
<br />
Problem z aplikacją polega na tym, że zawsze po kliknięciu przycisku NextButton zwiększa ona zmienną CurrentQuestionIndex o 1. Gdy wartość zmiennej wynosi już 3, a użytkownik kolejny raz kliknie przycisk NextButton, aplikacja zmieni wartość zmiennej z 3 na 4, następnie wywoła blok Select list item, aby odczytać pozycję o aktualnym indeksie CurrentQuestionIndex, czyli w tym przypadku czwartą pozycję. Ponieważ zmienna QuestionList zawiera tylko trzy elementy, Android wykaże błąd.<br />
<br />
Aplikacja musi zadawać pytanie - sprawdzać warunek - gdy nastąpi kliknięcie przycisku NextButton i realizować polecenia zawarte w różnych blokach w zależności od odpowiedzi. Elementem do sprawdzenia jest to, czy zmienna CurrentQuestionIndex już ma wartość 3. Jeżeli tak - należy ustawić CurrentQuestionIndex z powrotem na 0, aby użytkownik wrócił do pierwszego pytania.<br />
<br />
Będziesz potrzebował następujących bloków:<br />
{| class="wikitable"<br />
!Typ bloku<br />
!Kategoria<br />
!Działanie<br />
|-<br />
|if then<br />
|Control<br />
|sprawdzenie, czy użytkownik jest na etapie ostatniego pytania<br />
|-<br />
|= <br />
|Math<br />
|sprawdzenie, czy currentQuestionIndex ma wartość 3<br />
|-<br />
|get global currentQuestionIndex<br />
|Variables<br />
|<br />
|-<br />
|0 (3)<br />
|Math<br />
|3 to numer na liście<br />
|-<br />
|set currentQuestionIndex to<br />
|Variables<br />
|ustawienie na 0, aby wrócić do pierwszego pytania<br />
|-<br />
|0<br />
|Math<br />
|ustawienie na 0, ponieważ kolejne bloki zwiększą wartość do 1<br />
|}<br />
Zmodyfikowany blok obsługi zdarzenia When NextButton.Click powinien wyglądać następująco:<br />
<br />
[[Plik:t6-9.png]]<br />
<br />
===Jak działają bloki===<br />
Po kliknięciu przycisku NextButton aplikacja najpierw sprawdza, czy currentQuestionIndex ma wartość 3. Jeżeli tak, wartość tej zmiennej jest ustawiana na 0, aby po zwiększeniu jej w dalszych krokach jej wartość wyniosła 1. Wtedy quiz wróci do pierwszego pytania. Zauważ, że tylko bloki osadzone w bloku if-then są zależne od warunku. Blok zwiększenia wartości i blok Set QuestionLabel.Text to są wykonywane bez względu na jakikolwiek warunek.<br />
<br />
==Aplikacja modyfikowalna: Ułatwianie modyfikowania pytań==<br />
Teraz zmodyfikujemy aplikację, aby można było łatwo dodawać i usuwać elementy z listy. Zmień bloki tak, aby działały na liście o dowolnej długości, a nie tylko liście z dokładnie trzema pozycjami. <br />
Na początek dodaj czwarte pytanie do zmiennej QuestionList i kolejną odpowiedź do AnswerList. W tym celu musisz najpierw zwiększyć liczbę dostępnych pól za pomocą przycisku modyfikującego (mutatora). Aby dowiedzieć się więcej o tym elemencie, zobacz: http://appinventor.mit.edu/explore/ai2/support/concepts/mutators. Bloki powinny wyglądać następująco:<br />
<br />
===Przetestuj zmodyfikowaną aplikację.===<br />
Kliknij przycisk NextButton kilka razy. Zauważysz, że czwarte pytanie nigdy się nie pojawia, bez względu na to, ile razy klikniesz przycisk.<br />
<br />
Problemem jest to, że test sprawdzający, czy użytkownik znajduje się przy ostatnim pytaniu, jest zbyt szczegółowy: pyta, czy zmienna CurrentQuestionIndex ma wartość 3:<br />
<br />
Możesz po prostu zmienić liczbę z 3 na 4, a aplikacja będzie znów działać poprawnie. Problem polega jednak na tym, że za każdym razem, gdy zmodyfikujesz liczbę pytań i odpowiedzi, będziesz musiał pamiętać, aby dokonać także tej zmiany. Takie zależności w programie komputerowym często prowadzą do błędów, w szczególności gdy aplikacja staje się bardziej złożona. Znacznie lepiej jest przygotować program w taki sposób, aby działał niezależnie od liczby pytań. Takie uogólnienie jest jeszcze ważniejsze, gdy lista, z którą pracujesz, zmienia się dynamicznie, na przykład w aplikacji z quizem, gdzie użytkownik może dodawać nowe pytania.<br />
<br />
Lepszym rozwiązaniem jest sprawdzenie warunku w sposób bardziej ogólny. Tak naprawdę chcesz wiedzieć, czy bieżące pytanie – czyli wartość zmiennej currentQuestionIndex jest tak duża, jak ilość elementów w zmiennej QuestionList. Jeżeli aplikacja sprawdzi warunek w bardziej ogólny sposób, to będzie działać, nawet jeżeli dodasz lub usuniesz elementy ze zmiennej QuestionList. Aby zmienić blok obsługi zdarzenia When NextButton.Click, zmień poprzedni test sprawdzający, który odnosił się bezpośrednio do 3. Będziesz potrzebował następujących bloków:<br />
{| class="wikitable"<br />
!Typ bloku<br />
!Szuflada<br />
!Działanie<br />
|-<br />
|length of list<br />
|Lists<br />
|Pyta, ile elementów jest w zmiennej QuestionList<br />
|-<br />
|get global QuestionList<br />
|Variables<br />
|Określa, o którą listę chodzi<br />
|}<br />
Blok obsługi zdarzenia When NextButton.Click powinien teraz wyglądać następująco:<br />
<br />
<br />
===Jak działają bloki?===<br />
Warunek if porównuje teraz wartość zmiennej CurrentQuestionIndex z długością zmiennej QuestionList. Zatem jeżeli zmienna CurrentQuestionIndex ma wartość 4, a długość zmiennej QuestionList wynosi 4, to wartość zmiennej currentQuestionIndex zostanie ustawiona na 0 (a następnie na 1, 2 itd.). Zauważ - bloki nie odwołują się już do 3 ani żadnej innej określonej wartości, dlatego instrukcja będzie działać bez względu na liczbę elementów listy.<br />
<br />
Przetestuj zmodyfikowane zachowanie. Czy po kliknięciu przycisku NextButton aplikacja przechodzi teraz przez cztery pytania, wracając po ostatnim do pierwszego?<br />
<br />
==Przełączanie zdjęcia dla każdego pytania==<br />
Na razie aplikacja wyświetla to samo zdjęcie, bez względu na to, jakie pytanie zostaje zadane. Możesz to zmienić tak, aby po kliknięciu przycisku NextButton pojawiała się fotografia dotycząca danego pytania. W obszarze Media dostępne są cztery dodane wcześniej zdjęcia. Teraz utworzymy trzecią listę - PictureList, której elementami będą nazwy plików zdjęć, a następnie zmodyfikujemy blok obsługi zdarzenia When NextButton.Click, aby program po każdym pytaniu przełączał zdjęcie.<br />
Najpierw utwórz listę PictureList i zainicjuj ją nazwami plików graficznych. Upewnij się, czy nazwy są dokładnie takie same jak nazwy plików, które zostały załadowane do obszaru Media. Oto jak powinien wyglądać blok dla listy PictureList:<br />
<br />
Następnie zmodyfikuj blok obsługi zdarzeń When NextButton.Click, aby zmieniał wyświetlane zdjęcie w zależności od zadanego pytania. Jeżeli ustawisz właściwość Image.Picture na nazwę pliku zdjęcia, które zostało załadowane, właśnie ta fotografia zostanie wyświetlona. Aby zmodyfikować blok When NextButton.Click, potrzebujesz następujących bloków:<br />
{| class="wikitable"<br />
!Typ bloku<br />
!Kategoria<br />
!Działanie<br />
|-<br />
|set Image1.Picture to<br />
|Image1<br />
|ustaw, aby zmieniać zdjęcie<br />
|-<br />
|select list item<br />
|Lists<br />
|należy wybrać zdjęcie odpowiadające na aktualne pytanie<br />
|-<br />
|get global PictureList<br />
|Variables<br />
|wybierz nazwę pliku z tej listy<br />
|-<br />
|get global currentQuestionIndex<br />
|Variables<br />
|wybierz element o n-tym indeksie currentQuestionIndex<br />
|}<br />
Oto jak powinny wyglądać bloki:<br />
<br />
===Jak działają bloki?===<br />
Zmienna CurrentQuestionIndex służy jako indeks dla zmiennej QuestionList. Wartość CurrentQuestionIndex wynosi 1, aplikacja wybiera pierwsze pytanie i pierwsze zdjęcie. Gdy CurrentQuestionIndex wynosi 2, aplikacja wybiera drugie pytanie i drugie zdjęcie. Oczywiście takie działanie zależy od tego, czy listy są ze sobą zsynchronizowane. Tak jest w tym przypadku - pierwszy obraz - LarsenBerra.jpg to zdjęcie Dona Larsena, jednocześnie Don Larsen to odpowiedź na pierwsze pytanie (Kto był doskonałym miotaczem w World Series?). <br />
Przetestuj zmodyfikowane zachowanie. Czy nowe zdjęcie pojawia się po każdym kliknięciu przycisku NextButton?<br />
<br />
==Ocena udzielanych odpowiedzi==<br />
Teraz dodamy bloki, które określają, czy użytkownik odpowiedział na pytanie prawidłowo, czy też nie. Gracz wprowadza odpowiedź do AnswerText, a następnie klika przycisk AnswerButton. Aplikacja musi porównać wpis użytkownika z odpowiedzią na bieżące pytanie, używając bloku if... then... w celu jej sprawdzenia. Etykieta RightWrongLabel powinna być modyfikowana, aby podawać, czy odpowiedź jest prawidłowa, czy nie.<br />
<br />
Do tego zachowania będą potrzebne następujące bloki:<br />
{| class="wikitable"<br />
!Typ bloku<br />
!Kategoria<br />
!Działanie<br />
|-<br />
|when AnswerButton.Click<br />
|AnswerButton<br />
|zachowanie jest wyzwalane, gdy użytkownik kliknie przycisk AnswerButton<br />
|-<br />
|if... then...<br />
|Control<br />
|Użyj mutatora, aby dodać alternatywę (else). Jeżeli odpowiedź jest prawidłowa - zrób jedno, w przeciwnym razie (else) - zrób coś innego<br />
|-<br />
|= <br />
|Math<br />
|sprawdzenie, czy odpowiedź jest prawidłowa<br />
|-<br />
|AnswerText.Text<br />
|AnswerText<br />
|Odpowiedź użytkownika pojawia się w tym polu tekstowym<br />
|-<br />
|select list item<br />
|Lists<br />
|wybrać bieżącą odpowiedź z listy AnswerList<br />
|-<br />
|get global AnswerList<br />
|Variables<br />
|lista, z której jest wybierany element<br />
|-<br />
|get global currentQuestionIndex<br />
|Variables<br />
|numer pytania (i numer odpowiedzi), przy którym jest użytkownik<br />
|-<br />
|set RightWrongLabel.Text to<br />
|RightWrongLabel<br />
|tutaj podaj odpowiedź<br />
|-<br />
|Dobrze!<br />
|Text<br />
|jeżeli odpowiedź jest prawidłowa<br />
|-<br />
|set RightWrongLabel.Text to<br />
|RightWrongLabel<br />
|tutaj podaj odpowiedź<br />
|-<br />
|Źle<br />
|Text<br />
|jeżeli odpowiedź jest nieprawidłowa<br />
|}<br />
Bloki powinny wyglądać następująco:<br />
<br />
===Jak działają bloki?===<br />
Test if sprawdza, czy odpowiedź użytkownika (AnswerText.Text) jest taka sama, jak element na liście AnswerList o indeksie równym wartości zmiennej CurrentQuestionIndex. Jeżeli zmienna CurrentQuestionIndex ma wartość 1, aplikacja porównuje odpowiedź użytkownika z pierwszą pozycją na liście AnswerList, (Don Larsen). Jeżeli zmienna CurrentQuestionIndex zmieni wartość na 2, program zestawia odpowiedź z drugą pozycją na liście, czyli Dallas Branden. Jeśli wynik porównania jest pozytywny, przeprowadzane są bloki then, a treść etykiety RightWrongLabel zostaje ustawiona na Dobrze!. Jeżeli wynik testu jest negatywny (fałszywy), przeprowadzane są bloki alternatywy (else), a treść etykiety RightWrongLabel zostaje ustawiona na Źle.<br />
<br />
Przetestuj zmodyfikowaną aplikację. Spróbuj odpowiedzieć na jedno z pytań. Powinna pojawić się ocena, czy odpowiedź była dokładnie taka sama, jak na liście AnswerList. Sprawdź zarówno prawidłowe, jak i nieprawidłowe odpowiedzi (Uwaga - uwzględniana jest wielkość liter!). Kliknij przycisk NextButton i odpowiedz na drugie pytanie. Czy aplikacja nadal działa? Powinna, ale zauważ, że gdy klikniesz przycisk NextButton, tekst Dobrze! lub Źle oraz poprzednia odpowiedź nadal będą wyświetlane. Choć nie wpływa to zasadniczo na naszą grę, to takie szczegóły interfejsu z pewnością zostaną zauważone przez użytkowników Twojej aplikacji.<br />
<br />
Aby wyzerować etykietę RightWrongLabel i AnswerText, umieść poniższe bloki w bloku obsługi zdarzeń When NextButton.click:<br />
{| class="wikitable"<br />
!Typ bloku<br />
!Kategoria<br />
!Działanie<br />
|-<br />
|set RightWrongLabel.Text to<br />
|RightWrongLabel<br />
|Ustawia wartość etykiety na…<br />
|-<br />
|„ „<br />
|Text<br />
|pusty tekst<br />
|-<br />
|set AnswerText.Text to<br />
|AnswerText<br />
|Ustawia wartość etykiety na…<br />
|-<br />
|„ „<br />
|Text<br />
|pusty tekst<br />
|}<br />
Bloki powinny wyglądać następująco:<br />
<br />
===Jak działają bloki?===<br />
Po kliknięciu przycisku NextButton użytkownik przechodzi do następnego pytania, dlatego początkowe wiersze bloku obsługi zdarzeń zerują etykietę RightWrongLabel i pole AnswerText.<br />
Przetestuj to zachowanie Odpowiedz na pytanie i kliknij przycisk Wyślij, a następnie - NextButton. Czy Twoja poprzednia odpowiedź i jej ocena zniknęły?<br />
<br />
==Ostateczna postać programu==<br />
Oto gotowa aplikacja QuizMe:<br />
<br />
Utwórz wykonywalną wersję aplikacji, wybierając menu Build/App (provide QR code for .apk). Gdy pojawi się kod kreskowy, użyj czytnika kodów w telefonie, aby pobrać i zainstalować aplikację.<br />
<br />
===Modyfikacje===<br />
Quiz w tej wersji jest już gotowy. Czy masz ochotę przemyśleć pewne zmiany?<br />
<br />
Zamiast wyświetlać zdjęcie dla każdego pytania, spróbuj odtworzyć dźwięk lub krótkie wideo. Za pomocą dźwięku możesz zmienić quiz w aplikację Jaka to melodia?.<br />
<br />
Quiz akceptuje ściśle określone odpowiedzi. Jeśli gracz odpowiedziałby, lekko przekształcając tekst (np. podając inicjał zamiast imienia), program uzna to za błąd. Można to zmienić na kilka różnych sposobów. Jednym z nich jest użycie bloku text.contains, aby sprawdzić, czy odpowiedź użytkownika zawiera prawidłową odpowiedź. Inny sposób to dostarczenie wielu odpowiedzi na każde pytanie i sprawdzenie przez iterację (użycie bloku for each), czy któraś z nich pasuje.<br />
<br />
Przekształć quiz tak, aby przedstawiał odpowiedzi do wyboru. Lista odpowiedzi będzie musiała być listą list, a każda podrzędna lista będzie musiała zawierać opcje odpowiedzi. Użyj komponentu ListPicker, aby umożliwić użytkownikowi wybranie odpowiedzi.<br />
<br />
<br />
==Podsumowanie==<br />
Oto niektóre koncepcje omówione w tym przewodniku:<br />
<ul><li>Aplikacje można tworzyć w sposób ogólny, aby pracować z dowolną listą danych.</li><br />
<li>Zmienne indeksu są wykorzystywane do śledzenia bieżącej pozycji na liście. Zwiększając wartość zmiennej indeksu, należy uważać na przekroczenie końca listy.</li></ul><br />
<br />
==Zeskanuj próbną aplikację do telefonu==<br />
Aby zainstalować i uruchomić aplikację próbną, zeskanuj poniższy kod kreskowy:<br />
<br />
==Pobierz kod źródłowy==<br />
Jeżeli chcesz pracować z tą próbką w programie App Inventor:<br />
<ul><li>pobierz na komputer kod źródłowy: [http://appinventor.mit.edu/explore/sites/all/files/ai2tutorials/QuizMe/QuizMe_MIT.aia http://appinventor.mit.edu/explore/sites/all/files/ai2tutorials/QuizMe/QuizMe_MIT.aia]</li><br />
<li>otwórz program App Inventor,</li><br />
<li>kliknij opcję My Projects,</li><br />
<li>wybierz Import project (.aia) from my computer...</li><br />
<li>znajdź i zatwierdź pobrany kod źródłowy.</li></ul></div>M Kelniarzhttp://wiki.mistrzowiekodowania.pl/index.php?title=QuizMeQuizMe2015-03-15T18:31:59Z<p>M Kelniarz: /* Iteracja pytań */</p>
<hr />
<div>=Aplikacja QuizMe dla App Inventor 2=<br />
<br />
==Co tworzysz?==<br />
[[Plik:t6-1.png|right]]QuizMe to gra dotycząca ciekawostek baseballowych, ale można jej użyć jako szablonu do tworzenia quizów z dowolnej dziedziny. W aplikacji użytkownik odpowiada na szereg pytań, otrzymując następnie informację zwrotną, czy udzielił poprawnej, czy błędnej odpowiedzi. Gracz przechodzi do kolejnego pytania, klikając przycisk.<br />
<br />
W grze QuizMe dysponujemy zamkniętym zbiorem pytań, chyba że programista je zmieni. W następnym etapie można utworzyć MakeQuiz & TakeQuiz – aplikację, która pozwala użytkownikom na tworzenie i modyfikowanie pytań.<br />
<br />
Poradnik ten zakłada, że znasz już podstawy tworzenia aplikacji w App Inventorze – korzystanie z Projektanta komponentów w celu utworzenia interfejsu użytkownika i z Edytora bloków, aby określić obsługę zdarzeń. Jeżeli potrzebujesz przypomnienia, spróbuj popracować z poradnikami podstawowymi zanim przejdziesz dalej.<br />
<br />
==Zaczynamy!==<br />
Połącz się z witryną internetową App Inventor i załóż nowy projekt. Nazwij go QuizMe, ustaw taki sam tytuł ekranu (Title). Za pomocą MIT AI2 Companion połącz program z urządzeniem mobilnym. Pobierz poniższe zdjęcia baseballistów i zapisz je w komputerze. Później załadujesz je do projektu.<br />
<ul><li> [http://beta.appinventor.mit.edu/learn/tutorials/quizme/QuizMeAssets/Larsenberra.jpg Larsenberra.jpg]</li><br />
<li> [http://beta.appinventor.mit.edu/learn/tutorials/quizme/QuizMeAssets/dallasbraden.jpg Dallasbraden.jpg]</li><br />
<li> [http://beta.appinventor.mit.edu/learn/tutorials/quizme/QuizMeAssets/cyyoung.jpg Cyyoung.jpg]</li><br />
<li> [http://beta.appinventor.mit.edu/learn/tutorials/quizme/QuizMeAssets/nolanryan.jpg Nolanryan.jpg]</li></ul><br />
<br />
==Wstęp==<br />
Zaprojektujesz grę typu quiz, w której użytkownik będzie przechodził do kolejnych pytań, klikając przycisk Dalej, a następnie otrzymywał prostą ocenę Dobrze/Źle dla każdej odpowiedzi.<br />
<br />
W tym przewodniku omówimy:<br />
<ul><li>definiowanie i wyświetlanie listy informacji;</li><br />
<li>przechodzenie przez listę za pomocą zmiennej indeksującej – zmiennej, która śledzi pozycję na liście;</li><br />
<li>zachowania warunkowe – wykonywanie określonych operacji tylko wtedy, gdy spełniony jest określony warunek;</li><br />
<li>Zmianę zdjęcia w zależności od sytuacji.</li></ul><br />
<br />
==Projektowanie aplikacji==<br />
Użyj Projektanta komponentów do utworzenia interfejsu dla aplikacji QuizMe. <br />
Aby utworzyć interfejs, najpierw załaduj do projektu pobrane zdjęcia. Kliknij przycisk Prześlij plik (Upload File...) w obszarze Media i wybierz jeden z pobranych wcześniej plików (np. Larsenberra.jpg). Następnie zrób to samo z pozostałymi trzema zdjęciami.<br />
Utwórz następujące komponenty, przeciągając je z Palety (Palette) do Przeglądarki (Viewer) i ustaw właściwości komponentów zgodnie z poniższym opisem:<br />
{|class="wikitable"<br />
! Typ komponentu<br />
! Kategoria<br />
! Jaką nadać jej nazwę<br />
! Działanie<br />
! Działanie komponentu<br />
|-<br />
|Image<br />
|User interface<br />
|Image1<br />
|Ustaw właściwość zdjęcia (Picture) na Larsenberra.jpg. Jest to pierwsze wyświetlane zdjęcie.<br />
|Obrazkowa część pytania<br />
|-<br />
|Label<br />
|User interface<br />
|QuestionLabel<br />
|Zmień właściwość tekstu (Text) na Pytanie:<br />
|Wyświetla bieżące pytanie<br />
|-<br />
|HorizontalArrangement<br />
|Layout<br />
|HorizontalArrangement1<br />
| <br />
|Organizuje komponenty AnswerPrompt i Text (podaj odpowiedź i tekst)<br />
|-<br />
|Label<br />
|User interface<br />
|AnswerPromptLabel<br />
|Zmień właściwość tekstu (Text) na Podaj odpowiedź:. Na ekranie przeglądarki przesuń tę etykietę do HorizontalArrangement1.<br />
|Wyświetla tekst prośby o odpowiedź.<br />
|-<br />
|TextBox<br />
|User interface<br />
|AnswerText<br />
|Zmień wskazówkę (Hint) na Podaj odpowiedź. Na ekranie przeglądarki przenieś AnswerText do komponentu HorizontalArrangement1.<br />
|Tutaj użytkownik podaje odpowiedź.<br />
|-<br />
|Label<br />
|User interface <br />
|RightWrongLabel<br />
|Zmień właściwość tekstu (Text) na Dobrze/Źle.<br />
|Tutaj wyświetlana jest ocena Dobrze/Źle.<br />
|-<br />
|HorizontalArrangement<br />
|Layout<br />
|HorizontalArrangement2<br />
|<br />
|Organizuje przyciski AnswerButton i NextButton (przycisk odpowiedzi i przycisk dalej).<br />
|-<br />
|Przycisk<br />
|User interface<br />
|AnswerButton<br />
|Zmień właściwość tekstu (Text) na Wyślij. Na ekranie przeglądarki przesuń ten przycisk do HorizontalArrangment2.<br />
|Użytkownik klika, aby przesłać odpowiedź.<br />
|-<br />
|Przycisk<br />
|User interface<br />
|NextButton<br />
|Zmień właściwość tekstu (Text) na Dalej. Przenieś ten przycisk do HorizontalArrangement2.<br />
|Użytkownik klika, aby przejść do następnego pytania.<br />
|} <br />
Po zakończeniu powinien on wyglądać jak poniższa ilustracja (pod nią znajdują się również bardziej szczegółowe informacje).<br />
[[Plik:t6-2.png]]<br />
<br />
==Programowanie aplikacji==<br />
Otwórz Edytor bloków, aby zaprogramować działanie komponentów. Najpierw zdefiniuj dwie zmienne - listy: zmienną QuestionList, zawierającą listę pytań i zmienną AnswerList z listą odpowiedzi na te pytania.<br />
<br />
Aby zdefiniować te dwie zmienne listy, potrzebujesz następujących bloków:<br />
{| class="wikitable"<br />
!Typ bloku<br />
!Kategoria<br />
!Działanie<br />
|-<br />
|initialize global name to<br />
|Variables<br />
|Definiuje zmienną QuestionList (zmień jej nazwę)<br />
|-<br />
|initialize global name to<br />
|Variables<br />
|Definiuje zmienną AnswerList (zmień jej nazwę)<br />
|-<br />
|make a list<br />
|Lists<br />
|Służy do dodawania elementów do zmiennej QuestionList<br />
|-<br />
|„ „ (trzykrotnie)<br />
|Lists<br />
|Służy do wpisania pytań<br />
|-<br />
|make a list<br />
|Lists<br />
|Służy do dodawania elementów do zmiennej AnswerList<br />
|-<br />
|„ „ (trzykrotnie)<br />
|Text<br />
|Służy do wpisania odpowiedzi<br />
|}<br />
Utwórz zmienne całościowe, przeciągając z kategorii zmiennych (Variables) na obszar roboczy blok Initialize global name to. Kliknij dwukrotnie domyślną nazwę name, aby ją zmienić. Blok Initialize global name to zawiera pole na początkową wartość zmiennej. Zmienna może zawierać liczbę, tekst, a nawet listę – aby ją utworzyć, podłącz blok Make a list do definicji zmiennej.<br />
<br />
Bloki powinny wyglądać następująco:<br />
<br />
[[Plik:t6-3.png]]<br />
===Zdefiniuj ukrytą zmienną Index===<br />
Za każdym razem, gdy użytkownik kliknie przycisk NextButton, aby przejść dalej, aplikacja musi pamiętać, przy którym pytaniu jest obecnie gracz. W języku programowania, aby coś zapamiętać, trzeba zdefiniować nową zmienną. W tym przypadku aplikacja musi zapamiętać bieżący numer pytania – indeks listy QuestionList.<br />
Aby zdefiniować zmienną currentQuestionIndex, potrzebujesz następujących bloków:<br />
{| class="wikitable"<br />
!Typ bloku<br />
!Kategoria<br />
!Działanie<br />
|-<br />
|initialize global name to<br />
|Variables<br />
|Definiuje zmienną currentQuestionIndex (zmień nazwę)<br />
|-<br />
|0 (1)<br />
|Math<br />
|Ustaw wartość początkową currentQuestionIndex na 1 (zmień liczbę)<br />
|}<br />
Bloki powinny wyglądać następująco:<br />
<br />
[[Plik:t6-4.png]]<br />
<br />
===Wyświetl pierwsze pytanie===<br />
Odłóż na razie kwestię odpowiedzi i skup się na zaprogramowaniu sekwencyjnego przejścia przez pytania. Pożądane zachowanie jest następujące: po uruchomieniu aplikacji na etykiecie o nazwie QuestionLabel pojawia się pierwsze pytanie. Gdy użytkownik kliknie NextButton, wyświetlone zostaje drugie pytanie. Po ponownym kliknięciu pojawia się trzecie pytanie. Po dotarciu do ostatniego pytania kliknięcie przycisku NextButton powoduje ponowne pojawienie się pierwszego pytania w etykiecie QuestionLabel.<br />
<br />
W programie App Inventor określone pozycje na liście są wybierane za pomocą bloku select list item. W tym bloku trzeba podać listę i indeks – pozycję na liście. Jeżeli na liście są trzy pozycje, prawidłowe indeksy to 1, 2 i 3.<br />
<br />
Po uruchomieniu aplikacja QuizMe powinna wybrać pierwsze pytanie z listy i wyświetlić je w komponencie QuestionLabel. Do tego zachowania inicjalizującego działanie aplikacji potrzebne są następujące bloki:<br />
<br />
{| class="wikitable"<br />
!Typ bloku<br />
!Kategoria<br />
!Działanie<br />
|-<br />
|when Screen1.Initialize<br />
|Screen1<br />
|Podczas uruchamiania aplikacji zainicjowana jest ta obsługa zdarzenia<br />
|-<br />
|set QuestionLabel.Text to<br />
|QuestionLabel<br />
|Umieszcza pierwsze pytanie w etykiecie QuestionLabel<br />
|-<br />
|select list item<br />
|Lists<br />
|Wybiera pierwsze pytanie z etykiety QuestionLabel<br />
|-<br />
|get <br />
|Variables<br />
|Ustala listę, z której jest wybierany element. Tutaj: Global QuestionList<br />
|-<br />
|0 (1)<br />
|Math<br />
|Wybiera pierwsze pytanie za pomocą indeksu 1. Ustaw wartość na 1.<br />
|}<br />
Bloki powinny wyglądać następująco:<br />
<br />
[[Plik:t6-5.png]]<br />
<br />
===Jak działają bloki?===<br />
Zdarzenie when Screen1.Initialize jest wyzwalane podczas uruchomienia aplikacji. Pierwsza pozycja zmiennej QuestionList zostaje wybrana i umieszczona w bloku set QuestionLabel.Text. Gdy aplikacja zostanie uruchomiona, użytkownik zobaczy pierwsze pytanie.<br />
===Przetestuj to zachowanie===<br />
Jeśli dotychczas nie skomunikowałeś urządzenia mobilnego z programem, zrób to teraz. Co pojawia się na urządzeniu? Jeżeli utworzono listę QuestionList tak, jak wskazano powyżej, w etykiecie QuestionLabel powinna pojawić się pierwsza pozycja tej listy (Kto był doskonałym miotaczem w World Series?).<br />
<br />
==Iteracja pytań==<br />
Zdefiniowałeś już zmienną CurrentQuestionIndex, zapamiętującą pytanie, przy którym znajduje się użytkownik. Zaprogramuj teraz zachowanie przycisku NextButton. Gdy zostanie on kliknięty, aplikacja zwiększy wartość zmiennej, np. zmieni ją z 1 na 2 lub z 2 na 3 itd., a następnie użyje tej wartości do zaznaczenia nowego bieżącego pytania. Do tego zachowania potrzebne są następujące bloki:<br />
{| class="wikitable"<br />
!Typ bloku<br />
!Kategoria<br />
!Działanie<br />
|-<br />
|when NextButton.Click<br />
|NextButton<br />
|Uruchamia obsługę zdarzeń po kliknięciu przycisku<br />
|-<br />
|set currentQuestionIndex to<br />
|Zmienne<br />
|Decyduje o ustawieniu indeksu wybranej listy<br />
|-<br />
|+ <br />
|Math<br />
|Służy do zwiększania wartości zmiennej currentQuestionIndex<br />
|-<br />
|get global currentQuestionIndex<br />
|Zmienne<br />
|Tworzy nową wartość poprzez zwiększenie poprzedniej wartości o 1<br />
|-<br />
|0 (1)<br />
|Math<br />
|Dla + 1<br />
|-<br />
|set QuestionLabel.Text to<br />
|QuestionLabel<br />
|Wyświetla kolejne pytanie<br />
|-<br />
|select list item<br />
|Listy<br />
|Ustawia element listy jako wartość QuestionLabel<br />
|-<br />
|get global QuestionList<br />
|Zmienne<br />
|Wskazuje, która lista będzie wybrana<br />
|-<br />
|get global currentQuestionIndex<br />
|Zmienne<br />
|Wskazuje, który element wybranej listy będzie wybrany<br />
|}<br />
Bloki powinny wyglądać następująco:<br />
<br />
[[Plik:t6-6.png]]<br />
<br />
===Jak działają bloki?===<br />
Pierwszy wiersz polecenia zwiększa wartość zmiennej currentQuestionIndex o 1 (jeżeli zmienna zawiera wartość 1, zostaje ona zmieniona na 2, z 2 na 3 itd.). Następnie wykorzystuje nową wartość do wyboru pytania o tym indeksie.<br />
<br />
Przypomnijmy, że w bloku obsługi zdarzeń Screen.Initialize aplikacja wybrała pierwsze do wyświetlenia pytanie:<br />
<br />
[[Plik:t6-7.png]]<br />
<br />
Po kliknięciu przycisku NextButton aplikacja nie wybiera konkretnie pierwszej, drugiej czy trzeciej pozycji na liście, tylko pozycję o n-tej wartości zmiennej currentQuestionIndex.<br />
<br />
[[Plik:t6-8.png]]<br />
<br />
Polecenia w blokach są wykonywane od prawej do lewej, tzn. aplikacja najpierw określa wartość parametru z bloku Select list item, którym jest zmienna CurrentQuestionIndex. Liczba zawarta w tej zmiennej zostaje użyta jako indeks podczas wykonania poleceń zawartych w bloku Select list item.<br />
<br />
[[Plik:info.png]]Po pierwszym kliknięciu przycisku NextButton, wartość zmiennej currentQuestionIndex przeskoczy z 1 na 2, aby aplikacja wybrała drugą pozycję z listy QuestionList (Kto był pierwszym doskonałym miotaczem w 2010?). Po drugim kliknięciu przycisku NextButton, wartość zmiennej currentQuestionIndex zostanie zmieniona z 2 na 3, a aplikacja wybierze trzecie pytanie z listy (Kto był pierwszym doskonałym miotaczem nowej ery?).<br />
===Przetestuj to zachowanie===<br />
Przetestuj zachowanie przycisku NextButton, aby sprawdzić, czy aplikacja działa poprawnie. Wciel się w rolę użytkownika i kliknij przycisk NextButton w telefonie. Czy urządzenie wyświetliło drugie pytanie: Kto był pierwszym doskonałym miotaczem w 2010?? Trzecie pytanie powinno pojawić się po kolejnym kliknięciu przycisku. Jeżeli aplikacja działa, pogratuluj sobie i przejdź dalej. Kliknij przycisk NextButton ponownie (po raz trzeci). Powinien zostać wyświetlony błąd: Próba uzyskania elementu 4 z listy o długości 3. Czy wiesz, na czym polega problem?<br />
<br />
Problem z aplikacją polega na tym, że zawsze po kliknięciu przycisku NextButton zwiększa ona zmienną CurrentQuestionIndex o 1. Gdy wartość zmiennej wynosi już 3, a użytkownik kolejny raz kliknie przycisk NextButton, aplikacja zmieni wartość zmiennej z 3 na 4, następnie wywoła blok Select list item, aby odczytać pozycję o aktualnym indeksie CurrentQuestionIndex, czyli w tym przypadku czwartą pozycję. Ponieważ zmienna QuestionList zawiera tylko trzy elementy, Android wykaże błąd.<br />
<br />
Aplikacja musi zadawać pytanie - sprawdzać warunek - gdy nastąpi kliknięcie przycisku NextButton i realizować polecenia zawarte w różnych blokach w zależności od odpowiedzi. Elementem do sprawdzenia jest to, czy zmienna CurrentQuestionIndex już ma wartość 3. Jeżeli tak - należy ustawić CurrentQuestionIndex z powrotem na 0, aby użytkownik wrócił do pierwszego pytania.<br />
<br />
Będziesz potrzebował następujących bloków:<br />
{| class="wikitable"<br />
!Typ bloku<br />
!Kategoria<br />
!Działanie<br />
|-<br />
|if then<br />
|Control<br />
|sprawdzenie, czy użytkownik jest na etapie ostatniego pytania<br />
|-<br />
|= <br />
|Math<br />
|sprawdzenie, czy currentQuestionIndex ma wartość 3<br />
|-<br />
|get global currentQuestionIndex<br />
|Variables<br />
|<br />
|-<br />
|0 (3)<br />
|Math<br />
|3 to numer na liście<br />
|-<br />
|set currentQuestionIndex to<br />
|Variables<br />
|ustawienie na 0, aby wrócić do pierwszego pytania<br />
|-<br />
|0<br />
|Math<br />
|ustawienie na 0, ponieważ kolejne bloki zwiększą wartość do 1<br />
|}<br />
Zmodyfikowany blok obsługi zdarzenia When NextButton.Click powinien wyglądać następująco:<br />
<br />
[[Plik:t6-9.png]]<br />
<br />
===Jak działają bloki===<br />
Po kliknięciu przycisku NextButton aplikacja najpierw sprawdza, czy currentQuestionIndex ma wartość 3. Jeżeli tak, wartość tej zmiennej jest ustawiana na 0, aby po zwiększeniu jej w dalszych krokach jej wartość wyniosła 1. Wtedy quiz wróci do pierwszego pytania. Zauważ, że tylko bloki osadzone w bloku if-then są zależne od warunku. Blok zwiększenia wartości i blok Set QuestionLabel.Text to są wykonywane bez względu na jakikolwiek warunek.<br />
<br />
==Aplikacja modyfikowalna: Ułatwianie modyfikowania pytań==<br />
Teraz zmodyfikujemy aplikację, aby można było łatwo dodawać i usuwać elementy z listy. Zmień bloki tak, aby działały na liście o dowolnej długości, a nie tylko liście z dokładnie trzema pozycjami. <br />
Na początek dodaj czwarte pytanie do zmiennej QuestionList i kolejną odpowiedź do AnswerList. W tym celu musisz najpierw zwiększyć liczbę dostępnych pól za pomocą przycisku modyfikującego (mutatora). Aby dowiedzieć się więcej o tym elemencie, zobacz: http://appinventor.mit.edu/explore/ai2/support/concepts/mutators. Bloki powinny wyglądać następująco:<br />
<br />
===Przetestuj zmodyfikowaną aplikację.===<br />
Kliknij przycisk NextButton kilka razy. Zauważysz, że czwarte pytanie nigdy się nie pojawia, bez względu na to, ile razy klikniesz przycisk.<br />
<br />
Problemem jest to, że test sprawdzający, czy użytkownik znajduje się przy ostatnim pytaniu, jest zbyt szczegółowy: pyta, czy zmienna CurrentQuestionIndex ma wartość 3:<br />
<br />
Możesz po prostu zmienić liczbę z 3 na 4, a aplikacja będzie znów działać poprawnie. Problem polega jednak na tym, że za każdym razem, gdy zmodyfikujesz liczbę pytań i odpowiedzi, będziesz musiał pamiętać, aby dokonać także tej zmiany. Takie zależności w programie komputerowym często prowadzą do błędów, w szczególności gdy aplikacja staje się bardziej złożona. Znacznie lepiej jest przygotować program w taki sposób, aby działał niezależnie od liczby pytań. Takie uogólnienie jest jeszcze ważniejsze, gdy lista, z którą pracujesz, zmienia się dynamicznie, na przykład w aplikacji z quizem, gdzie użytkownik może dodawać nowe pytania.<br />
<br />
Lepszym rozwiązaniem jest sprawdzenie warunku w sposób bardziej ogólny. Tak naprawdę chcesz wiedzieć, czy bieżące pytanie – czyli wartość zmiennej currentQuestionIndex jest tak duża, jak ilość elementów w zmiennej QuestionList. Jeżeli aplikacja sprawdzi warunek w bardziej ogólny sposób, to będzie działać, nawet jeżeli dodasz lub usuniesz elementy ze zmiennej QuestionList. Aby zmienić blok obsługi zdarzenia When NextButton.Click, zmień poprzedni test sprawdzający, który odnosił się bezpośrednio do 3. Będziesz potrzebował następujących bloków:<br />
{| class="wikitable"<br />
!Typ bloku<br />
!Szuflada<br />
!Działanie<br />
|-<br />
|length of list<br />
|Lists<br />
|Pyta, ile elementów jest w zmiennej QuestionList<br />
|-<br />
|get global QuestionList<br />
|Variables<br />
|Określa, o którą listę chodzi<br />
|}<br />
Blok obsługi zdarzenia When NextButton.Click powinien teraz wyglądać następująco:<br />
<br />
<br />
===Jak działają bloki?===<br />
Warunek if porównuje teraz wartość zmiennej CurrentQuestionIndex z długością zmiennej QuestionList. Zatem jeżeli zmienna CurrentQuestionIndex ma wartość 4, a długość zmiennej QuestionList wynosi 4, to wartość zmiennej currentQuestionIndex zostanie ustawiona na 0 (a następnie na 1, 2 itd.). Zauważ - bloki nie odwołują się już do 3 ani żadnej innej określonej wartości, dlatego instrukcja będzie działać bez względu na liczbę elementów listy.<br />
<br />
Przetestuj zmodyfikowane zachowanie. Czy po kliknięciu przycisku NextButton aplikacja przechodzi teraz przez cztery pytania, wracając po ostatnim do pierwszego?<br />
<br />
==Przełączanie zdjęcia dla każdego pytania==<br />
Na razie aplikacja wyświetla to samo zdjęcie, bez względu na to, jakie pytanie zostaje zadane. Możesz to zmienić tak, aby po kliknięciu przycisku NextButton pojawiała się fotografia dotycząca danego pytania. W obszarze Media dostępne są cztery dodane wcześniej zdjęcia. Teraz utworzymy trzecią listę - PictureList, której elementami będą nazwy plików zdjęć, a następnie zmodyfikujemy blok obsługi zdarzenia When NextButton.Click, aby program po każdym pytaniu przełączał zdjęcie.<br />
Najpierw utwórz listę PictureList i zainicjuj ją nazwami plików graficznych. Upewnij się, czy nazwy są dokładnie takie same jak nazwy plików, które zostały załadowane do obszaru Media. Oto jak powinien wyglądać blok dla listy PictureList:<br />
<br />
Następnie zmodyfikuj blok obsługi zdarzeń When NextButton.Click, aby zmieniał wyświetlane zdjęcie w zależności od zadanego pytania. Jeżeli ustawisz właściwość Image.Picture na nazwę pliku zdjęcia, które zostało załadowane, właśnie ta fotografia zostanie wyświetlona. Aby zmodyfikować blok When NextButton.Click, potrzebujesz następujących bloków:<br />
{| class="wikitable"<br />
!Typ bloku<br />
!Kategoria<br />
!Działanie<br />
|-<br />
|set Image1.Picture to<br />
|Image1<br />
|ustaw, aby zmieniać zdjęcie<br />
|-<br />
|select list item<br />
|Lists<br />
|należy wybrać zdjęcie odpowiadające na aktualne pytanie<br />
|-<br />
|get global PictureList<br />
|Variables<br />
|wybierz nazwę pliku z tej listy<br />
|-<br />
|get global currentQuestionIndex<br />
|Variables<br />
|wybierz element o n-tym indeksie currentQuestionIndex<br />
|}<br />
Oto jak powinny wyglądać bloki:<br />
<br />
===Jak działają bloki?===<br />
Zmienna CurrentQuestionIndex służy jako indeks dla zmiennej QuestionList. Wartość CurrentQuestionIndex wynosi 1, aplikacja wybiera pierwsze pytanie i pierwsze zdjęcie. Gdy CurrentQuestionIndex wynosi 2, aplikacja wybiera drugie pytanie i drugie zdjęcie. Oczywiście takie działanie zależy od tego, czy listy są ze sobą zsynchronizowane. Tak jest w tym przypadku - pierwszy obraz - LarsenBerra.jpg to zdjęcie Dona Larsena, jednocześnie Don Larsen to odpowiedź na pierwsze pytanie (Kto był doskonałym miotaczem w World Series?). <br />
Przetestuj zmodyfikowane zachowanie. Czy nowe zdjęcie pojawia się po każdym kliknięciu przycisku NextButton?<br />
<br />
==Ocena udzielanych odpowiedzi==<br />
Teraz dodamy bloki, które określają, czy użytkownik odpowiedział na pytanie prawidłowo, czy też nie. Gracz wprowadza odpowiedź do AnswerText, a następnie klika przycisk AnswerButton. Aplikacja musi porównać wpis użytkownika z odpowiedzią na bieżące pytanie, używając bloku if... then... w celu jej sprawdzenia. Etykieta RightWrongLabel powinna być modyfikowana, aby podawać, czy odpowiedź jest prawidłowa, czy nie.<br />
<br />
Do tego zachowania będą potrzebne następujące bloki:<br />
{| class="wikitable"<br />
!Typ bloku<br />
!Kategoria<br />
!Działanie<br />
|-<br />
|when AnswerButton.Click<br />
|AnswerButton<br />
|zachowanie jest wyzwalane, gdy użytkownik kliknie przycisk AnswerButton<br />
|-<br />
|if... then...<br />
|Control<br />
|Użyj mutatora, aby dodać alternatywę (else). Jeżeli odpowiedź jest prawidłowa - zrób jedno, w przeciwnym razie (else) - zrób coś innego<br />
|-<br />
|= <br />
|Math<br />
|sprawdzenie, czy odpowiedź jest prawidłowa<br />
|-<br />
|AnswerText.Text<br />
|AnswerText<br />
|Odpowiedź użytkownika pojawia się w tym polu tekstowym<br />
|-<br />
|select list item<br />
|Lists<br />
|wybrać bieżącą odpowiedź z listy AnswerList<br />
|-<br />
|get global AnswerList<br />
|Variables<br />
|lista, z której jest wybierany element<br />
|-<br />
|get global currentQuestionIndex<br />
|Variables<br />
|numer pytania (i numer odpowiedzi), przy którym jest użytkownik<br />
|-<br />
|set RightWrongLabel.Text to<br />
|RightWrongLabel<br />
|tutaj podaj odpowiedź<br />
|-<br />
|Dobrze!<br />
|Text<br />
|jeżeli odpowiedź jest prawidłowa<br />
|-<br />
|set RightWrongLabel.Text to<br />
|RightWrongLabel<br />
|tutaj podaj odpowiedź<br />
|-<br />
|Źle<br />
|Text<br />
|jeżeli odpowiedź jest nieprawidłowa<br />
|}<br />
Bloki powinny wyglądać następująco:<br />
<br />
===Jak działają bloki?===<br />
Test if sprawdza, czy odpowiedź użytkownika (AnswerText.Text) jest taka sama, jak element na liście AnswerList o indeksie równym wartości zmiennej CurrentQuestionIndex. Jeżeli zmienna CurrentQuestionIndex ma wartość 1, aplikacja porównuje odpowiedź użytkownika z pierwszą pozycją na liście AnswerList, (Don Larsen). Jeżeli zmienna CurrentQuestionIndex zmieni wartość na 2, program zestawia odpowiedź z drugą pozycją na liście, czyli Dallas Branden. Jeśli wynik porównania jest pozytywny, przeprowadzane są bloki then, a treść etykiety RightWrongLabel zostaje ustawiona na Dobrze!. Jeżeli wynik testu jest negatywny (fałszywy), przeprowadzane są bloki alternatywy (else), a treść etykiety RightWrongLabel zostaje ustawiona na Źle.<br />
<br />
Przetestuj zmodyfikowaną aplikację. Spróbuj odpowiedzieć na jedno z pytań. Powinna pojawić się ocena, czy odpowiedź była dokładnie taka sama, jak na liście AnswerList. Sprawdź zarówno prawidłowe, jak i nieprawidłowe odpowiedzi (Uwaga - uwzględniana jest wielkość liter!). Kliknij przycisk NextButton i odpowiedz na drugie pytanie. Czy aplikacja nadal działa? Powinna, ale zauważ, że gdy klikniesz przycisk NextButton, tekst Dobrze! lub Źle oraz poprzednia odpowiedź nadal będą wyświetlane. Choć nie wpływa to zasadniczo na naszą grę, to takie szczegóły interfejsu z pewnością zostaną zauważone przez użytkowników Twojej aplikacji.<br />
<br />
Aby wyzerować etykietę RightWrongLabel i AnswerText, umieść poniższe bloki w bloku obsługi zdarzeń When NextButton.click:<br />
{| class="wikitable"<br />
!Typ bloku<br />
!Kategoria<br />
!Działanie<br />
|-<br />
|set RightWrongLabel.Text to<br />
|RightWrongLabel<br />
|Ustawia wartość etykiety na…<br />
|-<br />
|„ „<br />
|Text<br />
|pusty tekst<br />
|-<br />
|set AnswerText.Text to<br />
|AnswerText<br />
|Ustawia wartość etykiety na…<br />
|-<br />
|„ „<br />
|Text<br />
|pusty tekst<br />
|}<br />
Bloki powinny wyglądać następująco:<br />
<br />
===Jak działają bloki?===<br />
Po kliknięciu przycisku NextButton użytkownik przechodzi do następnego pytania, dlatego początkowe wiersze bloku obsługi zdarzeń zerują etykietę RightWrongLabel i pole AnswerText.<br />
Przetestuj to zachowanie Odpowiedz na pytanie i kliknij przycisk Wyślij, a następnie - NextButton. Czy Twoja poprzednia odpowiedź i jej ocena zniknęły?<br />
<br />
==Ostateczna postać programu==<br />
Oto gotowa aplikacja QuizMe:<br />
<br />
Utwórz wykonywalną wersję aplikacji, wybierając menu Build/App (provide QR code for .apk). Gdy pojawi się kod kreskowy, użyj czytnika kodów w telefonie, aby pobrać i zainstalować aplikację.<br />
<br />
===Modyfikacje===<br />
Quiz w tej wersji jest już gotowy. Czy masz ochotę przemyśleć pewne zmiany?<br />
<br />
Zamiast wyświetlać zdjęcie dla każdego pytania, spróbuj odtworzyć dźwięk lub krótkie wideo. Za pomocą dźwięku możesz zmienić quiz w aplikację Jaka to melodia?.<br />
<br />
Quiz akceptuje ściśle określone odpowiedzi. Jeśli gracz odpowiedziałby, lekko przekształcając tekst (np. podając inicjał zamiast imienia), program uzna to za błąd. Można to zmienić na kilka różnych sposobów. Jednym z nich jest użycie bloku text.contains, aby sprawdzić, czy odpowiedź użytkownika zawiera prawidłową odpowiedź. Inny sposób to dostarczenie wielu odpowiedzi na każde pytanie i sprawdzenie przez iterację (użycie bloku for each), czy któraś z nich pasuje.<br />
<br />
Przekształć quiz tak, aby przedstawiał odpowiedzi do wyboru. Lista odpowiedzi będzie musiała być listą list, a każda podrzędna lista będzie musiała zawierać opcje odpowiedzi. Użyj komponentu ListPicker, aby umożliwić użytkownikowi wybranie odpowiedzi.<br />
<br />
<br />
==Podsumowanie==<br />
Oto niektóre koncepcje omówione w tym przewodniku:<br />
<ul><li>Aplikacje można tworzyć w sposób ogólny, aby pracować z dowolną listą danych.</li><br />
<li>Zmienne indeksu są wykorzystywane do śledzenia bieżącej pozycji na liście. Zwiększając wartość zmiennej indeksu, należy uważać na przekroczenie końca listy.</li></ul><br />
<br />
==Zeskanuj próbną aplikację do telefonu==<br />
Aby zainstalować i uruchomić aplikację próbną, zeskanuj poniższy kod kreskowy:<br />
<br />
==Pobierz kod źródłowy==<br />
Jeżeli chcesz pracować z tą próbką w programie App Inventor:<br />
<ul><li>pobierz na komputer kod źródłowy: [http://appinventor.mit.edu/explore/sites/all/files/ai2tutorials/QuizMe/QuizMe_MIT.aia http://appinventor.mit.edu/explore/sites/all/files/ai2tutorials/QuizMe/QuizMe_MIT.aia]</li><br />
<li>otwórz program App Inventor,</li><br />
<li>kliknij opcję My Projects,</li><br />
<li>wybierz Import project (.aia) from my computer...</li><br />
<li>znajdź i zatwierdź pobrany kod źródłowy.</li></ul></div>M Kelniarzhttp://wiki.mistrzowiekodowania.pl/index.php?title=QuizMeQuizMe2015-03-15T18:28:00Z<p>M Kelniarz: /* Programowanie aplikacji */</p>
<hr />
<div>=Aplikacja QuizMe dla App Inventor 2=<br />
<br />
==Co tworzysz?==<br />
[[Plik:t6-1.png|right]]QuizMe to gra dotycząca ciekawostek baseballowych, ale można jej użyć jako szablonu do tworzenia quizów z dowolnej dziedziny. W aplikacji użytkownik odpowiada na szereg pytań, otrzymując następnie informację zwrotną, czy udzielił poprawnej, czy błędnej odpowiedzi. Gracz przechodzi do kolejnego pytania, klikając przycisk.<br />
<br />
W grze QuizMe dysponujemy zamkniętym zbiorem pytań, chyba że programista je zmieni. W następnym etapie można utworzyć MakeQuiz & TakeQuiz – aplikację, która pozwala użytkownikom na tworzenie i modyfikowanie pytań.<br />
<br />
Poradnik ten zakłada, że znasz już podstawy tworzenia aplikacji w App Inventorze – korzystanie z Projektanta komponentów w celu utworzenia interfejsu użytkownika i z Edytora bloków, aby określić obsługę zdarzeń. Jeżeli potrzebujesz przypomnienia, spróbuj popracować z poradnikami podstawowymi zanim przejdziesz dalej.<br />
<br />
==Zaczynamy!==<br />
Połącz się z witryną internetową App Inventor i załóż nowy projekt. Nazwij go QuizMe, ustaw taki sam tytuł ekranu (Title). Za pomocą MIT AI2 Companion połącz program z urządzeniem mobilnym. Pobierz poniższe zdjęcia baseballistów i zapisz je w komputerze. Później załadujesz je do projektu.<br />
<ul><li> [http://beta.appinventor.mit.edu/learn/tutorials/quizme/QuizMeAssets/Larsenberra.jpg Larsenberra.jpg]</li><br />
<li> [http://beta.appinventor.mit.edu/learn/tutorials/quizme/QuizMeAssets/dallasbraden.jpg Dallasbraden.jpg]</li><br />
<li> [http://beta.appinventor.mit.edu/learn/tutorials/quizme/QuizMeAssets/cyyoung.jpg Cyyoung.jpg]</li><br />
<li> [http://beta.appinventor.mit.edu/learn/tutorials/quizme/QuizMeAssets/nolanryan.jpg Nolanryan.jpg]</li></ul><br />
<br />
==Wstęp==<br />
Zaprojektujesz grę typu quiz, w której użytkownik będzie przechodził do kolejnych pytań, klikając przycisk Dalej, a następnie otrzymywał prostą ocenę Dobrze/Źle dla każdej odpowiedzi.<br />
<br />
W tym przewodniku omówimy:<br />
<ul><li>definiowanie i wyświetlanie listy informacji;</li><br />
<li>przechodzenie przez listę za pomocą zmiennej indeksującej – zmiennej, która śledzi pozycję na liście;</li><br />
<li>zachowania warunkowe – wykonywanie określonych operacji tylko wtedy, gdy spełniony jest określony warunek;</li><br />
<li>Zmianę zdjęcia w zależności od sytuacji.</li></ul><br />
<br />
==Projektowanie aplikacji==<br />
Użyj Projektanta komponentów do utworzenia interfejsu dla aplikacji QuizMe. <br />
Aby utworzyć interfejs, najpierw załaduj do projektu pobrane zdjęcia. Kliknij przycisk Prześlij plik (Upload File...) w obszarze Media i wybierz jeden z pobranych wcześniej plików (np. Larsenberra.jpg). Następnie zrób to samo z pozostałymi trzema zdjęciami.<br />
Utwórz następujące komponenty, przeciągając je z Palety (Palette) do Przeglądarki (Viewer) i ustaw właściwości komponentów zgodnie z poniższym opisem:<br />
{|class="wikitable"<br />
! Typ komponentu<br />
! Kategoria<br />
! Jaką nadać jej nazwę<br />
! Działanie<br />
! Działanie komponentu<br />
|-<br />
|Image<br />
|User interface<br />
|Image1<br />
|Ustaw właściwość zdjęcia (Picture) na Larsenberra.jpg. Jest to pierwsze wyświetlane zdjęcie.<br />
|Obrazkowa część pytania<br />
|-<br />
|Label<br />
|User interface<br />
|QuestionLabel<br />
|Zmień właściwość tekstu (Text) na Pytanie:<br />
|Wyświetla bieżące pytanie<br />
|-<br />
|HorizontalArrangement<br />
|Layout<br />
|HorizontalArrangement1<br />
| <br />
|Organizuje komponenty AnswerPrompt i Text (podaj odpowiedź i tekst)<br />
|-<br />
|Label<br />
|User interface<br />
|AnswerPromptLabel<br />
|Zmień właściwość tekstu (Text) na Podaj odpowiedź:. Na ekranie przeglądarki przesuń tę etykietę do HorizontalArrangement1.<br />
|Wyświetla tekst prośby o odpowiedź.<br />
|-<br />
|TextBox<br />
|User interface<br />
|AnswerText<br />
|Zmień wskazówkę (Hint) na Podaj odpowiedź. Na ekranie przeglądarki przenieś AnswerText do komponentu HorizontalArrangement1.<br />
|Tutaj użytkownik podaje odpowiedź.<br />
|-<br />
|Label<br />
|User interface <br />
|RightWrongLabel<br />
|Zmień właściwość tekstu (Text) na Dobrze/Źle.<br />
|Tutaj wyświetlana jest ocena Dobrze/Źle.<br />
|-<br />
|HorizontalArrangement<br />
|Layout<br />
|HorizontalArrangement2<br />
|<br />
|Organizuje przyciski AnswerButton i NextButton (przycisk odpowiedzi i przycisk dalej).<br />
|-<br />
|Przycisk<br />
|User interface<br />
|AnswerButton<br />
|Zmień właściwość tekstu (Text) na Wyślij. Na ekranie przeglądarki przesuń ten przycisk do HorizontalArrangment2.<br />
|Użytkownik klika, aby przesłać odpowiedź.<br />
|-<br />
|Przycisk<br />
|User interface<br />
|NextButton<br />
|Zmień właściwość tekstu (Text) na Dalej. Przenieś ten przycisk do HorizontalArrangement2.<br />
|Użytkownik klika, aby przejść do następnego pytania.<br />
|} <br />
Po zakończeniu powinien on wyglądać jak poniższa ilustracja (pod nią znajdują się również bardziej szczegółowe informacje).<br />
[[Plik:t6-2.png]]<br />
<br />
==Programowanie aplikacji==<br />
Otwórz Edytor bloków, aby zaprogramować działanie komponentów. Najpierw zdefiniuj dwie zmienne - listy: zmienną QuestionList, zawierającą listę pytań i zmienną AnswerList z listą odpowiedzi na te pytania.<br />
<br />
Aby zdefiniować te dwie zmienne listy, potrzebujesz następujących bloków:<br />
{| class="wikitable"<br />
!Typ bloku<br />
!Kategoria<br />
!Działanie<br />
|-<br />
|initialize global name to<br />
|Variables<br />
|Definiuje zmienną QuestionList (zmień jej nazwę)<br />
|-<br />
|initialize global name to<br />
|Variables<br />
|Definiuje zmienną AnswerList (zmień jej nazwę)<br />
|-<br />
|make a list<br />
|Lists<br />
|Służy do dodawania elementów do zmiennej QuestionList<br />
|-<br />
|„ „ (trzykrotnie)<br />
|Lists<br />
|Służy do wpisania pytań<br />
|-<br />
|make a list<br />
|Lists<br />
|Służy do dodawania elementów do zmiennej AnswerList<br />
|-<br />
|„ „ (trzykrotnie)<br />
|Text<br />
|Służy do wpisania odpowiedzi<br />
|}<br />
Utwórz zmienne całościowe, przeciągając z kategorii zmiennych (Variables) na obszar roboczy blok Initialize global name to. Kliknij dwukrotnie domyślną nazwę name, aby ją zmienić. Blok Initialize global name to zawiera pole na początkową wartość zmiennej. Zmienna może zawierać liczbę, tekst, a nawet listę – aby ją utworzyć, podłącz blok Make a list do definicji zmiennej.<br />
<br />
Bloki powinny wyglądać następująco:<br />
<br />
[[Plik:t6-3.png]]<br />
===Zdefiniuj ukrytą zmienną Index===<br />
Za każdym razem, gdy użytkownik kliknie przycisk NextButton, aby przejść dalej, aplikacja musi pamiętać, przy którym pytaniu jest obecnie gracz. W języku programowania, aby coś zapamiętać, trzeba zdefiniować nową zmienną. W tym przypadku aplikacja musi zapamiętać bieżący numer pytania – indeks listy QuestionList.<br />
Aby zdefiniować zmienną currentQuestionIndex, potrzebujesz następujących bloków:<br />
{| class="wikitable"<br />
!Typ bloku<br />
!Kategoria<br />
!Działanie<br />
|-<br />
|initialize global name to<br />
|Variables<br />
|Definiuje zmienną currentQuestionIndex (zmień nazwę)<br />
|-<br />
|0 (1)<br />
|Math<br />
|Ustaw wartość początkową currentQuestionIndex na 1 (zmień liczbę)<br />
|}<br />
Bloki powinny wyglądać następująco:<br />
<br />
[[Plik:t6-4.png]]<br />
<br />
===Wyświetl pierwsze pytanie===<br />
Odłóż na razie kwestię odpowiedzi i skup się na zaprogramowaniu sekwencyjnego przejścia przez pytania. Pożądane zachowanie jest następujące: po uruchomieniu aplikacji na etykiecie o nazwie QuestionLabel pojawia się pierwsze pytanie. Gdy użytkownik kliknie NextButton, wyświetlone zostaje drugie pytanie. Po ponownym kliknięciu pojawia się trzecie pytanie. Po dotarciu do ostatniego pytania kliknięcie przycisku NextButton powoduje ponowne pojawienie się pierwszego pytania w etykiecie QuestionLabel.<br />
<br />
W programie App Inventor określone pozycje na liście są wybierane za pomocą bloku select list item. W tym bloku trzeba podać listę i indeks – pozycję na liście. Jeżeli na liście są trzy pozycje, prawidłowe indeksy to 1, 2 i 3.<br />
<br />
Po uruchomieniu aplikacja QuizMe powinna wybrać pierwsze pytanie z listy i wyświetlić je w komponencie QuestionLabel. Do tego zachowania inicjalizującego działanie aplikacji potrzebne są następujące bloki:<br />
<br />
{| class="wikitable"<br />
!Typ bloku<br />
!Kategoria<br />
!Działanie<br />
|-<br />
|when Screen1.Initialize<br />
|Screen1<br />
|Podczas uruchamiania aplikacji zainicjowana jest ta obsługa zdarzenia<br />
|-<br />
|set QuestionLabel.Text to<br />
|QuestionLabel<br />
|Umieszcza pierwsze pytanie w etykiecie QuestionLabel<br />
|-<br />
|select list item<br />
|Lists<br />
|Wybiera pierwsze pytanie z etykiety QuestionLabel<br />
|-<br />
|get <br />
|Variables<br />
|Ustala listę, z której jest wybierany element. Tutaj: Global QuestionList<br />
|-<br />
|0 (1)<br />
|Math<br />
|Wybiera pierwsze pytanie za pomocą indeksu 1. Ustaw wartość na 1.<br />
|}<br />
Bloki powinny wyglądać następująco:<br />
<br />
[[Plik:t6-5.png]]<br />
<br />
===Jak działają bloki?===<br />
Zdarzenie when Screen1.Initialize jest wyzwalane podczas uruchomienia aplikacji. Pierwsza pozycja zmiennej QuestionList zostaje wybrana i umieszczona w bloku set QuestionLabel.Text. Gdy aplikacja zostanie uruchomiona, użytkownik zobaczy pierwsze pytanie.<br />
===Przetestuj to zachowanie===<br />
Jeśli dotychczas nie skomunikowałeś urządzenia mobilnego z programem, zrób to teraz. Co pojawia się na urządzeniu? Jeżeli utworzono listę QuestionList tak, jak wskazano powyżej, w etykiecie QuestionLabel powinna pojawić się pierwsza pozycja tej listy (Kto był doskonałym miotaczem w World Series?).<br />
<br />
==Iteracja pytań==<br />
Zdefiniowałeś już zmienną CurrentQuestionIndex, zapamiętującą pytanie, przy którym znajduje się użytkownik. Zaprogramuj teraz zachowanie przycisku NextButton. Gdy zostanie on kliknięty, aplikacja zwiększy wartość zmiennej, np. zmieni ją z 1 na 2 lub z 2 na 3 itd., a następnie użyje tej wartości do zaznaczenia nowego bieżącego pytania. Do tego zachowania potrzebne są następujące bloki:<br />
{| class="wikitable"<br />
!Typ bloku<br />
!Kategoria<br />
!Działanie<br />
|-<br />
|when NextButton.Click<br />
|NextButton<br />
|Uruchamia obsługę zdarzeń po kliknięciu przycisku<br />
|-<br />
|set currentQuestionIndex to<br />
|Zmienne<br />
|Decyduje o ustawieniu indeksu wybranej listy<br />
|-<br />
|+ <br />
|Math<br />
|Służy do zwiększania wartości zmiennej currentQuestionIndex<br />
|-<br />
|get global currentQuestionIndex<br />
|Zmienne<br />
|Tworzy nową wartość poprzez zwiększenie poprzedniej wartości o 1<br />
|-<br />
|0 (1)<br />
|Math<br />
|Dla + 1<br />
|-<br />
|set QuestionLabel.Text to<br />
|QuestionLabel<br />
|Wyświetla kolejne pytanie<br />
|-<br />
|select list item<br />
|Listy<br />
|Ustawia element listy jako wartość QuestionLabel<br />
|-<br />
|get global QuestionList<br />
|Zmienne<br />
|Wskazuje, która lista będzie wybrana<br />
|-<br />
|get global currentQuestionIndex<br />
|Zmienne<br />
|Wskazuje, który element wybranej listy będzie wybrany<br />
|}<br />
Bloki powinny wyglądać następująco:<br />
<br />
===Jak działają bloki?===<br />
Pierwszy wiersz polecenia zwiększa wartość zmiennej currentQuestionIndex o 1 (jeżeli zmienna zawiera wartość 1, zostaje ona zmieniona na 2, z 2 na 3 itd.). Następnie wykorzystuje nową wartość do wyboru pytania o tym indeksie.<br />
<br />
Przypomnijmy, że w bloku obsługi zdarzeń Screen.Initialize aplikacja wybrała pierwsze do wyświetlenia pytanie:<br />
<br />
Po kliknięciu przycisku NextButton aplikacja nie wybiera konkretnie pierwszej, drugiej czy trzeciej pozycji na liście, tylko pozycję o n-tej wartości zmiennej currentQuestionIndex.<br />
<br />
Polecenia w blokach są wykonywane od prawej do lewej, tzn. aplikacja najpierw określa wartość parametru z bloku Select list item, którym jest zmienna CurrentQuestionIndex. Liczba zawarta w tej zmiennej zostaje użyta jako indeks podczas wykonania poleceń zawartych w bloku Select list item.<br />
<br />
Po pierwszym kliknięciu przycisku NextButton, wartość zmiennej currentQuestionIndex przeskoczy z 1 na 2, aby aplikacja wybrała drugą pozycję z listy QuestionList (Kto był pierwszym doskonałym miotaczem w 2010?). Po drugim kliknięciu przycisku NextButton, wartość zmiennej currentQuestionIndex zostanie zmieniona z 2 na 3, a aplikacja wybierze trzecie pytanie z listy (Kto był pierwszym doskonałym miotaczem nowej ery?).<br />
===Przetestuj to zachowanie===<br />
Przetestuj zachowanie przycisku NextButton, aby sprawdzić, czy aplikacja działa poprawnie. Wciel się w rolę użytkownika i kliknij przycisk NextButton w telefonie. Czy urządzenie wyświetliło drugie pytanie: Kto był pierwszym doskonałym miotaczem w 2010?? Trzecie pytanie powinno pojawić się po kolejnym kliknięciu przycisku. Jeżeli aplikacja działa, pogratuluj sobie i przejdź dalej. Kliknij przycisk NextButton ponownie (po raz trzeci). Powinien zostać wyświetlony błąd: Próba uzyskania elementu 4 z listy o długości 3. Czy wiesz, na czym polega problem?<br />
<br />
Problem z aplikacją polega na tym, że zawsze po kliknięciu przycisku NextButton zwiększa ona zmienną CurrentQuestionIndex o 1. Gdy wartość zmiennej wynosi już 3, a użytkownik kolejny raz kliknie przycisk NextButton, aplikacja zmieni wartość zmiennej z 3 na 4, następnie wywoła blok Select list item, aby odczytać pozycję o aktualnym indeksie CurrentQuestionIndex, czyli w tym przypadku czwartą pozycję. Ponieważ zmienna QuestionList zawiera tylko trzy elementy, Android wykaże błąd.<br />
<br />
Aplikacja musi zadawać pytanie - sprawdzać warunek - gdy nastąpi kliknięcie przycisku NextButton i realizować polecenia zawarte w różnych blokach w zależności od odpowiedzi. Elementem do sprawdzenia jest to, czy zmienna CurrentQuestionIndex już ma wartość 3. Jeżeli tak - należy ustawić CurrentQuestionIndex z powrotem na 0, aby użytkownik wrócił do pierwszego pytania.<br />
<br />
Będziesz potrzebował następujących bloków:<br />
{| class="wikitable"<br />
!Typ bloku<br />
!Kategoria<br />
!Działanie<br />
|-<br />
|if then<br />
|Control<br />
|sprawdzenie, czy użytkownik jest na etapie ostatniego pytania<br />
|-<br />
|= <br />
|Math<br />
|sprawdzenie, czy currentQuestionIndex ma wartość 3<br />
|-<br />
|get global currentQuestionIndex<br />
|Variables<br />
|<br />
|-<br />
|0 (3)<br />
|Math<br />
|3 to numer na liście<br />
|-<br />
|set currentQuestionIndex to<br />
|Variables<br />
|ustawienie na 0, aby wrócić do pierwszego pytania<br />
|-<br />
|0<br />
|Math<br />
|ustawienie na 0, ponieważ kolejne bloki zwiększą wartość do 1<br />
|}<br />
Zmodyfikowany blok obsługi zdarzenia When NextButton.Click powinien wyglądać następująco:<br />
<br />
===Jak działają bloki===<br />
Po kliknięciu przycisku NextButton aplikacja najpierw sprawdza, czy currentQuestionIndex ma wartość 3. Jeżeli tak, wartość tej zmiennej jest ustawiana na 0, aby po zwiększeniu jej w dalszych krokach jej wartość wyniosła 1. Wtedy quiz wróci do pierwszego pytania. Zauważ, że tylko bloki osadzone w bloku if-then są zależne od warunku. Blok zwiększenia wartości i blok Set QuestionLabel.Text to są wykonywane bez względu na jakikolwiek warunek.<br />
<br />
==Aplikacja modyfikowalna: Ułatwianie modyfikowania pytań==<br />
Teraz zmodyfikujemy aplikację, aby można było łatwo dodawać i usuwać elementy z listy. Zmień bloki tak, aby działały na liście o dowolnej długości, a nie tylko liście z dokładnie trzema pozycjami. <br />
Na początek dodaj czwarte pytanie do zmiennej QuestionList i kolejną odpowiedź do AnswerList. W tym celu musisz najpierw zwiększyć liczbę dostępnych pól za pomocą przycisku modyfikującego (mutatora). Aby dowiedzieć się więcej o tym elemencie, zobacz: http://appinventor.mit.edu/explore/ai2/support/concepts/mutators. Bloki powinny wyglądać następująco:<br />
<br />
===Przetestuj zmodyfikowaną aplikację.===<br />
Kliknij przycisk NextButton kilka razy. Zauważysz, że czwarte pytanie nigdy się nie pojawia, bez względu na to, ile razy klikniesz przycisk.<br />
<br />
Problemem jest to, że test sprawdzający, czy użytkownik znajduje się przy ostatnim pytaniu, jest zbyt szczegółowy: pyta, czy zmienna CurrentQuestionIndex ma wartość 3:<br />
<br />
Możesz po prostu zmienić liczbę z 3 na 4, a aplikacja będzie znów działać poprawnie. Problem polega jednak na tym, że za każdym razem, gdy zmodyfikujesz liczbę pytań i odpowiedzi, będziesz musiał pamiętać, aby dokonać także tej zmiany. Takie zależności w programie komputerowym często prowadzą do błędów, w szczególności gdy aplikacja staje się bardziej złożona. Znacznie lepiej jest przygotować program w taki sposób, aby działał niezależnie od liczby pytań. Takie uogólnienie jest jeszcze ważniejsze, gdy lista, z którą pracujesz, zmienia się dynamicznie, na przykład w aplikacji z quizem, gdzie użytkownik może dodawać nowe pytania.<br />
<br />
Lepszym rozwiązaniem jest sprawdzenie warunku w sposób bardziej ogólny. Tak naprawdę chcesz wiedzieć, czy bieżące pytanie – czyli wartość zmiennej currentQuestionIndex jest tak duża, jak ilość elementów w zmiennej QuestionList. Jeżeli aplikacja sprawdzi warunek w bardziej ogólny sposób, to będzie działać, nawet jeżeli dodasz lub usuniesz elementy ze zmiennej QuestionList. Aby zmienić blok obsługi zdarzenia When NextButton.Click, zmień poprzedni test sprawdzający, który odnosił się bezpośrednio do 3. Będziesz potrzebował następujących bloków:<br />
{| class="wikitable"<br />
!Typ bloku<br />
!Szuflada<br />
!Działanie<br />
|-<br />
|length of list<br />
|Lists<br />
|Pyta, ile elementów jest w zmiennej QuestionList<br />
|-<br />
|get global QuestionList<br />
|Variables<br />
|Określa, o którą listę chodzi<br />
|}<br />
Blok obsługi zdarzenia When NextButton.Click powinien teraz wyglądać następująco:<br />
<br />
<br />
===Jak działają bloki?===<br />
Warunek if porównuje teraz wartość zmiennej CurrentQuestionIndex z długością zmiennej QuestionList. Zatem jeżeli zmienna CurrentQuestionIndex ma wartość 4, a długość zmiennej QuestionList wynosi 4, to wartość zmiennej currentQuestionIndex zostanie ustawiona na 0 (a następnie na 1, 2 itd.). Zauważ - bloki nie odwołują się już do 3 ani żadnej innej określonej wartości, dlatego instrukcja będzie działać bez względu na liczbę elementów listy.<br />
<br />
Przetestuj zmodyfikowane zachowanie. Czy po kliknięciu przycisku NextButton aplikacja przechodzi teraz przez cztery pytania, wracając po ostatnim do pierwszego?<br />
<br />
==Przełączanie zdjęcia dla każdego pytania==<br />
Na razie aplikacja wyświetla to samo zdjęcie, bez względu na to, jakie pytanie zostaje zadane. Możesz to zmienić tak, aby po kliknięciu przycisku NextButton pojawiała się fotografia dotycząca danego pytania. W obszarze Media dostępne są cztery dodane wcześniej zdjęcia. Teraz utworzymy trzecią listę - PictureList, której elementami będą nazwy plików zdjęć, a następnie zmodyfikujemy blok obsługi zdarzenia When NextButton.Click, aby program po każdym pytaniu przełączał zdjęcie.<br />
Najpierw utwórz listę PictureList i zainicjuj ją nazwami plików graficznych. Upewnij się, czy nazwy są dokładnie takie same jak nazwy plików, które zostały załadowane do obszaru Media. Oto jak powinien wyglądać blok dla listy PictureList:<br />
<br />
Następnie zmodyfikuj blok obsługi zdarzeń When NextButton.Click, aby zmieniał wyświetlane zdjęcie w zależności od zadanego pytania. Jeżeli ustawisz właściwość Image.Picture na nazwę pliku zdjęcia, które zostało załadowane, właśnie ta fotografia zostanie wyświetlona. Aby zmodyfikować blok When NextButton.Click, potrzebujesz następujących bloków:<br />
{| class="wikitable"<br />
!Typ bloku<br />
!Kategoria<br />
!Działanie<br />
|-<br />
|set Image1.Picture to<br />
|Image1<br />
|ustaw, aby zmieniać zdjęcie<br />
|-<br />
|select list item<br />
|Lists<br />
|należy wybrać zdjęcie odpowiadające na aktualne pytanie<br />
|-<br />
|get global PictureList<br />
|Variables<br />
|wybierz nazwę pliku z tej listy<br />
|-<br />
|get global currentQuestionIndex<br />
|Variables<br />
|wybierz element o n-tym indeksie currentQuestionIndex<br />
|}<br />
Oto jak powinny wyglądać bloki:<br />
<br />
===Jak działają bloki?===<br />
Zmienna CurrentQuestionIndex służy jako indeks dla zmiennej QuestionList. Wartość CurrentQuestionIndex wynosi 1, aplikacja wybiera pierwsze pytanie i pierwsze zdjęcie. Gdy CurrentQuestionIndex wynosi 2, aplikacja wybiera drugie pytanie i drugie zdjęcie. Oczywiście takie działanie zależy od tego, czy listy są ze sobą zsynchronizowane. Tak jest w tym przypadku - pierwszy obraz - LarsenBerra.jpg to zdjęcie Dona Larsena, jednocześnie Don Larsen to odpowiedź na pierwsze pytanie (Kto był doskonałym miotaczem w World Series?). <br />
Przetestuj zmodyfikowane zachowanie. Czy nowe zdjęcie pojawia się po każdym kliknięciu przycisku NextButton?<br />
<br />
==Ocena udzielanych odpowiedzi==<br />
Teraz dodamy bloki, które określają, czy użytkownik odpowiedział na pytanie prawidłowo, czy też nie. Gracz wprowadza odpowiedź do AnswerText, a następnie klika przycisk AnswerButton. Aplikacja musi porównać wpis użytkownika z odpowiedzią na bieżące pytanie, używając bloku if... then... w celu jej sprawdzenia. Etykieta RightWrongLabel powinna być modyfikowana, aby podawać, czy odpowiedź jest prawidłowa, czy nie.<br />
<br />
Do tego zachowania będą potrzebne następujące bloki:<br />
{| class="wikitable"<br />
!Typ bloku<br />
!Kategoria<br />
!Działanie<br />
|-<br />
|when AnswerButton.Click<br />
|AnswerButton<br />
|zachowanie jest wyzwalane, gdy użytkownik kliknie przycisk AnswerButton<br />
|-<br />
|if... then...<br />
|Control<br />
|Użyj mutatora, aby dodać alternatywę (else). Jeżeli odpowiedź jest prawidłowa - zrób jedno, w przeciwnym razie (else) - zrób coś innego<br />
|-<br />
|= <br />
|Math<br />
|sprawdzenie, czy odpowiedź jest prawidłowa<br />
|-<br />
|AnswerText.Text<br />
|AnswerText<br />
|Odpowiedź użytkownika pojawia się w tym polu tekstowym<br />
|-<br />
|select list item<br />
|Lists<br />
|wybrać bieżącą odpowiedź z listy AnswerList<br />
|-<br />
|get global AnswerList<br />
|Variables<br />
|lista, z której jest wybierany element<br />
|-<br />
|get global currentQuestionIndex<br />
|Variables<br />
|numer pytania (i numer odpowiedzi), przy którym jest użytkownik<br />
|-<br />
|set RightWrongLabel.Text to<br />
|RightWrongLabel<br />
|tutaj podaj odpowiedź<br />
|-<br />
|Dobrze!<br />
|Text<br />
|jeżeli odpowiedź jest prawidłowa<br />
|-<br />
|set RightWrongLabel.Text to<br />
|RightWrongLabel<br />
|tutaj podaj odpowiedź<br />
|-<br />
|Źle<br />
|Text<br />
|jeżeli odpowiedź jest nieprawidłowa<br />
|}<br />
Bloki powinny wyglądać następująco:<br />
<br />
===Jak działają bloki?===<br />
Test if sprawdza, czy odpowiedź użytkownika (AnswerText.Text) jest taka sama, jak element na liście AnswerList o indeksie równym wartości zmiennej CurrentQuestionIndex. Jeżeli zmienna CurrentQuestionIndex ma wartość 1, aplikacja porównuje odpowiedź użytkownika z pierwszą pozycją na liście AnswerList, (Don Larsen). Jeżeli zmienna CurrentQuestionIndex zmieni wartość na 2, program zestawia odpowiedź z drugą pozycją na liście, czyli Dallas Branden. Jeśli wynik porównania jest pozytywny, przeprowadzane są bloki then, a treść etykiety RightWrongLabel zostaje ustawiona na Dobrze!. Jeżeli wynik testu jest negatywny (fałszywy), przeprowadzane są bloki alternatywy (else), a treść etykiety RightWrongLabel zostaje ustawiona na Źle.<br />
<br />
Przetestuj zmodyfikowaną aplikację. Spróbuj odpowiedzieć na jedno z pytań. Powinna pojawić się ocena, czy odpowiedź była dokładnie taka sama, jak na liście AnswerList. Sprawdź zarówno prawidłowe, jak i nieprawidłowe odpowiedzi (Uwaga - uwzględniana jest wielkość liter!). Kliknij przycisk NextButton i odpowiedz na drugie pytanie. Czy aplikacja nadal działa? Powinna, ale zauważ, że gdy klikniesz przycisk NextButton, tekst Dobrze! lub Źle oraz poprzednia odpowiedź nadal będą wyświetlane. Choć nie wpływa to zasadniczo na naszą grę, to takie szczegóły interfejsu z pewnością zostaną zauważone przez użytkowników Twojej aplikacji.<br />
<br />
Aby wyzerować etykietę RightWrongLabel i AnswerText, umieść poniższe bloki w bloku obsługi zdarzeń When NextButton.click:<br />
{| class="wikitable"<br />
!Typ bloku<br />
!Kategoria<br />
!Działanie<br />
|-<br />
|set RightWrongLabel.Text to<br />
|RightWrongLabel<br />
|Ustawia wartość etykiety na…<br />
|-<br />
|„ „<br />
|Text<br />
|pusty tekst<br />
|-<br />
|set AnswerText.Text to<br />
|AnswerText<br />
|Ustawia wartość etykiety na…<br />
|-<br />
|„ „<br />
|Text<br />
|pusty tekst<br />
|}<br />
Bloki powinny wyglądać następująco:<br />
<br />
===Jak działają bloki?===<br />
Po kliknięciu przycisku NextButton użytkownik przechodzi do następnego pytania, dlatego początkowe wiersze bloku obsługi zdarzeń zerują etykietę RightWrongLabel i pole AnswerText.<br />
Przetestuj to zachowanie Odpowiedz na pytanie i kliknij przycisk Wyślij, a następnie - NextButton. Czy Twoja poprzednia odpowiedź i jej ocena zniknęły?<br />
<br />
==Ostateczna postać programu==<br />
Oto gotowa aplikacja QuizMe:<br />
<br />
Utwórz wykonywalną wersję aplikacji, wybierając menu Build/App (provide QR code for .apk). Gdy pojawi się kod kreskowy, użyj czytnika kodów w telefonie, aby pobrać i zainstalować aplikację.<br />
<br />
===Modyfikacje===<br />
Quiz w tej wersji jest już gotowy. Czy masz ochotę przemyśleć pewne zmiany?<br />
<br />
Zamiast wyświetlać zdjęcie dla każdego pytania, spróbuj odtworzyć dźwięk lub krótkie wideo. Za pomocą dźwięku możesz zmienić quiz w aplikację Jaka to melodia?.<br />
<br />
Quiz akceptuje ściśle określone odpowiedzi. Jeśli gracz odpowiedziałby, lekko przekształcając tekst (np. podając inicjał zamiast imienia), program uzna to za błąd. Można to zmienić na kilka różnych sposobów. Jednym z nich jest użycie bloku text.contains, aby sprawdzić, czy odpowiedź użytkownika zawiera prawidłową odpowiedź. Inny sposób to dostarczenie wielu odpowiedzi na każde pytanie i sprawdzenie przez iterację (użycie bloku for each), czy któraś z nich pasuje.<br />
<br />
Przekształć quiz tak, aby przedstawiał odpowiedzi do wyboru. Lista odpowiedzi będzie musiała być listą list, a każda podrzędna lista będzie musiała zawierać opcje odpowiedzi. Użyj komponentu ListPicker, aby umożliwić użytkownikowi wybranie odpowiedzi.<br />
<br />
<br />
==Podsumowanie==<br />
Oto niektóre koncepcje omówione w tym przewodniku:<br />
<ul><li>Aplikacje można tworzyć w sposób ogólny, aby pracować z dowolną listą danych.</li><br />
<li>Zmienne indeksu są wykorzystywane do śledzenia bieżącej pozycji na liście. Zwiększając wartość zmiennej indeksu, należy uważać na przekroczenie końca listy.</li></ul><br />
<br />
==Zeskanuj próbną aplikację do telefonu==<br />
Aby zainstalować i uruchomić aplikację próbną, zeskanuj poniższy kod kreskowy:<br />
<br />
==Pobierz kod źródłowy==<br />
Jeżeli chcesz pracować z tą próbką w programie App Inventor:<br />
<ul><li>pobierz na komputer kod źródłowy: [http://appinventor.mit.edu/explore/sites/all/files/ai2tutorials/QuizMe/QuizMe_MIT.aia http://appinventor.mit.edu/explore/sites/all/files/ai2tutorials/QuizMe/QuizMe_MIT.aia]</li><br />
<li>otwórz program App Inventor,</li><br />
<li>kliknij opcję My Projects,</li><br />
<li>wybierz Import project (.aia) from my computer...</li><br />
<li>znajdź i zatwierdź pobrany kod źródłowy.</li></ul></div>M Kelniarzhttp://wiki.mistrzowiekodowania.pl/index.php?title=QuizMeQuizMe2015-03-15T18:26:25Z<p>M Kelniarz: /* Wyświetl pierwsze pytanie */</p>
<hr />
<div>=Aplikacja QuizMe dla App Inventor 2=<br />
<br />
==Co tworzysz?==<br />
[[Plik:t6-1.png|right]]QuizMe to gra dotycząca ciekawostek baseballowych, ale można jej użyć jako szablonu do tworzenia quizów z dowolnej dziedziny. W aplikacji użytkownik odpowiada na szereg pytań, otrzymując następnie informację zwrotną, czy udzielił poprawnej, czy błędnej odpowiedzi. Gracz przechodzi do kolejnego pytania, klikając przycisk.<br />
<br />
W grze QuizMe dysponujemy zamkniętym zbiorem pytań, chyba że programista je zmieni. W następnym etapie można utworzyć MakeQuiz & TakeQuiz – aplikację, która pozwala użytkownikom na tworzenie i modyfikowanie pytań.<br />
<br />
Poradnik ten zakłada, że znasz już podstawy tworzenia aplikacji w App Inventorze – korzystanie z Projektanta komponentów w celu utworzenia interfejsu użytkownika i z Edytora bloków, aby określić obsługę zdarzeń. Jeżeli potrzebujesz przypomnienia, spróbuj popracować z poradnikami podstawowymi zanim przejdziesz dalej.<br />
<br />
==Zaczynamy!==<br />
Połącz się z witryną internetową App Inventor i załóż nowy projekt. Nazwij go QuizMe, ustaw taki sam tytuł ekranu (Title). Za pomocą MIT AI2 Companion połącz program z urządzeniem mobilnym. Pobierz poniższe zdjęcia baseballistów i zapisz je w komputerze. Później załadujesz je do projektu.<br />
<ul><li> [http://beta.appinventor.mit.edu/learn/tutorials/quizme/QuizMeAssets/Larsenberra.jpg Larsenberra.jpg]</li><br />
<li> [http://beta.appinventor.mit.edu/learn/tutorials/quizme/QuizMeAssets/dallasbraden.jpg Dallasbraden.jpg]</li><br />
<li> [http://beta.appinventor.mit.edu/learn/tutorials/quizme/QuizMeAssets/cyyoung.jpg Cyyoung.jpg]</li><br />
<li> [http://beta.appinventor.mit.edu/learn/tutorials/quizme/QuizMeAssets/nolanryan.jpg Nolanryan.jpg]</li></ul><br />
<br />
==Wstęp==<br />
Zaprojektujesz grę typu quiz, w której użytkownik będzie przechodził do kolejnych pytań, klikając przycisk Dalej, a następnie otrzymywał prostą ocenę Dobrze/Źle dla każdej odpowiedzi.<br />
<br />
W tym przewodniku omówimy:<br />
<ul><li>definiowanie i wyświetlanie listy informacji;</li><br />
<li>przechodzenie przez listę za pomocą zmiennej indeksującej – zmiennej, która śledzi pozycję na liście;</li><br />
<li>zachowania warunkowe – wykonywanie określonych operacji tylko wtedy, gdy spełniony jest określony warunek;</li><br />
<li>Zmianę zdjęcia w zależności od sytuacji.</li></ul><br />
<br />
==Projektowanie aplikacji==<br />
Użyj Projektanta komponentów do utworzenia interfejsu dla aplikacji QuizMe. <br />
Aby utworzyć interfejs, najpierw załaduj do projektu pobrane zdjęcia. Kliknij przycisk Prześlij plik (Upload File...) w obszarze Media i wybierz jeden z pobranych wcześniej plików (np. Larsenberra.jpg). Następnie zrób to samo z pozostałymi trzema zdjęciami.<br />
Utwórz następujące komponenty, przeciągając je z Palety (Palette) do Przeglądarki (Viewer) i ustaw właściwości komponentów zgodnie z poniższym opisem:<br />
{|class="wikitable"<br />
! Typ komponentu<br />
! Kategoria<br />
! Jaką nadać jej nazwę<br />
! Działanie<br />
! Działanie komponentu<br />
|-<br />
|Image<br />
|User interface<br />
|Image1<br />
|Ustaw właściwość zdjęcia (Picture) na Larsenberra.jpg. Jest to pierwsze wyświetlane zdjęcie.<br />
|Obrazkowa część pytania<br />
|-<br />
|Label<br />
|User interface<br />
|QuestionLabel<br />
|Zmień właściwość tekstu (Text) na Pytanie:<br />
|Wyświetla bieżące pytanie<br />
|-<br />
|HorizontalArrangement<br />
|Layout<br />
|HorizontalArrangement1<br />
| <br />
|Organizuje komponenty AnswerPrompt i Text (podaj odpowiedź i tekst)<br />
|-<br />
|Label<br />
|User interface<br />
|AnswerPromptLabel<br />
|Zmień właściwość tekstu (Text) na Podaj odpowiedź:. Na ekranie przeglądarki przesuń tę etykietę do HorizontalArrangement1.<br />
|Wyświetla tekst prośby o odpowiedź.<br />
|-<br />
|TextBox<br />
|User interface<br />
|AnswerText<br />
|Zmień wskazówkę (Hint) na Podaj odpowiedź. Na ekranie przeglądarki przenieś AnswerText do komponentu HorizontalArrangement1.<br />
|Tutaj użytkownik podaje odpowiedź.<br />
|-<br />
|Label<br />
|User interface <br />
|RightWrongLabel<br />
|Zmień właściwość tekstu (Text) na Dobrze/Źle.<br />
|Tutaj wyświetlana jest ocena Dobrze/Źle.<br />
|-<br />
|HorizontalArrangement<br />
|Layout<br />
|HorizontalArrangement2<br />
|<br />
|Organizuje przyciski AnswerButton i NextButton (przycisk odpowiedzi i przycisk dalej).<br />
|-<br />
|Przycisk<br />
|User interface<br />
|AnswerButton<br />
|Zmień właściwość tekstu (Text) na Wyślij. Na ekranie przeglądarki przesuń ten przycisk do HorizontalArrangment2.<br />
|Użytkownik klika, aby przesłać odpowiedź.<br />
|-<br />
|Przycisk<br />
|User interface<br />
|NextButton<br />
|Zmień właściwość tekstu (Text) na Dalej. Przenieś ten przycisk do HorizontalArrangement2.<br />
|Użytkownik klika, aby przejść do następnego pytania.<br />
|} <br />
Po zakończeniu powinien on wyglądać jak poniższa ilustracja (pod nią znajdują się również bardziej szczegółowe informacje).<br />
[[Plik:t6-2.png]]<br />
<br />
==Programowanie aplikacji==<br />
Otwórz Edytor bloków, aby zaprogramować działanie komponentów. Najpierw zdefiniuj dwie zmienne - listy: zmienną QuestionList, zawierającą listę pytań i zmienną AnswerList z listą odpowiedzi na te pytania.<br />
<br />
Aby zdefiniować te dwie zmienne listy, potrzebujesz następujących bloków:<br />
{| class="wikitable"<br />
!Typ bloku<br />
!Kategoria<br />
!Działanie<br />
|-<br />
|initialize global name to<br />
|Variables<br />
|Definiuje zmienną QuestionList (zmień jej nazwę)<br />
|-<br />
|initialize global name to<br />
|Variables<br />
|Definiuje zmienną AnswerList (zmień jej nazwę)<br />
|-<br />
|make a list<br />
|Lists<br />
|Służy do dodawania elementów do zmiennej QuestionList<br />
|-<br />
|„ „ (trzykrotnie)<br />
|Lists<br />
|Służy do wpisania pytań<br />
|-<br />
|make a list<br />
|Lists<br />
|Służy do dodawania elementów do zmiennej AnswerList<br />
|-<br />
|„ „ (trzykrotnie)<br />
|Text<br />
|Służy do wpisania odpowiedzi<br />
|}<br />
Utwórz zmienne całościowe, przeciągając z kategorii zmiennych (Variables) na obszar roboczy blok Initialize global name to. Kliknij dwukrotnie domyślną nazwę name, aby ją zmienić. Blok Initialize global name to zawiera pole na początkową wartość zmiennej. Zmienna może zawierać liczbę, tekst, a nawet listę – aby ją utworzyć, podłącz blok Make a list do definicji zmiennej.<br />
<br />
Bloki powinny wyglądać następująco:<br />
===Zdefiniuj ukrytą zmienną Index===<br />
Za każdym razem, gdy użytkownik kliknie przycisk NextButton, aby przejść dalej, aplikacja musi pamiętać, przy którym pytaniu jest obecnie gracz. W języku programowania, aby coś zapamiętać, trzeba zdefiniować nową zmienną. W tym przypadku aplikacja musi zapamiętać bieżący numer pytania – indeks listy QuestionList.<br />
Aby zdefiniować zmienną currentQuestionIndex, potrzebujesz następujących bloków:<br />
{| class="wikitable"<br />
!Typ bloku<br />
!Kategoria<br />
!Działanie<br />
|-<br />
|initialize global name to<br />
|Variables<br />
|Definiuje zmienną currentQuestionIndex (zmień nazwę)<br />
|-<br />
|0 (1)<br />
|Math<br />
|Ustaw wartość początkową currentQuestionIndex na 1 (zmień liczbę)<br />
|}<br />
Bloki powinny wyglądać następująco:<br />
<br />
[[Plik:t6-3.png]]<br />
<br />
===Wyświetl pierwsze pytanie===<br />
Odłóż na razie kwestię odpowiedzi i skup się na zaprogramowaniu sekwencyjnego przejścia przez pytania. Pożądane zachowanie jest następujące: po uruchomieniu aplikacji na etykiecie o nazwie QuestionLabel pojawia się pierwsze pytanie. Gdy użytkownik kliknie NextButton, wyświetlone zostaje drugie pytanie. Po ponownym kliknięciu pojawia się trzecie pytanie. Po dotarciu do ostatniego pytania kliknięcie przycisku NextButton powoduje ponowne pojawienie się pierwszego pytania w etykiecie QuestionLabel.<br />
<br />
W programie App Inventor określone pozycje na liście są wybierane za pomocą bloku select list item. W tym bloku trzeba podać listę i indeks – pozycję na liście. Jeżeli na liście są trzy pozycje, prawidłowe indeksy to 1, 2 i 3.<br />
<br />
Po uruchomieniu aplikacja QuizMe powinna wybrać pierwsze pytanie z listy i wyświetlić je w komponencie QuestionLabel. Do tego zachowania inicjalizującego działanie aplikacji potrzebne są następujące bloki:<br />
<br />
{| class="wikitable"<br />
!Typ bloku<br />
!Kategoria<br />
!Działanie<br />
|-<br />
|when Screen1.Initialize<br />
|Screen1<br />
|Podczas uruchamiania aplikacji zainicjowana jest ta obsługa zdarzenia<br />
|-<br />
|set QuestionLabel.Text to<br />
|QuestionLabel<br />
|Umieszcza pierwsze pytanie w etykiecie QuestionLabel<br />
|-<br />
|select list item<br />
|Lists<br />
|Wybiera pierwsze pytanie z etykiety QuestionLabel<br />
|-<br />
|get <br />
|Variables<br />
|Ustala listę, z której jest wybierany element. Tutaj: Global QuestionList<br />
|-<br />
|0 (1)<br />
|Math<br />
|Wybiera pierwsze pytanie za pomocą indeksu 1. Ustaw wartość na 1.<br />
|}<br />
Bloki powinny wyglądać następująco:<br />
<br />
[[Plik:t6-4.png]]<br />
<br />
===Jak działają bloki?===<br />
Zdarzenie when Screen1.Initialize jest wyzwalane podczas uruchomienia aplikacji. Pierwsza pozycja zmiennej QuestionList zostaje wybrana i umieszczona w bloku set QuestionLabel.Text. Gdy aplikacja zostanie uruchomiona, użytkownik zobaczy pierwsze pytanie.<br />
===Przetestuj to zachowanie===<br />
Jeśli dotychczas nie skomunikowałeś urządzenia mobilnego z programem, zrób to teraz. Co pojawia się na urządzeniu? Jeżeli utworzono listę QuestionList tak, jak wskazano powyżej, w etykiecie QuestionLabel powinna pojawić się pierwsza pozycja tej listy (Kto był doskonałym miotaczem w World Series?).<br />
<br />
==Iteracja pytań==<br />
Zdefiniowałeś już zmienną CurrentQuestionIndex, zapamiętującą pytanie, przy którym znajduje się użytkownik. Zaprogramuj teraz zachowanie przycisku NextButton. Gdy zostanie on kliknięty, aplikacja zwiększy wartość zmiennej, np. zmieni ją z 1 na 2 lub z 2 na 3 itd., a następnie użyje tej wartości do zaznaczenia nowego bieżącego pytania. Do tego zachowania potrzebne są następujące bloki:<br />
{| class="wikitable"<br />
!Typ bloku<br />
!Kategoria<br />
!Działanie<br />
|-<br />
|when NextButton.Click<br />
|NextButton<br />
|Uruchamia obsługę zdarzeń po kliknięciu przycisku<br />
|-<br />
|set currentQuestionIndex to<br />
|Zmienne<br />
|Decyduje o ustawieniu indeksu wybranej listy<br />
|-<br />
|+ <br />
|Math<br />
|Służy do zwiększania wartości zmiennej currentQuestionIndex<br />
|-<br />
|get global currentQuestionIndex<br />
|Zmienne<br />
|Tworzy nową wartość poprzez zwiększenie poprzedniej wartości o 1<br />
|-<br />
|0 (1)<br />
|Math<br />
|Dla + 1<br />
|-<br />
|set QuestionLabel.Text to<br />
|QuestionLabel<br />
|Wyświetla kolejne pytanie<br />
|-<br />
|select list item<br />
|Listy<br />
|Ustawia element listy jako wartość QuestionLabel<br />
|-<br />
|get global QuestionList<br />
|Zmienne<br />
|Wskazuje, która lista będzie wybrana<br />
|-<br />
|get global currentQuestionIndex<br />
|Zmienne<br />
|Wskazuje, który element wybranej listy będzie wybrany<br />
|}<br />
Bloki powinny wyglądać następująco:<br />
<br />
===Jak działają bloki?===<br />
Pierwszy wiersz polecenia zwiększa wartość zmiennej currentQuestionIndex o 1 (jeżeli zmienna zawiera wartość 1, zostaje ona zmieniona na 2, z 2 na 3 itd.). Następnie wykorzystuje nową wartość do wyboru pytania o tym indeksie.<br />
<br />
Przypomnijmy, że w bloku obsługi zdarzeń Screen.Initialize aplikacja wybrała pierwsze do wyświetlenia pytanie:<br />
<br />
Po kliknięciu przycisku NextButton aplikacja nie wybiera konkretnie pierwszej, drugiej czy trzeciej pozycji na liście, tylko pozycję o n-tej wartości zmiennej currentQuestionIndex.<br />
<br />
Polecenia w blokach są wykonywane od prawej do lewej, tzn. aplikacja najpierw określa wartość parametru z bloku Select list item, którym jest zmienna CurrentQuestionIndex. Liczba zawarta w tej zmiennej zostaje użyta jako indeks podczas wykonania poleceń zawartych w bloku Select list item.<br />
<br />
Po pierwszym kliknięciu przycisku NextButton, wartość zmiennej currentQuestionIndex przeskoczy z 1 na 2, aby aplikacja wybrała drugą pozycję z listy QuestionList (Kto był pierwszym doskonałym miotaczem w 2010?). Po drugim kliknięciu przycisku NextButton, wartość zmiennej currentQuestionIndex zostanie zmieniona z 2 na 3, a aplikacja wybierze trzecie pytanie z listy (Kto był pierwszym doskonałym miotaczem nowej ery?).<br />
===Przetestuj to zachowanie===<br />
Przetestuj zachowanie przycisku NextButton, aby sprawdzić, czy aplikacja działa poprawnie. Wciel się w rolę użytkownika i kliknij przycisk NextButton w telefonie. Czy urządzenie wyświetliło drugie pytanie: Kto był pierwszym doskonałym miotaczem w 2010?? Trzecie pytanie powinno pojawić się po kolejnym kliknięciu przycisku. Jeżeli aplikacja działa, pogratuluj sobie i przejdź dalej. Kliknij przycisk NextButton ponownie (po raz trzeci). Powinien zostać wyświetlony błąd: Próba uzyskania elementu 4 z listy o długości 3. Czy wiesz, na czym polega problem?<br />
<br />
Problem z aplikacją polega na tym, że zawsze po kliknięciu przycisku NextButton zwiększa ona zmienną CurrentQuestionIndex o 1. Gdy wartość zmiennej wynosi już 3, a użytkownik kolejny raz kliknie przycisk NextButton, aplikacja zmieni wartość zmiennej z 3 na 4, następnie wywoła blok Select list item, aby odczytać pozycję o aktualnym indeksie CurrentQuestionIndex, czyli w tym przypadku czwartą pozycję. Ponieważ zmienna QuestionList zawiera tylko trzy elementy, Android wykaże błąd.<br />
<br />
Aplikacja musi zadawać pytanie - sprawdzać warunek - gdy nastąpi kliknięcie przycisku NextButton i realizować polecenia zawarte w różnych blokach w zależności od odpowiedzi. Elementem do sprawdzenia jest to, czy zmienna CurrentQuestionIndex już ma wartość 3. Jeżeli tak - należy ustawić CurrentQuestionIndex z powrotem na 0, aby użytkownik wrócił do pierwszego pytania.<br />
<br />
Będziesz potrzebował następujących bloków:<br />
{| class="wikitable"<br />
!Typ bloku<br />
!Kategoria<br />
!Działanie<br />
|-<br />
|if then<br />
|Control<br />
|sprawdzenie, czy użytkownik jest na etapie ostatniego pytania<br />
|-<br />
|= <br />
|Math<br />
|sprawdzenie, czy currentQuestionIndex ma wartość 3<br />
|-<br />
|get global currentQuestionIndex<br />
|Variables<br />
|<br />
|-<br />
|0 (3)<br />
|Math<br />
|3 to numer na liście<br />
|-<br />
|set currentQuestionIndex to<br />
|Variables<br />
|ustawienie na 0, aby wrócić do pierwszego pytania<br />
|-<br />
|0<br />
|Math<br />
|ustawienie na 0, ponieważ kolejne bloki zwiększą wartość do 1<br />
|}<br />
Zmodyfikowany blok obsługi zdarzenia When NextButton.Click powinien wyglądać następująco:<br />
<br />
===Jak działają bloki===<br />
Po kliknięciu przycisku NextButton aplikacja najpierw sprawdza, czy currentQuestionIndex ma wartość 3. Jeżeli tak, wartość tej zmiennej jest ustawiana na 0, aby po zwiększeniu jej w dalszych krokach jej wartość wyniosła 1. Wtedy quiz wróci do pierwszego pytania. Zauważ, że tylko bloki osadzone w bloku if-then są zależne od warunku. Blok zwiększenia wartości i blok Set QuestionLabel.Text to są wykonywane bez względu na jakikolwiek warunek.<br />
<br />
==Aplikacja modyfikowalna: Ułatwianie modyfikowania pytań==<br />
Teraz zmodyfikujemy aplikację, aby można było łatwo dodawać i usuwać elementy z listy. Zmień bloki tak, aby działały na liście o dowolnej długości, a nie tylko liście z dokładnie trzema pozycjami. <br />
Na początek dodaj czwarte pytanie do zmiennej QuestionList i kolejną odpowiedź do AnswerList. W tym celu musisz najpierw zwiększyć liczbę dostępnych pól za pomocą przycisku modyfikującego (mutatora). Aby dowiedzieć się więcej o tym elemencie, zobacz: http://appinventor.mit.edu/explore/ai2/support/concepts/mutators. Bloki powinny wyglądać następująco:<br />
<br />
===Przetestuj zmodyfikowaną aplikację.===<br />
Kliknij przycisk NextButton kilka razy. Zauważysz, że czwarte pytanie nigdy się nie pojawia, bez względu na to, ile razy klikniesz przycisk.<br />
<br />
Problemem jest to, że test sprawdzający, czy użytkownik znajduje się przy ostatnim pytaniu, jest zbyt szczegółowy: pyta, czy zmienna CurrentQuestionIndex ma wartość 3:<br />
<br />
Możesz po prostu zmienić liczbę z 3 na 4, a aplikacja będzie znów działać poprawnie. Problem polega jednak na tym, że za każdym razem, gdy zmodyfikujesz liczbę pytań i odpowiedzi, będziesz musiał pamiętać, aby dokonać także tej zmiany. Takie zależności w programie komputerowym często prowadzą do błędów, w szczególności gdy aplikacja staje się bardziej złożona. Znacznie lepiej jest przygotować program w taki sposób, aby działał niezależnie od liczby pytań. Takie uogólnienie jest jeszcze ważniejsze, gdy lista, z którą pracujesz, zmienia się dynamicznie, na przykład w aplikacji z quizem, gdzie użytkownik może dodawać nowe pytania.<br />
<br />
Lepszym rozwiązaniem jest sprawdzenie warunku w sposób bardziej ogólny. Tak naprawdę chcesz wiedzieć, czy bieżące pytanie – czyli wartość zmiennej currentQuestionIndex jest tak duża, jak ilość elementów w zmiennej QuestionList. Jeżeli aplikacja sprawdzi warunek w bardziej ogólny sposób, to będzie działać, nawet jeżeli dodasz lub usuniesz elementy ze zmiennej QuestionList. Aby zmienić blok obsługi zdarzenia When NextButton.Click, zmień poprzedni test sprawdzający, który odnosił się bezpośrednio do 3. Będziesz potrzebował następujących bloków:<br />
{| class="wikitable"<br />
!Typ bloku<br />
!Szuflada<br />
!Działanie<br />
|-<br />
|length of list<br />
|Lists<br />
|Pyta, ile elementów jest w zmiennej QuestionList<br />
|-<br />
|get global QuestionList<br />
|Variables<br />
|Określa, o którą listę chodzi<br />
|}<br />
Blok obsługi zdarzenia When NextButton.Click powinien teraz wyglądać następująco:<br />
<br />
<br />
===Jak działają bloki?===<br />
Warunek if porównuje teraz wartość zmiennej CurrentQuestionIndex z długością zmiennej QuestionList. Zatem jeżeli zmienna CurrentQuestionIndex ma wartość 4, a długość zmiennej QuestionList wynosi 4, to wartość zmiennej currentQuestionIndex zostanie ustawiona na 0 (a następnie na 1, 2 itd.). Zauważ - bloki nie odwołują się już do 3 ani żadnej innej określonej wartości, dlatego instrukcja będzie działać bez względu na liczbę elementów listy.<br />
<br />
Przetestuj zmodyfikowane zachowanie. Czy po kliknięciu przycisku NextButton aplikacja przechodzi teraz przez cztery pytania, wracając po ostatnim do pierwszego?<br />
<br />
==Przełączanie zdjęcia dla każdego pytania==<br />
Na razie aplikacja wyświetla to samo zdjęcie, bez względu na to, jakie pytanie zostaje zadane. Możesz to zmienić tak, aby po kliknięciu przycisku NextButton pojawiała się fotografia dotycząca danego pytania. W obszarze Media dostępne są cztery dodane wcześniej zdjęcia. Teraz utworzymy trzecią listę - PictureList, której elementami będą nazwy plików zdjęć, a następnie zmodyfikujemy blok obsługi zdarzenia When NextButton.Click, aby program po każdym pytaniu przełączał zdjęcie.<br />
Najpierw utwórz listę PictureList i zainicjuj ją nazwami plików graficznych. Upewnij się, czy nazwy są dokładnie takie same jak nazwy plików, które zostały załadowane do obszaru Media. Oto jak powinien wyglądać blok dla listy PictureList:<br />
<br />
Następnie zmodyfikuj blok obsługi zdarzeń When NextButton.Click, aby zmieniał wyświetlane zdjęcie w zależności od zadanego pytania. Jeżeli ustawisz właściwość Image.Picture na nazwę pliku zdjęcia, które zostało załadowane, właśnie ta fotografia zostanie wyświetlona. Aby zmodyfikować blok When NextButton.Click, potrzebujesz następujących bloków:<br />
{| class="wikitable"<br />
!Typ bloku<br />
!Kategoria<br />
!Działanie<br />
|-<br />
|set Image1.Picture to<br />
|Image1<br />
|ustaw, aby zmieniać zdjęcie<br />
|-<br />
|select list item<br />
|Lists<br />
|należy wybrać zdjęcie odpowiadające na aktualne pytanie<br />
|-<br />
|get global PictureList<br />
|Variables<br />
|wybierz nazwę pliku z tej listy<br />
|-<br />
|get global currentQuestionIndex<br />
|Variables<br />
|wybierz element o n-tym indeksie currentQuestionIndex<br />
|}<br />
Oto jak powinny wyglądać bloki:<br />
<br />
===Jak działają bloki?===<br />
Zmienna CurrentQuestionIndex służy jako indeks dla zmiennej QuestionList. Wartość CurrentQuestionIndex wynosi 1, aplikacja wybiera pierwsze pytanie i pierwsze zdjęcie. Gdy CurrentQuestionIndex wynosi 2, aplikacja wybiera drugie pytanie i drugie zdjęcie. Oczywiście takie działanie zależy od tego, czy listy są ze sobą zsynchronizowane. Tak jest w tym przypadku - pierwszy obraz - LarsenBerra.jpg to zdjęcie Dona Larsena, jednocześnie Don Larsen to odpowiedź na pierwsze pytanie (Kto był doskonałym miotaczem w World Series?). <br />
Przetestuj zmodyfikowane zachowanie. Czy nowe zdjęcie pojawia się po każdym kliknięciu przycisku NextButton?<br />
<br />
==Ocena udzielanych odpowiedzi==<br />
Teraz dodamy bloki, które określają, czy użytkownik odpowiedział na pytanie prawidłowo, czy też nie. Gracz wprowadza odpowiedź do AnswerText, a następnie klika przycisk AnswerButton. Aplikacja musi porównać wpis użytkownika z odpowiedzią na bieżące pytanie, używając bloku if... then... w celu jej sprawdzenia. Etykieta RightWrongLabel powinna być modyfikowana, aby podawać, czy odpowiedź jest prawidłowa, czy nie.<br />
<br />
Do tego zachowania będą potrzebne następujące bloki:<br />
{| class="wikitable"<br />
!Typ bloku<br />
!Kategoria<br />
!Działanie<br />
|-<br />
|when AnswerButton.Click<br />
|AnswerButton<br />
|zachowanie jest wyzwalane, gdy użytkownik kliknie przycisk AnswerButton<br />
|-<br />
|if... then...<br />
|Control<br />
|Użyj mutatora, aby dodać alternatywę (else). Jeżeli odpowiedź jest prawidłowa - zrób jedno, w przeciwnym razie (else) - zrób coś innego<br />
|-<br />
|= <br />
|Math<br />
|sprawdzenie, czy odpowiedź jest prawidłowa<br />
|-<br />
|AnswerText.Text<br />
|AnswerText<br />
|Odpowiedź użytkownika pojawia się w tym polu tekstowym<br />
|-<br />
|select list item<br />
|Lists<br />
|wybrać bieżącą odpowiedź z listy AnswerList<br />
|-<br />
|get global AnswerList<br />
|Variables<br />
|lista, z której jest wybierany element<br />
|-<br />
|get global currentQuestionIndex<br />
|Variables<br />
|numer pytania (i numer odpowiedzi), przy którym jest użytkownik<br />
|-<br />
|set RightWrongLabel.Text to<br />
|RightWrongLabel<br />
|tutaj podaj odpowiedź<br />
|-<br />
|Dobrze!<br />
|Text<br />
|jeżeli odpowiedź jest prawidłowa<br />
|-<br />
|set RightWrongLabel.Text to<br />
|RightWrongLabel<br />
|tutaj podaj odpowiedź<br />
|-<br />
|Źle<br />
|Text<br />
|jeżeli odpowiedź jest nieprawidłowa<br />
|}<br />
Bloki powinny wyglądać następująco:<br />
<br />
===Jak działają bloki?===<br />
Test if sprawdza, czy odpowiedź użytkownika (AnswerText.Text) jest taka sama, jak element na liście AnswerList o indeksie równym wartości zmiennej CurrentQuestionIndex. Jeżeli zmienna CurrentQuestionIndex ma wartość 1, aplikacja porównuje odpowiedź użytkownika z pierwszą pozycją na liście AnswerList, (Don Larsen). Jeżeli zmienna CurrentQuestionIndex zmieni wartość na 2, program zestawia odpowiedź z drugą pozycją na liście, czyli Dallas Branden. Jeśli wynik porównania jest pozytywny, przeprowadzane są bloki then, a treść etykiety RightWrongLabel zostaje ustawiona na Dobrze!. Jeżeli wynik testu jest negatywny (fałszywy), przeprowadzane są bloki alternatywy (else), a treść etykiety RightWrongLabel zostaje ustawiona na Źle.<br />
<br />
Przetestuj zmodyfikowaną aplikację. Spróbuj odpowiedzieć na jedno z pytań. Powinna pojawić się ocena, czy odpowiedź była dokładnie taka sama, jak na liście AnswerList. Sprawdź zarówno prawidłowe, jak i nieprawidłowe odpowiedzi (Uwaga - uwzględniana jest wielkość liter!). Kliknij przycisk NextButton i odpowiedz na drugie pytanie. Czy aplikacja nadal działa? Powinna, ale zauważ, że gdy klikniesz przycisk NextButton, tekst Dobrze! lub Źle oraz poprzednia odpowiedź nadal będą wyświetlane. Choć nie wpływa to zasadniczo na naszą grę, to takie szczegóły interfejsu z pewnością zostaną zauważone przez użytkowników Twojej aplikacji.<br />
<br />
Aby wyzerować etykietę RightWrongLabel i AnswerText, umieść poniższe bloki w bloku obsługi zdarzeń When NextButton.click:<br />
{| class="wikitable"<br />
!Typ bloku<br />
!Kategoria<br />
!Działanie<br />
|-<br />
|set RightWrongLabel.Text to<br />
|RightWrongLabel<br />
|Ustawia wartość etykiety na…<br />
|-<br />
|„ „<br />
|Text<br />
|pusty tekst<br />
|-<br />
|set AnswerText.Text to<br />
|AnswerText<br />
|Ustawia wartość etykiety na…<br />
|-<br />
|„ „<br />
|Text<br />
|pusty tekst<br />
|}<br />
Bloki powinny wyglądać następująco:<br />
<br />
===Jak działają bloki?===<br />
Po kliknięciu przycisku NextButton użytkownik przechodzi do następnego pytania, dlatego początkowe wiersze bloku obsługi zdarzeń zerują etykietę RightWrongLabel i pole AnswerText.<br />
Przetestuj to zachowanie Odpowiedz na pytanie i kliknij przycisk Wyślij, a następnie - NextButton. Czy Twoja poprzednia odpowiedź i jej ocena zniknęły?<br />
<br />
==Ostateczna postać programu==<br />
Oto gotowa aplikacja QuizMe:<br />
<br />
Utwórz wykonywalną wersję aplikacji, wybierając menu Build/App (provide QR code for .apk). Gdy pojawi się kod kreskowy, użyj czytnika kodów w telefonie, aby pobrać i zainstalować aplikację.<br />
<br />
===Modyfikacje===<br />
Quiz w tej wersji jest już gotowy. Czy masz ochotę przemyśleć pewne zmiany?<br />
<br />
Zamiast wyświetlać zdjęcie dla każdego pytania, spróbuj odtworzyć dźwięk lub krótkie wideo. Za pomocą dźwięku możesz zmienić quiz w aplikację Jaka to melodia?.<br />
<br />
Quiz akceptuje ściśle określone odpowiedzi. Jeśli gracz odpowiedziałby, lekko przekształcając tekst (np. podając inicjał zamiast imienia), program uzna to za błąd. Można to zmienić na kilka różnych sposobów. Jednym z nich jest użycie bloku text.contains, aby sprawdzić, czy odpowiedź użytkownika zawiera prawidłową odpowiedź. Inny sposób to dostarczenie wielu odpowiedzi na każde pytanie i sprawdzenie przez iterację (użycie bloku for each), czy któraś z nich pasuje.<br />
<br />
Przekształć quiz tak, aby przedstawiał odpowiedzi do wyboru. Lista odpowiedzi będzie musiała być listą list, a każda podrzędna lista będzie musiała zawierać opcje odpowiedzi. Użyj komponentu ListPicker, aby umożliwić użytkownikowi wybranie odpowiedzi.<br />
<br />
<br />
==Podsumowanie==<br />
Oto niektóre koncepcje omówione w tym przewodniku:<br />
<ul><li>Aplikacje można tworzyć w sposób ogólny, aby pracować z dowolną listą danych.</li><br />
<li>Zmienne indeksu są wykorzystywane do śledzenia bieżącej pozycji na liście. Zwiększając wartość zmiennej indeksu, należy uważać na przekroczenie końca listy.</li></ul><br />
<br />
==Zeskanuj próbną aplikację do telefonu==<br />
Aby zainstalować i uruchomić aplikację próbną, zeskanuj poniższy kod kreskowy:<br />
<br />
==Pobierz kod źródłowy==<br />
Jeżeli chcesz pracować z tą próbką w programie App Inventor:<br />
<ul><li>pobierz na komputer kod źródłowy: [http://appinventor.mit.edu/explore/sites/all/files/ai2tutorials/QuizMe/QuizMe_MIT.aia http://appinventor.mit.edu/explore/sites/all/files/ai2tutorials/QuizMe/QuizMe_MIT.aia]</li><br />
<li>otwórz program App Inventor,</li><br />
<li>kliknij opcję My Projects,</li><br />
<li>wybierz Import project (.aia) from my computer...</li><br />
<li>znajdź i zatwierdź pobrany kod źródłowy.</li></ul></div>M Kelniarzhttp://wiki.mistrzowiekodowania.pl/index.php?title=QuizMeQuizMe2015-03-15T18:26:03Z<p>M Kelniarz: /* Zdefiniuj ukrytą zmienną Index */</p>
<hr />
<div>=Aplikacja QuizMe dla App Inventor 2=<br />
<br />
==Co tworzysz?==<br />
[[Plik:t6-1.png|right]]QuizMe to gra dotycząca ciekawostek baseballowych, ale można jej użyć jako szablonu do tworzenia quizów z dowolnej dziedziny. W aplikacji użytkownik odpowiada na szereg pytań, otrzymując następnie informację zwrotną, czy udzielił poprawnej, czy błędnej odpowiedzi. Gracz przechodzi do kolejnego pytania, klikając przycisk.<br />
<br />
W grze QuizMe dysponujemy zamkniętym zbiorem pytań, chyba że programista je zmieni. W następnym etapie można utworzyć MakeQuiz & TakeQuiz – aplikację, która pozwala użytkownikom na tworzenie i modyfikowanie pytań.<br />
<br />
Poradnik ten zakłada, że znasz już podstawy tworzenia aplikacji w App Inventorze – korzystanie z Projektanta komponentów w celu utworzenia interfejsu użytkownika i z Edytora bloków, aby określić obsługę zdarzeń. Jeżeli potrzebujesz przypomnienia, spróbuj popracować z poradnikami podstawowymi zanim przejdziesz dalej.<br />
<br />
==Zaczynamy!==<br />
Połącz się z witryną internetową App Inventor i załóż nowy projekt. Nazwij go QuizMe, ustaw taki sam tytuł ekranu (Title). Za pomocą MIT AI2 Companion połącz program z urządzeniem mobilnym. Pobierz poniższe zdjęcia baseballistów i zapisz je w komputerze. Później załadujesz je do projektu.<br />
<ul><li> [http://beta.appinventor.mit.edu/learn/tutorials/quizme/QuizMeAssets/Larsenberra.jpg Larsenberra.jpg]</li><br />
<li> [http://beta.appinventor.mit.edu/learn/tutorials/quizme/QuizMeAssets/dallasbraden.jpg Dallasbraden.jpg]</li><br />
<li> [http://beta.appinventor.mit.edu/learn/tutorials/quizme/QuizMeAssets/cyyoung.jpg Cyyoung.jpg]</li><br />
<li> [http://beta.appinventor.mit.edu/learn/tutorials/quizme/QuizMeAssets/nolanryan.jpg Nolanryan.jpg]</li></ul><br />
<br />
==Wstęp==<br />
Zaprojektujesz grę typu quiz, w której użytkownik będzie przechodził do kolejnych pytań, klikając przycisk Dalej, a następnie otrzymywał prostą ocenę Dobrze/Źle dla każdej odpowiedzi.<br />
<br />
W tym przewodniku omówimy:<br />
<ul><li>definiowanie i wyświetlanie listy informacji;</li><br />
<li>przechodzenie przez listę za pomocą zmiennej indeksującej – zmiennej, która śledzi pozycję na liście;</li><br />
<li>zachowania warunkowe – wykonywanie określonych operacji tylko wtedy, gdy spełniony jest określony warunek;</li><br />
<li>Zmianę zdjęcia w zależności od sytuacji.</li></ul><br />
<br />
==Projektowanie aplikacji==<br />
Użyj Projektanta komponentów do utworzenia interfejsu dla aplikacji QuizMe. <br />
Aby utworzyć interfejs, najpierw załaduj do projektu pobrane zdjęcia. Kliknij przycisk Prześlij plik (Upload File...) w obszarze Media i wybierz jeden z pobranych wcześniej plików (np. Larsenberra.jpg). Następnie zrób to samo z pozostałymi trzema zdjęciami.<br />
Utwórz następujące komponenty, przeciągając je z Palety (Palette) do Przeglądarki (Viewer) i ustaw właściwości komponentów zgodnie z poniższym opisem:<br />
{|class="wikitable"<br />
! Typ komponentu<br />
! Kategoria<br />
! Jaką nadać jej nazwę<br />
! Działanie<br />
! Działanie komponentu<br />
|-<br />
|Image<br />
|User interface<br />
|Image1<br />
|Ustaw właściwość zdjęcia (Picture) na Larsenberra.jpg. Jest to pierwsze wyświetlane zdjęcie.<br />
|Obrazkowa część pytania<br />
|-<br />
|Label<br />
|User interface<br />
|QuestionLabel<br />
|Zmień właściwość tekstu (Text) na Pytanie:<br />
|Wyświetla bieżące pytanie<br />
|-<br />
|HorizontalArrangement<br />
|Layout<br />
|HorizontalArrangement1<br />
| <br />
|Organizuje komponenty AnswerPrompt i Text (podaj odpowiedź i tekst)<br />
|-<br />
|Label<br />
|User interface<br />
|AnswerPromptLabel<br />
|Zmień właściwość tekstu (Text) na Podaj odpowiedź:. Na ekranie przeglądarki przesuń tę etykietę do HorizontalArrangement1.<br />
|Wyświetla tekst prośby o odpowiedź.<br />
|-<br />
|TextBox<br />
|User interface<br />
|AnswerText<br />
|Zmień wskazówkę (Hint) na Podaj odpowiedź. Na ekranie przeglądarki przenieś AnswerText do komponentu HorizontalArrangement1.<br />
|Tutaj użytkownik podaje odpowiedź.<br />
|-<br />
|Label<br />
|User interface <br />
|RightWrongLabel<br />
|Zmień właściwość tekstu (Text) na Dobrze/Źle.<br />
|Tutaj wyświetlana jest ocena Dobrze/Źle.<br />
|-<br />
|HorizontalArrangement<br />
|Layout<br />
|HorizontalArrangement2<br />
|<br />
|Organizuje przyciski AnswerButton i NextButton (przycisk odpowiedzi i przycisk dalej).<br />
|-<br />
|Przycisk<br />
|User interface<br />
|AnswerButton<br />
|Zmień właściwość tekstu (Text) na Wyślij. Na ekranie przeglądarki przesuń ten przycisk do HorizontalArrangment2.<br />
|Użytkownik klika, aby przesłać odpowiedź.<br />
|-<br />
|Przycisk<br />
|User interface<br />
|NextButton<br />
|Zmień właściwość tekstu (Text) na Dalej. Przenieś ten przycisk do HorizontalArrangement2.<br />
|Użytkownik klika, aby przejść do następnego pytania.<br />
|} <br />
Po zakończeniu powinien on wyglądać jak poniższa ilustracja (pod nią znajdują się również bardziej szczegółowe informacje).<br />
[[Plik:t6-2.png]]<br />
<br />
==Programowanie aplikacji==<br />
Otwórz Edytor bloków, aby zaprogramować działanie komponentów. Najpierw zdefiniuj dwie zmienne - listy: zmienną QuestionList, zawierającą listę pytań i zmienną AnswerList z listą odpowiedzi na te pytania.<br />
<br />
Aby zdefiniować te dwie zmienne listy, potrzebujesz następujących bloków:<br />
{| class="wikitable"<br />
!Typ bloku<br />
!Kategoria<br />
!Działanie<br />
|-<br />
|initialize global name to<br />
|Variables<br />
|Definiuje zmienną QuestionList (zmień jej nazwę)<br />
|-<br />
|initialize global name to<br />
|Variables<br />
|Definiuje zmienną AnswerList (zmień jej nazwę)<br />
|-<br />
|make a list<br />
|Lists<br />
|Służy do dodawania elementów do zmiennej QuestionList<br />
|-<br />
|„ „ (trzykrotnie)<br />
|Lists<br />
|Służy do wpisania pytań<br />
|-<br />
|make a list<br />
|Lists<br />
|Służy do dodawania elementów do zmiennej AnswerList<br />
|-<br />
|„ „ (trzykrotnie)<br />
|Text<br />
|Służy do wpisania odpowiedzi<br />
|}<br />
Utwórz zmienne całościowe, przeciągając z kategorii zmiennych (Variables) na obszar roboczy blok Initialize global name to. Kliknij dwukrotnie domyślną nazwę name, aby ją zmienić. Blok Initialize global name to zawiera pole na początkową wartość zmiennej. Zmienna może zawierać liczbę, tekst, a nawet listę – aby ją utworzyć, podłącz blok Make a list do definicji zmiennej.<br />
<br />
Bloki powinny wyglądać następująco:<br />
===Zdefiniuj ukrytą zmienną Index===<br />
Za każdym razem, gdy użytkownik kliknie przycisk NextButton, aby przejść dalej, aplikacja musi pamiętać, przy którym pytaniu jest obecnie gracz. W języku programowania, aby coś zapamiętać, trzeba zdefiniować nową zmienną. W tym przypadku aplikacja musi zapamiętać bieżący numer pytania – indeks listy QuestionList.<br />
Aby zdefiniować zmienną currentQuestionIndex, potrzebujesz następujących bloków:<br />
{| class="wikitable"<br />
!Typ bloku<br />
!Kategoria<br />
!Działanie<br />
|-<br />
|initialize global name to<br />
|Variables<br />
|Definiuje zmienną currentQuestionIndex (zmień nazwę)<br />
|-<br />
|0 (1)<br />
|Math<br />
|Ustaw wartość początkową currentQuestionIndex na 1 (zmień liczbę)<br />
|}<br />
Bloki powinny wyglądać następująco:<br />
<br />
[[Plik:t6-3.png]]<br />
<br />
===Wyświetl pierwsze pytanie===<br />
Odłóż na razie kwestię odpowiedzi i skup się na zaprogramowaniu sekwencyjnego przejścia przez pytania. Pożądane zachowanie jest następujące: po uruchomieniu aplikacji na etykiecie o nazwie QuestionLabel pojawia się pierwsze pytanie. Gdy użytkownik kliknie NextButton, wyświetlone zostaje drugie pytanie. Po ponownym kliknięciu pojawia się trzecie pytanie. Po dotarciu do ostatniego pytania kliknięcie przycisku NextButton powoduje ponowne pojawienie się pierwszego pytania w etykiecie QuestionLabel.<br />
<br />
W programie App Inventor określone pozycje na liście są wybierane za pomocą bloku select list item. W tym bloku trzeba podać listę i indeks – pozycję na liście. Jeżeli na liście są trzy pozycje, prawidłowe indeksy to 1, 2 i 3.<br />
<br />
Po uruchomieniu aplikacja QuizMe powinna wybrać pierwsze pytanie z listy i wyświetlić je w komponencie QuestionLabel. Do tego zachowania inicjalizującego działanie aplikacji potrzebne są następujące bloki:<br />
<br />
{| class="wikitable"<br />
!Typ bloku<br />
!Kategoria<br />
!Działanie<br />
|-<br />
|when Screen1.Initialize<br />
|Screen1<br />
|Podczas uruchamiania aplikacji zainicjowana jest ta obsługa zdarzenia<br />
|-<br />
|set QuestionLabel.Text to<br />
|QuestionLabel<br />
|Umieszcza pierwsze pytanie w etykiecie QuestionLabel<br />
|-<br />
|select list item<br />
|Lists<br />
|Wybiera pierwsze pytanie z etykiety QuestionLabel<br />
|-<br />
|get <br />
|Variables<br />
|Ustala listę, z której jest wybierany element. Tutaj: Global QuestionList<br />
|-<br />
|0 (1)<br />
|Math<br />
|Wybiera pierwsze pytanie za pomocą indeksu 1. Ustaw wartość na 1.<br />
|}<br />
Bloki powinny wyglądać następująco:<br />
[[Plik:t6-3.png]]<br />
<br />
===Jak działają bloki?===<br />
Zdarzenie when Screen1.Initialize jest wyzwalane podczas uruchomienia aplikacji. Pierwsza pozycja zmiennej QuestionList zostaje wybrana i umieszczona w bloku set QuestionLabel.Text. Gdy aplikacja zostanie uruchomiona, użytkownik zobaczy pierwsze pytanie.<br />
===Przetestuj to zachowanie===<br />
Jeśli dotychczas nie skomunikowałeś urządzenia mobilnego z programem, zrób to teraz. Co pojawia się na urządzeniu? Jeżeli utworzono listę QuestionList tak, jak wskazano powyżej, w etykiecie QuestionLabel powinna pojawić się pierwsza pozycja tej listy (Kto był doskonałym miotaczem w World Series?).<br />
<br />
==Iteracja pytań==<br />
Zdefiniowałeś już zmienną CurrentQuestionIndex, zapamiętującą pytanie, przy którym znajduje się użytkownik. Zaprogramuj teraz zachowanie przycisku NextButton. Gdy zostanie on kliknięty, aplikacja zwiększy wartość zmiennej, np. zmieni ją z 1 na 2 lub z 2 na 3 itd., a następnie użyje tej wartości do zaznaczenia nowego bieżącego pytania. Do tego zachowania potrzebne są następujące bloki:<br />
{| class="wikitable"<br />
!Typ bloku<br />
!Kategoria<br />
!Działanie<br />
|-<br />
|when NextButton.Click<br />
|NextButton<br />
|Uruchamia obsługę zdarzeń po kliknięciu przycisku<br />
|-<br />
|set currentQuestionIndex to<br />
|Zmienne<br />
|Decyduje o ustawieniu indeksu wybranej listy<br />
|-<br />
|+ <br />
|Math<br />
|Służy do zwiększania wartości zmiennej currentQuestionIndex<br />
|-<br />
|get global currentQuestionIndex<br />
|Zmienne<br />
|Tworzy nową wartość poprzez zwiększenie poprzedniej wartości o 1<br />
|-<br />
|0 (1)<br />
|Math<br />
|Dla + 1<br />
|-<br />
|set QuestionLabel.Text to<br />
|QuestionLabel<br />
|Wyświetla kolejne pytanie<br />
|-<br />
|select list item<br />
|Listy<br />
|Ustawia element listy jako wartość QuestionLabel<br />
|-<br />
|get global QuestionList<br />
|Zmienne<br />
|Wskazuje, która lista będzie wybrana<br />
|-<br />
|get global currentQuestionIndex<br />
|Zmienne<br />
|Wskazuje, który element wybranej listy będzie wybrany<br />
|}<br />
Bloki powinny wyglądać następująco:<br />
<br />
===Jak działają bloki?===<br />
Pierwszy wiersz polecenia zwiększa wartość zmiennej currentQuestionIndex o 1 (jeżeli zmienna zawiera wartość 1, zostaje ona zmieniona na 2, z 2 na 3 itd.). Następnie wykorzystuje nową wartość do wyboru pytania o tym indeksie.<br />
<br />
Przypomnijmy, że w bloku obsługi zdarzeń Screen.Initialize aplikacja wybrała pierwsze do wyświetlenia pytanie:<br />
<br />
Po kliknięciu przycisku NextButton aplikacja nie wybiera konkretnie pierwszej, drugiej czy trzeciej pozycji na liście, tylko pozycję o n-tej wartości zmiennej currentQuestionIndex.<br />
<br />
Polecenia w blokach są wykonywane od prawej do lewej, tzn. aplikacja najpierw określa wartość parametru z bloku Select list item, którym jest zmienna CurrentQuestionIndex. Liczba zawarta w tej zmiennej zostaje użyta jako indeks podczas wykonania poleceń zawartych w bloku Select list item.<br />
<br />
Po pierwszym kliknięciu przycisku NextButton, wartość zmiennej currentQuestionIndex przeskoczy z 1 na 2, aby aplikacja wybrała drugą pozycję z listy QuestionList (Kto był pierwszym doskonałym miotaczem w 2010?). Po drugim kliknięciu przycisku NextButton, wartość zmiennej currentQuestionIndex zostanie zmieniona z 2 na 3, a aplikacja wybierze trzecie pytanie z listy (Kto był pierwszym doskonałym miotaczem nowej ery?).<br />
===Przetestuj to zachowanie===<br />
Przetestuj zachowanie przycisku NextButton, aby sprawdzić, czy aplikacja działa poprawnie. Wciel się w rolę użytkownika i kliknij przycisk NextButton w telefonie. Czy urządzenie wyświetliło drugie pytanie: Kto był pierwszym doskonałym miotaczem w 2010?? Trzecie pytanie powinno pojawić się po kolejnym kliknięciu przycisku. Jeżeli aplikacja działa, pogratuluj sobie i przejdź dalej. Kliknij przycisk NextButton ponownie (po raz trzeci). Powinien zostać wyświetlony błąd: Próba uzyskania elementu 4 z listy o długości 3. Czy wiesz, na czym polega problem?<br />
<br />
Problem z aplikacją polega na tym, że zawsze po kliknięciu przycisku NextButton zwiększa ona zmienną CurrentQuestionIndex o 1. Gdy wartość zmiennej wynosi już 3, a użytkownik kolejny raz kliknie przycisk NextButton, aplikacja zmieni wartość zmiennej z 3 na 4, następnie wywoła blok Select list item, aby odczytać pozycję o aktualnym indeksie CurrentQuestionIndex, czyli w tym przypadku czwartą pozycję. Ponieważ zmienna QuestionList zawiera tylko trzy elementy, Android wykaże błąd.<br />
<br />
Aplikacja musi zadawać pytanie - sprawdzać warunek - gdy nastąpi kliknięcie przycisku NextButton i realizować polecenia zawarte w różnych blokach w zależności od odpowiedzi. Elementem do sprawdzenia jest to, czy zmienna CurrentQuestionIndex już ma wartość 3. Jeżeli tak - należy ustawić CurrentQuestionIndex z powrotem na 0, aby użytkownik wrócił do pierwszego pytania.<br />
<br />
Będziesz potrzebował następujących bloków:<br />
{| class="wikitable"<br />
!Typ bloku<br />
!Kategoria<br />
!Działanie<br />
|-<br />
|if then<br />
|Control<br />
|sprawdzenie, czy użytkownik jest na etapie ostatniego pytania<br />
|-<br />
|= <br />
|Math<br />
|sprawdzenie, czy currentQuestionIndex ma wartość 3<br />
|-<br />
|get global currentQuestionIndex<br />
|Variables<br />
|<br />
|-<br />
|0 (3)<br />
|Math<br />
|3 to numer na liście<br />
|-<br />
|set currentQuestionIndex to<br />
|Variables<br />
|ustawienie na 0, aby wrócić do pierwszego pytania<br />
|-<br />
|0<br />
|Math<br />
|ustawienie na 0, ponieważ kolejne bloki zwiększą wartość do 1<br />
|}<br />
Zmodyfikowany blok obsługi zdarzenia When NextButton.Click powinien wyglądać następująco:<br />
<br />
===Jak działają bloki===<br />
Po kliknięciu przycisku NextButton aplikacja najpierw sprawdza, czy currentQuestionIndex ma wartość 3. Jeżeli tak, wartość tej zmiennej jest ustawiana na 0, aby po zwiększeniu jej w dalszych krokach jej wartość wyniosła 1. Wtedy quiz wróci do pierwszego pytania. Zauważ, że tylko bloki osadzone w bloku if-then są zależne od warunku. Blok zwiększenia wartości i blok Set QuestionLabel.Text to są wykonywane bez względu na jakikolwiek warunek.<br />
<br />
==Aplikacja modyfikowalna: Ułatwianie modyfikowania pytań==<br />
Teraz zmodyfikujemy aplikację, aby można było łatwo dodawać i usuwać elementy z listy. Zmień bloki tak, aby działały na liście o dowolnej długości, a nie tylko liście z dokładnie trzema pozycjami. <br />
Na początek dodaj czwarte pytanie do zmiennej QuestionList i kolejną odpowiedź do AnswerList. W tym celu musisz najpierw zwiększyć liczbę dostępnych pól za pomocą przycisku modyfikującego (mutatora). Aby dowiedzieć się więcej o tym elemencie, zobacz: http://appinventor.mit.edu/explore/ai2/support/concepts/mutators. Bloki powinny wyglądać następująco:<br />
<br />
===Przetestuj zmodyfikowaną aplikację.===<br />
Kliknij przycisk NextButton kilka razy. Zauważysz, że czwarte pytanie nigdy się nie pojawia, bez względu na to, ile razy klikniesz przycisk.<br />
<br />
Problemem jest to, że test sprawdzający, czy użytkownik znajduje się przy ostatnim pytaniu, jest zbyt szczegółowy: pyta, czy zmienna CurrentQuestionIndex ma wartość 3:<br />
<br />
Możesz po prostu zmienić liczbę z 3 na 4, a aplikacja będzie znów działać poprawnie. Problem polega jednak na tym, że za każdym razem, gdy zmodyfikujesz liczbę pytań i odpowiedzi, będziesz musiał pamiętać, aby dokonać także tej zmiany. Takie zależności w programie komputerowym często prowadzą do błędów, w szczególności gdy aplikacja staje się bardziej złożona. Znacznie lepiej jest przygotować program w taki sposób, aby działał niezależnie od liczby pytań. Takie uogólnienie jest jeszcze ważniejsze, gdy lista, z którą pracujesz, zmienia się dynamicznie, na przykład w aplikacji z quizem, gdzie użytkownik może dodawać nowe pytania.<br />
<br />
Lepszym rozwiązaniem jest sprawdzenie warunku w sposób bardziej ogólny. Tak naprawdę chcesz wiedzieć, czy bieżące pytanie – czyli wartość zmiennej currentQuestionIndex jest tak duża, jak ilość elementów w zmiennej QuestionList. Jeżeli aplikacja sprawdzi warunek w bardziej ogólny sposób, to będzie działać, nawet jeżeli dodasz lub usuniesz elementy ze zmiennej QuestionList. Aby zmienić blok obsługi zdarzenia When NextButton.Click, zmień poprzedni test sprawdzający, który odnosił się bezpośrednio do 3. Będziesz potrzebował następujących bloków:<br />
{| class="wikitable"<br />
!Typ bloku<br />
!Szuflada<br />
!Działanie<br />
|-<br />
|length of list<br />
|Lists<br />
|Pyta, ile elementów jest w zmiennej QuestionList<br />
|-<br />
|get global QuestionList<br />
|Variables<br />
|Określa, o którą listę chodzi<br />
|}<br />
Blok obsługi zdarzenia When NextButton.Click powinien teraz wyglądać następująco:<br />
<br />
<br />
===Jak działają bloki?===<br />
Warunek if porównuje teraz wartość zmiennej CurrentQuestionIndex z długością zmiennej QuestionList. Zatem jeżeli zmienna CurrentQuestionIndex ma wartość 4, a długość zmiennej QuestionList wynosi 4, to wartość zmiennej currentQuestionIndex zostanie ustawiona na 0 (a następnie na 1, 2 itd.). Zauważ - bloki nie odwołują się już do 3 ani żadnej innej określonej wartości, dlatego instrukcja będzie działać bez względu na liczbę elementów listy.<br />
<br />
Przetestuj zmodyfikowane zachowanie. Czy po kliknięciu przycisku NextButton aplikacja przechodzi teraz przez cztery pytania, wracając po ostatnim do pierwszego?<br />
<br />
==Przełączanie zdjęcia dla każdego pytania==<br />
Na razie aplikacja wyświetla to samo zdjęcie, bez względu na to, jakie pytanie zostaje zadane. Możesz to zmienić tak, aby po kliknięciu przycisku NextButton pojawiała się fotografia dotycząca danego pytania. W obszarze Media dostępne są cztery dodane wcześniej zdjęcia. Teraz utworzymy trzecią listę - PictureList, której elementami będą nazwy plików zdjęć, a następnie zmodyfikujemy blok obsługi zdarzenia When NextButton.Click, aby program po każdym pytaniu przełączał zdjęcie.<br />
Najpierw utwórz listę PictureList i zainicjuj ją nazwami plików graficznych. Upewnij się, czy nazwy są dokładnie takie same jak nazwy plików, które zostały załadowane do obszaru Media. Oto jak powinien wyglądać blok dla listy PictureList:<br />
<br />
Następnie zmodyfikuj blok obsługi zdarzeń When NextButton.Click, aby zmieniał wyświetlane zdjęcie w zależności od zadanego pytania. Jeżeli ustawisz właściwość Image.Picture na nazwę pliku zdjęcia, które zostało załadowane, właśnie ta fotografia zostanie wyświetlona. Aby zmodyfikować blok When NextButton.Click, potrzebujesz następujących bloków:<br />
{| class="wikitable"<br />
!Typ bloku<br />
!Kategoria<br />
!Działanie<br />
|-<br />
|set Image1.Picture to<br />
|Image1<br />
|ustaw, aby zmieniać zdjęcie<br />
|-<br />
|select list item<br />
|Lists<br />
|należy wybrać zdjęcie odpowiadające na aktualne pytanie<br />
|-<br />
|get global PictureList<br />
|Variables<br />
|wybierz nazwę pliku z tej listy<br />
|-<br />
|get global currentQuestionIndex<br />
|Variables<br />
|wybierz element o n-tym indeksie currentQuestionIndex<br />
|}<br />
Oto jak powinny wyglądać bloki:<br />
<br />
===Jak działają bloki?===<br />
Zmienna CurrentQuestionIndex służy jako indeks dla zmiennej QuestionList. Wartość CurrentQuestionIndex wynosi 1, aplikacja wybiera pierwsze pytanie i pierwsze zdjęcie. Gdy CurrentQuestionIndex wynosi 2, aplikacja wybiera drugie pytanie i drugie zdjęcie. Oczywiście takie działanie zależy od tego, czy listy są ze sobą zsynchronizowane. Tak jest w tym przypadku - pierwszy obraz - LarsenBerra.jpg to zdjęcie Dona Larsena, jednocześnie Don Larsen to odpowiedź na pierwsze pytanie (Kto był doskonałym miotaczem w World Series?). <br />
Przetestuj zmodyfikowane zachowanie. Czy nowe zdjęcie pojawia się po każdym kliknięciu przycisku NextButton?<br />
<br />
==Ocena udzielanych odpowiedzi==<br />
Teraz dodamy bloki, które określają, czy użytkownik odpowiedział na pytanie prawidłowo, czy też nie. Gracz wprowadza odpowiedź do AnswerText, a następnie klika przycisk AnswerButton. Aplikacja musi porównać wpis użytkownika z odpowiedzią na bieżące pytanie, używając bloku if... then... w celu jej sprawdzenia. Etykieta RightWrongLabel powinna być modyfikowana, aby podawać, czy odpowiedź jest prawidłowa, czy nie.<br />
<br />
Do tego zachowania będą potrzebne następujące bloki:<br />
{| class="wikitable"<br />
!Typ bloku<br />
!Kategoria<br />
!Działanie<br />
|-<br />
|when AnswerButton.Click<br />
|AnswerButton<br />
|zachowanie jest wyzwalane, gdy użytkownik kliknie przycisk AnswerButton<br />
|-<br />
|if... then...<br />
|Control<br />
|Użyj mutatora, aby dodać alternatywę (else). Jeżeli odpowiedź jest prawidłowa - zrób jedno, w przeciwnym razie (else) - zrób coś innego<br />
|-<br />
|= <br />
|Math<br />
|sprawdzenie, czy odpowiedź jest prawidłowa<br />
|-<br />
|AnswerText.Text<br />
|AnswerText<br />
|Odpowiedź użytkownika pojawia się w tym polu tekstowym<br />
|-<br />
|select list item<br />
|Lists<br />
|wybrać bieżącą odpowiedź z listy AnswerList<br />
|-<br />
|get global AnswerList<br />
|Variables<br />
|lista, z której jest wybierany element<br />
|-<br />
|get global currentQuestionIndex<br />
|Variables<br />
|numer pytania (i numer odpowiedzi), przy którym jest użytkownik<br />
|-<br />
|set RightWrongLabel.Text to<br />
|RightWrongLabel<br />
|tutaj podaj odpowiedź<br />
|-<br />
|Dobrze!<br />
|Text<br />
|jeżeli odpowiedź jest prawidłowa<br />
|-<br />
|set RightWrongLabel.Text to<br />
|RightWrongLabel<br />
|tutaj podaj odpowiedź<br />
|-<br />
|Źle<br />
|Text<br />
|jeżeli odpowiedź jest nieprawidłowa<br />
|}<br />
Bloki powinny wyglądać następująco:<br />
<br />
===Jak działają bloki?===<br />
Test if sprawdza, czy odpowiedź użytkownika (AnswerText.Text) jest taka sama, jak element na liście AnswerList o indeksie równym wartości zmiennej CurrentQuestionIndex. Jeżeli zmienna CurrentQuestionIndex ma wartość 1, aplikacja porównuje odpowiedź użytkownika z pierwszą pozycją na liście AnswerList, (Don Larsen). Jeżeli zmienna CurrentQuestionIndex zmieni wartość na 2, program zestawia odpowiedź z drugą pozycją na liście, czyli Dallas Branden. Jeśli wynik porównania jest pozytywny, przeprowadzane są bloki then, a treść etykiety RightWrongLabel zostaje ustawiona na Dobrze!. Jeżeli wynik testu jest negatywny (fałszywy), przeprowadzane są bloki alternatywy (else), a treść etykiety RightWrongLabel zostaje ustawiona na Źle.<br />
<br />
Przetestuj zmodyfikowaną aplikację. Spróbuj odpowiedzieć na jedno z pytań. Powinna pojawić się ocena, czy odpowiedź była dokładnie taka sama, jak na liście AnswerList. Sprawdź zarówno prawidłowe, jak i nieprawidłowe odpowiedzi (Uwaga - uwzględniana jest wielkość liter!). Kliknij przycisk NextButton i odpowiedz na drugie pytanie. Czy aplikacja nadal działa? Powinna, ale zauważ, że gdy klikniesz przycisk NextButton, tekst Dobrze! lub Źle oraz poprzednia odpowiedź nadal będą wyświetlane. Choć nie wpływa to zasadniczo na naszą grę, to takie szczegóły interfejsu z pewnością zostaną zauważone przez użytkowników Twojej aplikacji.<br />
<br />
Aby wyzerować etykietę RightWrongLabel i AnswerText, umieść poniższe bloki w bloku obsługi zdarzeń When NextButton.click:<br />
{| class="wikitable"<br />
!Typ bloku<br />
!Kategoria<br />
!Działanie<br />
|-<br />
|set RightWrongLabel.Text to<br />
|RightWrongLabel<br />
|Ustawia wartość etykiety na…<br />
|-<br />
|„ „<br />
|Text<br />
|pusty tekst<br />
|-<br />
|set AnswerText.Text to<br />
|AnswerText<br />
|Ustawia wartość etykiety na…<br />
|-<br />
|„ „<br />
|Text<br />
|pusty tekst<br />
|}<br />
Bloki powinny wyglądać następująco:<br />
<br />
===Jak działają bloki?===<br />
Po kliknięciu przycisku NextButton użytkownik przechodzi do następnego pytania, dlatego początkowe wiersze bloku obsługi zdarzeń zerują etykietę RightWrongLabel i pole AnswerText.<br />
Przetestuj to zachowanie Odpowiedz na pytanie i kliknij przycisk Wyślij, a następnie - NextButton. Czy Twoja poprzednia odpowiedź i jej ocena zniknęły?<br />
<br />
==Ostateczna postać programu==<br />
Oto gotowa aplikacja QuizMe:<br />
<br />
Utwórz wykonywalną wersję aplikacji, wybierając menu Build/App (provide QR code for .apk). Gdy pojawi się kod kreskowy, użyj czytnika kodów w telefonie, aby pobrać i zainstalować aplikację.<br />
<br />
===Modyfikacje===<br />
Quiz w tej wersji jest już gotowy. Czy masz ochotę przemyśleć pewne zmiany?<br />
<br />
Zamiast wyświetlać zdjęcie dla każdego pytania, spróbuj odtworzyć dźwięk lub krótkie wideo. Za pomocą dźwięku możesz zmienić quiz w aplikację Jaka to melodia?.<br />
<br />
Quiz akceptuje ściśle określone odpowiedzi. Jeśli gracz odpowiedziałby, lekko przekształcając tekst (np. podając inicjał zamiast imienia), program uzna to za błąd. Można to zmienić na kilka różnych sposobów. Jednym z nich jest użycie bloku text.contains, aby sprawdzić, czy odpowiedź użytkownika zawiera prawidłową odpowiedź. Inny sposób to dostarczenie wielu odpowiedzi na każde pytanie i sprawdzenie przez iterację (użycie bloku for each), czy któraś z nich pasuje.<br />
<br />
Przekształć quiz tak, aby przedstawiał odpowiedzi do wyboru. Lista odpowiedzi będzie musiała być listą list, a każda podrzędna lista będzie musiała zawierać opcje odpowiedzi. Użyj komponentu ListPicker, aby umożliwić użytkownikowi wybranie odpowiedzi.<br />
<br />
<br />
==Podsumowanie==<br />
Oto niektóre koncepcje omówione w tym przewodniku:<br />
<ul><li>Aplikacje można tworzyć w sposób ogólny, aby pracować z dowolną listą danych.</li><br />
<li>Zmienne indeksu są wykorzystywane do śledzenia bieżącej pozycji na liście. Zwiększając wartość zmiennej indeksu, należy uważać na przekroczenie końca listy.</li></ul><br />
<br />
==Zeskanuj próbną aplikację do telefonu==<br />
Aby zainstalować i uruchomić aplikację próbną, zeskanuj poniższy kod kreskowy:<br />
<br />
==Pobierz kod źródłowy==<br />
Jeżeli chcesz pracować z tą próbką w programie App Inventor:<br />
<ul><li>pobierz na komputer kod źródłowy: [http://appinventor.mit.edu/explore/sites/all/files/ai2tutorials/QuizMe/QuizMe_MIT.aia http://appinventor.mit.edu/explore/sites/all/files/ai2tutorials/QuizMe/QuizMe_MIT.aia]</li><br />
<li>otwórz program App Inventor,</li><br />
<li>kliknij opcję My Projects,</li><br />
<li>wybierz Import project (.aia) from my computer...</li><br />
<li>znajdź i zatwierdź pobrany kod źródłowy.</li></ul></div>M Kelniarzhttp://wiki.mistrzowiekodowania.pl/index.php?title=QuizMeQuizMe2015-03-15T18:25:23Z<p>M Kelniarz: /* Programowanie aplikacji */</p>
<hr />
<div>=Aplikacja QuizMe dla App Inventor 2=<br />
<br />
==Co tworzysz?==<br />
[[Plik:t6-1.png|right]]QuizMe to gra dotycząca ciekawostek baseballowych, ale można jej użyć jako szablonu do tworzenia quizów z dowolnej dziedziny. W aplikacji użytkownik odpowiada na szereg pytań, otrzymując następnie informację zwrotną, czy udzielił poprawnej, czy błędnej odpowiedzi. Gracz przechodzi do kolejnego pytania, klikając przycisk.<br />
<br />
W grze QuizMe dysponujemy zamkniętym zbiorem pytań, chyba że programista je zmieni. W następnym etapie można utworzyć MakeQuiz & TakeQuiz – aplikację, która pozwala użytkownikom na tworzenie i modyfikowanie pytań.<br />
<br />
Poradnik ten zakłada, że znasz już podstawy tworzenia aplikacji w App Inventorze – korzystanie z Projektanta komponentów w celu utworzenia interfejsu użytkownika i z Edytora bloków, aby określić obsługę zdarzeń. Jeżeli potrzebujesz przypomnienia, spróbuj popracować z poradnikami podstawowymi zanim przejdziesz dalej.<br />
<br />
==Zaczynamy!==<br />
Połącz się z witryną internetową App Inventor i załóż nowy projekt. Nazwij go QuizMe, ustaw taki sam tytuł ekranu (Title). Za pomocą MIT AI2 Companion połącz program z urządzeniem mobilnym. Pobierz poniższe zdjęcia baseballistów i zapisz je w komputerze. Później załadujesz je do projektu.<br />
<ul><li> [http://beta.appinventor.mit.edu/learn/tutorials/quizme/QuizMeAssets/Larsenberra.jpg Larsenberra.jpg]</li><br />
<li> [http://beta.appinventor.mit.edu/learn/tutorials/quizme/QuizMeAssets/dallasbraden.jpg Dallasbraden.jpg]</li><br />
<li> [http://beta.appinventor.mit.edu/learn/tutorials/quizme/QuizMeAssets/cyyoung.jpg Cyyoung.jpg]</li><br />
<li> [http://beta.appinventor.mit.edu/learn/tutorials/quizme/QuizMeAssets/nolanryan.jpg Nolanryan.jpg]</li></ul><br />
<br />
==Wstęp==<br />
Zaprojektujesz grę typu quiz, w której użytkownik będzie przechodził do kolejnych pytań, klikając przycisk Dalej, a następnie otrzymywał prostą ocenę Dobrze/Źle dla każdej odpowiedzi.<br />
<br />
W tym przewodniku omówimy:<br />
<ul><li>definiowanie i wyświetlanie listy informacji;</li><br />
<li>przechodzenie przez listę za pomocą zmiennej indeksującej – zmiennej, która śledzi pozycję na liście;</li><br />
<li>zachowania warunkowe – wykonywanie określonych operacji tylko wtedy, gdy spełniony jest określony warunek;</li><br />
<li>Zmianę zdjęcia w zależności od sytuacji.</li></ul><br />
<br />
==Projektowanie aplikacji==<br />
Użyj Projektanta komponentów do utworzenia interfejsu dla aplikacji QuizMe. <br />
Aby utworzyć interfejs, najpierw załaduj do projektu pobrane zdjęcia. Kliknij przycisk Prześlij plik (Upload File...) w obszarze Media i wybierz jeden z pobranych wcześniej plików (np. Larsenberra.jpg). Następnie zrób to samo z pozostałymi trzema zdjęciami.<br />
Utwórz następujące komponenty, przeciągając je z Palety (Palette) do Przeglądarki (Viewer) i ustaw właściwości komponentów zgodnie z poniższym opisem:<br />
{|class="wikitable"<br />
! Typ komponentu<br />
! Kategoria<br />
! Jaką nadać jej nazwę<br />
! Działanie<br />
! Działanie komponentu<br />
|-<br />
|Image<br />
|User interface<br />
|Image1<br />
|Ustaw właściwość zdjęcia (Picture) na Larsenberra.jpg. Jest to pierwsze wyświetlane zdjęcie.<br />
|Obrazkowa część pytania<br />
|-<br />
|Label<br />
|User interface<br />
|QuestionLabel<br />
|Zmień właściwość tekstu (Text) na Pytanie:<br />
|Wyświetla bieżące pytanie<br />
|-<br />
|HorizontalArrangement<br />
|Layout<br />
|HorizontalArrangement1<br />
| <br />
|Organizuje komponenty AnswerPrompt i Text (podaj odpowiedź i tekst)<br />
|-<br />
|Label<br />
|User interface<br />
|AnswerPromptLabel<br />
|Zmień właściwość tekstu (Text) na Podaj odpowiedź:. Na ekranie przeglądarki przesuń tę etykietę do HorizontalArrangement1.<br />
|Wyświetla tekst prośby o odpowiedź.<br />
|-<br />
|TextBox<br />
|User interface<br />
|AnswerText<br />
|Zmień wskazówkę (Hint) na Podaj odpowiedź. Na ekranie przeglądarki przenieś AnswerText do komponentu HorizontalArrangement1.<br />
|Tutaj użytkownik podaje odpowiedź.<br />
|-<br />
|Label<br />
|User interface <br />
|RightWrongLabel<br />
|Zmień właściwość tekstu (Text) na Dobrze/Źle.<br />
|Tutaj wyświetlana jest ocena Dobrze/Źle.<br />
|-<br />
|HorizontalArrangement<br />
|Layout<br />
|HorizontalArrangement2<br />
|<br />
|Organizuje przyciski AnswerButton i NextButton (przycisk odpowiedzi i przycisk dalej).<br />
|-<br />
|Przycisk<br />
|User interface<br />
|AnswerButton<br />
|Zmień właściwość tekstu (Text) na Wyślij. Na ekranie przeglądarki przesuń ten przycisk do HorizontalArrangment2.<br />
|Użytkownik klika, aby przesłać odpowiedź.<br />
|-<br />
|Przycisk<br />
|User interface<br />
|NextButton<br />
|Zmień właściwość tekstu (Text) na Dalej. Przenieś ten przycisk do HorizontalArrangement2.<br />
|Użytkownik klika, aby przejść do następnego pytania.<br />
|} <br />
Po zakończeniu powinien on wyglądać jak poniższa ilustracja (pod nią znajdują się również bardziej szczegółowe informacje).<br />
[[Plik:t6-2.png]]<br />
<br />
==Programowanie aplikacji==<br />
Otwórz Edytor bloków, aby zaprogramować działanie komponentów. Najpierw zdefiniuj dwie zmienne - listy: zmienną QuestionList, zawierającą listę pytań i zmienną AnswerList z listą odpowiedzi na te pytania.<br />
<br />
Aby zdefiniować te dwie zmienne listy, potrzebujesz następujących bloków:<br />
{| class="wikitable"<br />
!Typ bloku<br />
!Kategoria<br />
!Działanie<br />
|-<br />
|initialize global name to<br />
|Variables<br />
|Definiuje zmienną QuestionList (zmień jej nazwę)<br />
|-<br />
|initialize global name to<br />
|Variables<br />
|Definiuje zmienną AnswerList (zmień jej nazwę)<br />
|-<br />
|make a list<br />
|Lists<br />
|Służy do dodawania elementów do zmiennej QuestionList<br />
|-<br />
|„ „ (trzykrotnie)<br />
|Lists<br />
|Służy do wpisania pytań<br />
|-<br />
|make a list<br />
|Lists<br />
|Służy do dodawania elementów do zmiennej AnswerList<br />
|-<br />
|„ „ (trzykrotnie)<br />
|Text<br />
|Służy do wpisania odpowiedzi<br />
|}<br />
Utwórz zmienne całościowe, przeciągając z kategorii zmiennych (Variables) na obszar roboczy blok Initialize global name to. Kliknij dwukrotnie domyślną nazwę name, aby ją zmienić. Blok Initialize global name to zawiera pole na początkową wartość zmiennej. Zmienna może zawierać liczbę, tekst, a nawet listę – aby ją utworzyć, podłącz blok Make a list do definicji zmiennej.<br />
<br />
Bloki powinny wyglądać następująco:<br />
===Zdefiniuj ukrytą zmienną Index===<br />
Za każdym razem, gdy użytkownik kliknie przycisk NextButton, aby przejść dalej, aplikacja musi pamiętać, przy którym pytaniu jest obecnie gracz. W języku programowania, aby coś zapamiętać, trzeba zdefiniować nową zmienną. W tym przypadku aplikacja musi zapamiętać bieżący numer pytania – indeks listy QuestionList.<br />
Aby zdefiniować zmienną currentQuestionIndex, potrzebujesz następujących bloków:<br />
{| class="wikitable"<br />
!Typ bloku<br />
!Kategoria<br />
!Działanie<br />
|-<br />
|initialize global name to<br />
|Variables<br />
|Definiuje zmienną currentQuestionIndex (zmień nazwę)<br />
|-<br />
|0 (1)<br />
|Math<br />
|Ustaw wartość początkową currentQuestionIndex na 1 (zmień liczbę)<br />
|}<br />
Bloki powinny wyglądać następująco:<br />
<br />
===Wyświetl pierwsze pytanie===<br />
Odłóż na razie kwestię odpowiedzi i skup się na zaprogramowaniu sekwencyjnego przejścia przez pytania. Pożądane zachowanie jest następujące: po uruchomieniu aplikacji na etykiecie o nazwie QuestionLabel pojawia się pierwsze pytanie. Gdy użytkownik kliknie NextButton, wyświetlone zostaje drugie pytanie. Po ponownym kliknięciu pojawia się trzecie pytanie. Po dotarciu do ostatniego pytania kliknięcie przycisku NextButton powoduje ponowne pojawienie się pierwszego pytania w etykiecie QuestionLabel.<br />
<br />
W programie App Inventor określone pozycje na liście są wybierane za pomocą bloku select list item. W tym bloku trzeba podać listę i indeks – pozycję na liście. Jeżeli na liście są trzy pozycje, prawidłowe indeksy to 1, 2 i 3.<br />
<br />
Po uruchomieniu aplikacja QuizMe powinna wybrać pierwsze pytanie z listy i wyświetlić je w komponencie QuestionLabel. Do tego zachowania inicjalizującego działanie aplikacji potrzebne są następujące bloki:<br />
<br />
{| class="wikitable"<br />
!Typ bloku<br />
!Kategoria<br />
!Działanie<br />
|-<br />
|when Screen1.Initialize<br />
|Screen1<br />
|Podczas uruchamiania aplikacji zainicjowana jest ta obsługa zdarzenia<br />
|-<br />
|set QuestionLabel.Text to<br />
|QuestionLabel<br />
|Umieszcza pierwsze pytanie w etykiecie QuestionLabel<br />
|-<br />
|select list item<br />
|Lists<br />
|Wybiera pierwsze pytanie z etykiety QuestionLabel<br />
|-<br />
|get <br />
|Variables<br />
|Ustala listę, z której jest wybierany element. Tutaj: Global QuestionList<br />
|-<br />
|0 (1)<br />
|Math<br />
|Wybiera pierwsze pytanie za pomocą indeksu 1. Ustaw wartość na 1.<br />
|}<br />
Bloki powinny wyglądać następująco:<br />
[[Plik:t6-3.png]]<br />
<br />
===Jak działają bloki?===<br />
Zdarzenie when Screen1.Initialize jest wyzwalane podczas uruchomienia aplikacji. Pierwsza pozycja zmiennej QuestionList zostaje wybrana i umieszczona w bloku set QuestionLabel.Text. Gdy aplikacja zostanie uruchomiona, użytkownik zobaczy pierwsze pytanie.<br />
===Przetestuj to zachowanie===<br />
Jeśli dotychczas nie skomunikowałeś urządzenia mobilnego z programem, zrób to teraz. Co pojawia się na urządzeniu? Jeżeli utworzono listę QuestionList tak, jak wskazano powyżej, w etykiecie QuestionLabel powinna pojawić się pierwsza pozycja tej listy (Kto był doskonałym miotaczem w World Series?).<br />
<br />
==Iteracja pytań==<br />
Zdefiniowałeś już zmienną CurrentQuestionIndex, zapamiętującą pytanie, przy którym znajduje się użytkownik. Zaprogramuj teraz zachowanie przycisku NextButton. Gdy zostanie on kliknięty, aplikacja zwiększy wartość zmiennej, np. zmieni ją z 1 na 2 lub z 2 na 3 itd., a następnie użyje tej wartości do zaznaczenia nowego bieżącego pytania. Do tego zachowania potrzebne są następujące bloki:<br />
{| class="wikitable"<br />
!Typ bloku<br />
!Kategoria<br />
!Działanie<br />
|-<br />
|when NextButton.Click<br />
|NextButton<br />
|Uruchamia obsługę zdarzeń po kliknięciu przycisku<br />
|-<br />
|set currentQuestionIndex to<br />
|Zmienne<br />
|Decyduje o ustawieniu indeksu wybranej listy<br />
|-<br />
|+ <br />
|Math<br />
|Służy do zwiększania wartości zmiennej currentQuestionIndex<br />
|-<br />
|get global currentQuestionIndex<br />
|Zmienne<br />
|Tworzy nową wartość poprzez zwiększenie poprzedniej wartości o 1<br />
|-<br />
|0 (1)<br />
|Math<br />
|Dla + 1<br />
|-<br />
|set QuestionLabel.Text to<br />
|QuestionLabel<br />
|Wyświetla kolejne pytanie<br />
|-<br />
|select list item<br />
|Listy<br />
|Ustawia element listy jako wartość QuestionLabel<br />
|-<br />
|get global QuestionList<br />
|Zmienne<br />
|Wskazuje, która lista będzie wybrana<br />
|-<br />
|get global currentQuestionIndex<br />
|Zmienne<br />
|Wskazuje, który element wybranej listy będzie wybrany<br />
|}<br />
Bloki powinny wyglądać następująco:<br />
<br />
===Jak działają bloki?===<br />
Pierwszy wiersz polecenia zwiększa wartość zmiennej currentQuestionIndex o 1 (jeżeli zmienna zawiera wartość 1, zostaje ona zmieniona na 2, z 2 na 3 itd.). Następnie wykorzystuje nową wartość do wyboru pytania o tym indeksie.<br />
<br />
Przypomnijmy, że w bloku obsługi zdarzeń Screen.Initialize aplikacja wybrała pierwsze do wyświetlenia pytanie:<br />
<br />
Po kliknięciu przycisku NextButton aplikacja nie wybiera konkretnie pierwszej, drugiej czy trzeciej pozycji na liście, tylko pozycję o n-tej wartości zmiennej currentQuestionIndex.<br />
<br />
Polecenia w blokach są wykonywane od prawej do lewej, tzn. aplikacja najpierw określa wartość parametru z bloku Select list item, którym jest zmienna CurrentQuestionIndex. Liczba zawarta w tej zmiennej zostaje użyta jako indeks podczas wykonania poleceń zawartych w bloku Select list item.<br />
<br />
Po pierwszym kliknięciu przycisku NextButton, wartość zmiennej currentQuestionIndex przeskoczy z 1 na 2, aby aplikacja wybrała drugą pozycję z listy QuestionList (Kto był pierwszym doskonałym miotaczem w 2010?). Po drugim kliknięciu przycisku NextButton, wartość zmiennej currentQuestionIndex zostanie zmieniona z 2 na 3, a aplikacja wybierze trzecie pytanie z listy (Kto był pierwszym doskonałym miotaczem nowej ery?).<br />
===Przetestuj to zachowanie===<br />
Przetestuj zachowanie przycisku NextButton, aby sprawdzić, czy aplikacja działa poprawnie. Wciel się w rolę użytkownika i kliknij przycisk NextButton w telefonie. Czy urządzenie wyświetliło drugie pytanie: Kto był pierwszym doskonałym miotaczem w 2010?? Trzecie pytanie powinno pojawić się po kolejnym kliknięciu przycisku. Jeżeli aplikacja działa, pogratuluj sobie i przejdź dalej. Kliknij przycisk NextButton ponownie (po raz trzeci). Powinien zostać wyświetlony błąd: Próba uzyskania elementu 4 z listy o długości 3. Czy wiesz, na czym polega problem?<br />
<br />
Problem z aplikacją polega na tym, że zawsze po kliknięciu przycisku NextButton zwiększa ona zmienną CurrentQuestionIndex o 1. Gdy wartość zmiennej wynosi już 3, a użytkownik kolejny raz kliknie przycisk NextButton, aplikacja zmieni wartość zmiennej z 3 na 4, następnie wywoła blok Select list item, aby odczytać pozycję o aktualnym indeksie CurrentQuestionIndex, czyli w tym przypadku czwartą pozycję. Ponieważ zmienna QuestionList zawiera tylko trzy elementy, Android wykaże błąd.<br />
<br />
Aplikacja musi zadawać pytanie - sprawdzać warunek - gdy nastąpi kliknięcie przycisku NextButton i realizować polecenia zawarte w różnych blokach w zależności od odpowiedzi. Elementem do sprawdzenia jest to, czy zmienna CurrentQuestionIndex już ma wartość 3. Jeżeli tak - należy ustawić CurrentQuestionIndex z powrotem na 0, aby użytkownik wrócił do pierwszego pytania.<br />
<br />
Będziesz potrzebował następujących bloków:<br />
{| class="wikitable"<br />
!Typ bloku<br />
!Kategoria<br />
!Działanie<br />
|-<br />
|if then<br />
|Control<br />
|sprawdzenie, czy użytkownik jest na etapie ostatniego pytania<br />
|-<br />
|= <br />
|Math<br />
|sprawdzenie, czy currentQuestionIndex ma wartość 3<br />
|-<br />
|get global currentQuestionIndex<br />
|Variables<br />
|<br />
|-<br />
|0 (3)<br />
|Math<br />
|3 to numer na liście<br />
|-<br />
|set currentQuestionIndex to<br />
|Variables<br />
|ustawienie na 0, aby wrócić do pierwszego pytania<br />
|-<br />
|0<br />
|Math<br />
|ustawienie na 0, ponieważ kolejne bloki zwiększą wartość do 1<br />
|}<br />
Zmodyfikowany blok obsługi zdarzenia When NextButton.Click powinien wyglądać następująco:<br />
<br />
===Jak działają bloki===<br />
Po kliknięciu przycisku NextButton aplikacja najpierw sprawdza, czy currentQuestionIndex ma wartość 3. Jeżeli tak, wartość tej zmiennej jest ustawiana na 0, aby po zwiększeniu jej w dalszych krokach jej wartość wyniosła 1. Wtedy quiz wróci do pierwszego pytania. Zauważ, że tylko bloki osadzone w bloku if-then są zależne od warunku. Blok zwiększenia wartości i blok Set QuestionLabel.Text to są wykonywane bez względu na jakikolwiek warunek.<br />
<br />
==Aplikacja modyfikowalna: Ułatwianie modyfikowania pytań==<br />
Teraz zmodyfikujemy aplikację, aby można było łatwo dodawać i usuwać elementy z listy. Zmień bloki tak, aby działały na liście o dowolnej długości, a nie tylko liście z dokładnie trzema pozycjami. <br />
Na początek dodaj czwarte pytanie do zmiennej QuestionList i kolejną odpowiedź do AnswerList. W tym celu musisz najpierw zwiększyć liczbę dostępnych pól za pomocą przycisku modyfikującego (mutatora). Aby dowiedzieć się więcej o tym elemencie, zobacz: http://appinventor.mit.edu/explore/ai2/support/concepts/mutators. Bloki powinny wyglądać następująco:<br />
<br />
===Przetestuj zmodyfikowaną aplikację.===<br />
Kliknij przycisk NextButton kilka razy. Zauważysz, że czwarte pytanie nigdy się nie pojawia, bez względu na to, ile razy klikniesz przycisk.<br />
<br />
Problemem jest to, że test sprawdzający, czy użytkownik znajduje się przy ostatnim pytaniu, jest zbyt szczegółowy: pyta, czy zmienna CurrentQuestionIndex ma wartość 3:<br />
<br />
Możesz po prostu zmienić liczbę z 3 na 4, a aplikacja będzie znów działać poprawnie. Problem polega jednak na tym, że za każdym razem, gdy zmodyfikujesz liczbę pytań i odpowiedzi, będziesz musiał pamiętać, aby dokonać także tej zmiany. Takie zależności w programie komputerowym często prowadzą do błędów, w szczególności gdy aplikacja staje się bardziej złożona. Znacznie lepiej jest przygotować program w taki sposób, aby działał niezależnie od liczby pytań. Takie uogólnienie jest jeszcze ważniejsze, gdy lista, z którą pracujesz, zmienia się dynamicznie, na przykład w aplikacji z quizem, gdzie użytkownik może dodawać nowe pytania.<br />
<br />
Lepszym rozwiązaniem jest sprawdzenie warunku w sposób bardziej ogólny. Tak naprawdę chcesz wiedzieć, czy bieżące pytanie – czyli wartość zmiennej currentQuestionIndex jest tak duża, jak ilość elementów w zmiennej QuestionList. Jeżeli aplikacja sprawdzi warunek w bardziej ogólny sposób, to będzie działać, nawet jeżeli dodasz lub usuniesz elementy ze zmiennej QuestionList. Aby zmienić blok obsługi zdarzenia When NextButton.Click, zmień poprzedni test sprawdzający, który odnosił się bezpośrednio do 3. Będziesz potrzebował następujących bloków:<br />
{| class="wikitable"<br />
!Typ bloku<br />
!Szuflada<br />
!Działanie<br />
|-<br />
|length of list<br />
|Lists<br />
|Pyta, ile elementów jest w zmiennej QuestionList<br />
|-<br />
|get global QuestionList<br />
|Variables<br />
|Określa, o którą listę chodzi<br />
|}<br />
Blok obsługi zdarzenia When NextButton.Click powinien teraz wyglądać następująco:<br />
<br />
<br />
===Jak działają bloki?===<br />
Warunek if porównuje teraz wartość zmiennej CurrentQuestionIndex z długością zmiennej QuestionList. Zatem jeżeli zmienna CurrentQuestionIndex ma wartość 4, a długość zmiennej QuestionList wynosi 4, to wartość zmiennej currentQuestionIndex zostanie ustawiona na 0 (a następnie na 1, 2 itd.). Zauważ - bloki nie odwołują się już do 3 ani żadnej innej określonej wartości, dlatego instrukcja będzie działać bez względu na liczbę elementów listy.<br />
<br />
Przetestuj zmodyfikowane zachowanie. Czy po kliknięciu przycisku NextButton aplikacja przechodzi teraz przez cztery pytania, wracając po ostatnim do pierwszego?<br />
<br />
==Przełączanie zdjęcia dla każdego pytania==<br />
Na razie aplikacja wyświetla to samo zdjęcie, bez względu na to, jakie pytanie zostaje zadane. Możesz to zmienić tak, aby po kliknięciu przycisku NextButton pojawiała się fotografia dotycząca danego pytania. W obszarze Media dostępne są cztery dodane wcześniej zdjęcia. Teraz utworzymy trzecią listę - PictureList, której elementami będą nazwy plików zdjęć, a następnie zmodyfikujemy blok obsługi zdarzenia When NextButton.Click, aby program po każdym pytaniu przełączał zdjęcie.<br />
Najpierw utwórz listę PictureList i zainicjuj ją nazwami plików graficznych. Upewnij się, czy nazwy są dokładnie takie same jak nazwy plików, które zostały załadowane do obszaru Media. Oto jak powinien wyglądać blok dla listy PictureList:<br />
<br />
Następnie zmodyfikuj blok obsługi zdarzeń When NextButton.Click, aby zmieniał wyświetlane zdjęcie w zależności od zadanego pytania. Jeżeli ustawisz właściwość Image.Picture na nazwę pliku zdjęcia, które zostało załadowane, właśnie ta fotografia zostanie wyświetlona. Aby zmodyfikować blok When NextButton.Click, potrzebujesz następujących bloków:<br />
{| class="wikitable"<br />
!Typ bloku<br />
!Kategoria<br />
!Działanie<br />
|-<br />
|set Image1.Picture to<br />
|Image1<br />
|ustaw, aby zmieniać zdjęcie<br />
|-<br />
|select list item<br />
|Lists<br />
|należy wybrać zdjęcie odpowiadające na aktualne pytanie<br />
|-<br />
|get global PictureList<br />
|Variables<br />
|wybierz nazwę pliku z tej listy<br />
|-<br />
|get global currentQuestionIndex<br />
|Variables<br />
|wybierz element o n-tym indeksie currentQuestionIndex<br />
|}<br />
Oto jak powinny wyglądać bloki:<br />
<br />
===Jak działają bloki?===<br />
Zmienna CurrentQuestionIndex służy jako indeks dla zmiennej QuestionList. Wartość CurrentQuestionIndex wynosi 1, aplikacja wybiera pierwsze pytanie i pierwsze zdjęcie. Gdy CurrentQuestionIndex wynosi 2, aplikacja wybiera drugie pytanie i drugie zdjęcie. Oczywiście takie działanie zależy od tego, czy listy są ze sobą zsynchronizowane. Tak jest w tym przypadku - pierwszy obraz - LarsenBerra.jpg to zdjęcie Dona Larsena, jednocześnie Don Larsen to odpowiedź na pierwsze pytanie (Kto był doskonałym miotaczem w World Series?). <br />
Przetestuj zmodyfikowane zachowanie. Czy nowe zdjęcie pojawia się po każdym kliknięciu przycisku NextButton?<br />
<br />
==Ocena udzielanych odpowiedzi==<br />
Teraz dodamy bloki, które określają, czy użytkownik odpowiedział na pytanie prawidłowo, czy też nie. Gracz wprowadza odpowiedź do AnswerText, a następnie klika przycisk AnswerButton. Aplikacja musi porównać wpis użytkownika z odpowiedzią na bieżące pytanie, używając bloku if... then... w celu jej sprawdzenia. Etykieta RightWrongLabel powinna być modyfikowana, aby podawać, czy odpowiedź jest prawidłowa, czy nie.<br />
<br />
Do tego zachowania będą potrzebne następujące bloki:<br />
{| class="wikitable"<br />
!Typ bloku<br />
!Kategoria<br />
!Działanie<br />
|-<br />
|when AnswerButton.Click<br />
|AnswerButton<br />
|zachowanie jest wyzwalane, gdy użytkownik kliknie przycisk AnswerButton<br />
|-<br />
|if... then...<br />
|Control<br />
|Użyj mutatora, aby dodać alternatywę (else). Jeżeli odpowiedź jest prawidłowa - zrób jedno, w przeciwnym razie (else) - zrób coś innego<br />
|-<br />
|= <br />
|Math<br />
|sprawdzenie, czy odpowiedź jest prawidłowa<br />
|-<br />
|AnswerText.Text<br />
|AnswerText<br />
|Odpowiedź użytkownika pojawia się w tym polu tekstowym<br />
|-<br />
|select list item<br />
|Lists<br />
|wybrać bieżącą odpowiedź z listy AnswerList<br />
|-<br />
|get global AnswerList<br />
|Variables<br />
|lista, z której jest wybierany element<br />
|-<br />
|get global currentQuestionIndex<br />
|Variables<br />
|numer pytania (i numer odpowiedzi), przy którym jest użytkownik<br />
|-<br />
|set RightWrongLabel.Text to<br />
|RightWrongLabel<br />
|tutaj podaj odpowiedź<br />
|-<br />
|Dobrze!<br />
|Text<br />
|jeżeli odpowiedź jest prawidłowa<br />
|-<br />
|set RightWrongLabel.Text to<br />
|RightWrongLabel<br />
|tutaj podaj odpowiedź<br />
|-<br />
|Źle<br />
|Text<br />
|jeżeli odpowiedź jest nieprawidłowa<br />
|}<br />
Bloki powinny wyglądać następująco:<br />
<br />
===Jak działają bloki?===<br />
Test if sprawdza, czy odpowiedź użytkownika (AnswerText.Text) jest taka sama, jak element na liście AnswerList o indeksie równym wartości zmiennej CurrentQuestionIndex. Jeżeli zmienna CurrentQuestionIndex ma wartość 1, aplikacja porównuje odpowiedź użytkownika z pierwszą pozycją na liście AnswerList, (Don Larsen). Jeżeli zmienna CurrentQuestionIndex zmieni wartość na 2, program zestawia odpowiedź z drugą pozycją na liście, czyli Dallas Branden. Jeśli wynik porównania jest pozytywny, przeprowadzane są bloki then, a treść etykiety RightWrongLabel zostaje ustawiona na Dobrze!. Jeżeli wynik testu jest negatywny (fałszywy), przeprowadzane są bloki alternatywy (else), a treść etykiety RightWrongLabel zostaje ustawiona na Źle.<br />
<br />
Przetestuj zmodyfikowaną aplikację. Spróbuj odpowiedzieć na jedno z pytań. Powinna pojawić się ocena, czy odpowiedź była dokładnie taka sama, jak na liście AnswerList. Sprawdź zarówno prawidłowe, jak i nieprawidłowe odpowiedzi (Uwaga - uwzględniana jest wielkość liter!). Kliknij przycisk NextButton i odpowiedz na drugie pytanie. Czy aplikacja nadal działa? Powinna, ale zauważ, że gdy klikniesz przycisk NextButton, tekst Dobrze! lub Źle oraz poprzednia odpowiedź nadal będą wyświetlane. Choć nie wpływa to zasadniczo na naszą grę, to takie szczegóły interfejsu z pewnością zostaną zauważone przez użytkowników Twojej aplikacji.<br />
<br />
Aby wyzerować etykietę RightWrongLabel i AnswerText, umieść poniższe bloki w bloku obsługi zdarzeń When NextButton.click:<br />
{| class="wikitable"<br />
!Typ bloku<br />
!Kategoria<br />
!Działanie<br />
|-<br />
|set RightWrongLabel.Text to<br />
|RightWrongLabel<br />
|Ustawia wartość etykiety na…<br />
|-<br />
|„ „<br />
|Text<br />
|pusty tekst<br />
|-<br />
|set AnswerText.Text to<br />
|AnswerText<br />
|Ustawia wartość etykiety na…<br />
|-<br />
|„ „<br />
|Text<br />
|pusty tekst<br />
|}<br />
Bloki powinny wyglądać następująco:<br />
<br />
===Jak działają bloki?===<br />
Po kliknięciu przycisku NextButton użytkownik przechodzi do następnego pytania, dlatego początkowe wiersze bloku obsługi zdarzeń zerują etykietę RightWrongLabel i pole AnswerText.<br />
Przetestuj to zachowanie Odpowiedz na pytanie i kliknij przycisk Wyślij, a następnie - NextButton. Czy Twoja poprzednia odpowiedź i jej ocena zniknęły?<br />
<br />
==Ostateczna postać programu==<br />
Oto gotowa aplikacja QuizMe:<br />
<br />
Utwórz wykonywalną wersję aplikacji, wybierając menu Build/App (provide QR code for .apk). Gdy pojawi się kod kreskowy, użyj czytnika kodów w telefonie, aby pobrać i zainstalować aplikację.<br />
<br />
===Modyfikacje===<br />
Quiz w tej wersji jest już gotowy. Czy masz ochotę przemyśleć pewne zmiany?<br />
<br />
Zamiast wyświetlać zdjęcie dla każdego pytania, spróbuj odtworzyć dźwięk lub krótkie wideo. Za pomocą dźwięku możesz zmienić quiz w aplikację Jaka to melodia?.<br />
<br />
Quiz akceptuje ściśle określone odpowiedzi. Jeśli gracz odpowiedziałby, lekko przekształcając tekst (np. podając inicjał zamiast imienia), program uzna to za błąd. Można to zmienić na kilka różnych sposobów. Jednym z nich jest użycie bloku text.contains, aby sprawdzić, czy odpowiedź użytkownika zawiera prawidłową odpowiedź. Inny sposób to dostarczenie wielu odpowiedzi na każde pytanie i sprawdzenie przez iterację (użycie bloku for each), czy któraś z nich pasuje.<br />
<br />
Przekształć quiz tak, aby przedstawiał odpowiedzi do wyboru. Lista odpowiedzi będzie musiała być listą list, a każda podrzędna lista będzie musiała zawierać opcje odpowiedzi. Użyj komponentu ListPicker, aby umożliwić użytkownikowi wybranie odpowiedzi.<br />
<br />
<br />
==Podsumowanie==<br />
Oto niektóre koncepcje omówione w tym przewodniku:<br />
<ul><li>Aplikacje można tworzyć w sposób ogólny, aby pracować z dowolną listą danych.</li><br />
<li>Zmienne indeksu są wykorzystywane do śledzenia bieżącej pozycji na liście. Zwiększając wartość zmiennej indeksu, należy uważać na przekroczenie końca listy.</li></ul><br />
<br />
==Zeskanuj próbną aplikację do telefonu==<br />
Aby zainstalować i uruchomić aplikację próbną, zeskanuj poniższy kod kreskowy:<br />
<br />
==Pobierz kod źródłowy==<br />
Jeżeli chcesz pracować z tą próbką w programie App Inventor:<br />
<ul><li>pobierz na komputer kod źródłowy: [http://appinventor.mit.edu/explore/sites/all/files/ai2tutorials/QuizMe/QuizMe_MIT.aia http://appinventor.mit.edu/explore/sites/all/files/ai2tutorials/QuizMe/QuizMe_MIT.aia]</li><br />
<li>otwórz program App Inventor,</li><br />
<li>kliknij opcję My Projects,</li><br />
<li>wybierz Import project (.aia) from my computer...</li><br />
<li>znajdź i zatwierdź pobrany kod źródłowy.</li></ul></div>M Kelniarzhttp://wiki.mistrzowiekodowania.pl/index.php?title=QuizMeQuizMe2015-03-15T18:24:07Z<p>M Kelniarz: /* Projektowanie aplikacji */</p>
<hr />
<div>=Aplikacja QuizMe dla App Inventor 2=<br />
<br />
==Co tworzysz?==<br />
[[Plik:t6-1.png|right]]QuizMe to gra dotycząca ciekawostek baseballowych, ale można jej użyć jako szablonu do tworzenia quizów z dowolnej dziedziny. W aplikacji użytkownik odpowiada na szereg pytań, otrzymując następnie informację zwrotną, czy udzielił poprawnej, czy błędnej odpowiedzi. Gracz przechodzi do kolejnego pytania, klikając przycisk.<br />
<br />
W grze QuizMe dysponujemy zamkniętym zbiorem pytań, chyba że programista je zmieni. W następnym etapie można utworzyć MakeQuiz & TakeQuiz – aplikację, która pozwala użytkownikom na tworzenie i modyfikowanie pytań.<br />
<br />
Poradnik ten zakłada, że znasz już podstawy tworzenia aplikacji w App Inventorze – korzystanie z Projektanta komponentów w celu utworzenia interfejsu użytkownika i z Edytora bloków, aby określić obsługę zdarzeń. Jeżeli potrzebujesz przypomnienia, spróbuj popracować z poradnikami podstawowymi zanim przejdziesz dalej.<br />
<br />
==Zaczynamy!==<br />
Połącz się z witryną internetową App Inventor i załóż nowy projekt. Nazwij go QuizMe, ustaw taki sam tytuł ekranu (Title). Za pomocą MIT AI2 Companion połącz program z urządzeniem mobilnym. Pobierz poniższe zdjęcia baseballistów i zapisz je w komputerze. Później załadujesz je do projektu.<br />
<ul><li> [http://beta.appinventor.mit.edu/learn/tutorials/quizme/QuizMeAssets/Larsenberra.jpg Larsenberra.jpg]</li><br />
<li> [http://beta.appinventor.mit.edu/learn/tutorials/quizme/QuizMeAssets/dallasbraden.jpg Dallasbraden.jpg]</li><br />
<li> [http://beta.appinventor.mit.edu/learn/tutorials/quizme/QuizMeAssets/cyyoung.jpg Cyyoung.jpg]</li><br />
<li> [http://beta.appinventor.mit.edu/learn/tutorials/quizme/QuizMeAssets/nolanryan.jpg Nolanryan.jpg]</li></ul><br />
<br />
==Wstęp==<br />
Zaprojektujesz grę typu quiz, w której użytkownik będzie przechodził do kolejnych pytań, klikając przycisk Dalej, a następnie otrzymywał prostą ocenę Dobrze/Źle dla każdej odpowiedzi.<br />
<br />
W tym przewodniku omówimy:<br />
<ul><li>definiowanie i wyświetlanie listy informacji;</li><br />
<li>przechodzenie przez listę za pomocą zmiennej indeksującej – zmiennej, która śledzi pozycję na liście;</li><br />
<li>zachowania warunkowe – wykonywanie określonych operacji tylko wtedy, gdy spełniony jest określony warunek;</li><br />
<li>Zmianę zdjęcia w zależności od sytuacji.</li></ul><br />
<br />
==Projektowanie aplikacji==<br />
Użyj Projektanta komponentów do utworzenia interfejsu dla aplikacji QuizMe. <br />
Aby utworzyć interfejs, najpierw załaduj do projektu pobrane zdjęcia. Kliknij przycisk Prześlij plik (Upload File...) w obszarze Media i wybierz jeden z pobranych wcześniej plików (np. Larsenberra.jpg). Następnie zrób to samo z pozostałymi trzema zdjęciami.<br />
Utwórz następujące komponenty, przeciągając je z Palety (Palette) do Przeglądarki (Viewer) i ustaw właściwości komponentów zgodnie z poniższym opisem:<br />
{|class="wikitable"<br />
! Typ komponentu<br />
! Kategoria<br />
! Jaką nadać jej nazwę<br />
! Działanie<br />
! Działanie komponentu<br />
|-<br />
|Image<br />
|User interface<br />
|Image1<br />
|Ustaw właściwość zdjęcia (Picture) na Larsenberra.jpg. Jest to pierwsze wyświetlane zdjęcie.<br />
|Obrazkowa część pytania<br />
|-<br />
|Label<br />
|User interface<br />
|QuestionLabel<br />
|Zmień właściwość tekstu (Text) na Pytanie:<br />
|Wyświetla bieżące pytanie<br />
|-<br />
|HorizontalArrangement<br />
|Layout<br />
|HorizontalArrangement1<br />
| <br />
|Organizuje komponenty AnswerPrompt i Text (podaj odpowiedź i tekst)<br />
|-<br />
|Label<br />
|User interface<br />
|AnswerPromptLabel<br />
|Zmień właściwość tekstu (Text) na Podaj odpowiedź:. Na ekranie przeglądarki przesuń tę etykietę do HorizontalArrangement1.<br />
|Wyświetla tekst prośby o odpowiedź.<br />
|-<br />
|TextBox<br />
|User interface<br />
|AnswerText<br />
|Zmień wskazówkę (Hint) na Podaj odpowiedź. Na ekranie przeglądarki przenieś AnswerText do komponentu HorizontalArrangement1.<br />
|Tutaj użytkownik podaje odpowiedź.<br />
|-<br />
|Label<br />
|User interface <br />
|RightWrongLabel<br />
|Zmień właściwość tekstu (Text) na Dobrze/Źle.<br />
|Tutaj wyświetlana jest ocena Dobrze/Źle.<br />
|-<br />
|HorizontalArrangement<br />
|Layout<br />
|HorizontalArrangement2<br />
|<br />
|Organizuje przyciski AnswerButton i NextButton (przycisk odpowiedzi i przycisk dalej).<br />
|-<br />
|Przycisk<br />
|User interface<br />
|AnswerButton<br />
|Zmień właściwość tekstu (Text) na Wyślij. Na ekranie przeglądarki przesuń ten przycisk do HorizontalArrangment2.<br />
|Użytkownik klika, aby przesłać odpowiedź.<br />
|-<br />
|Przycisk<br />
|User interface<br />
|NextButton<br />
|Zmień właściwość tekstu (Text) na Dalej. Przenieś ten przycisk do HorizontalArrangement2.<br />
|Użytkownik klika, aby przejść do następnego pytania.<br />
|} <br />
Po zakończeniu powinien on wyglądać jak poniższa ilustracja (pod nią znajdują się również bardziej szczegółowe informacje).<br />
[[Plik:t6-2.png]]<br />
<br />
==Programowanie aplikacji==<br />
Otwórz Edytor bloków, aby zaprogramować działanie komponentów. Najpierw zdefiniuj dwie zmienne - listy: zmienną QuestionList, zawierającą listę pytań i zmienną AnswerList z listą odpowiedzi na te pytania.<br />
<br />
Aby zdefiniować te dwie zmienne listy, potrzebujesz następujących bloków:<br />
{| class="wikitable"<br />
!Typ bloku<br />
!Kategoria<br />
!Działanie<br />
|-<br />
|initialize global name to<br />
|Variables<br />
|Definiuje zmienną QuestionList (zmień jej nazwę)<br />
|-<br />
|initialize global name to<br />
|Variables<br />
|Definiuje zmienną AnswerList (zmień jej nazwę)<br />
|-<br />
|make a list<br />
|Lists<br />
|Służy do dodawania elementów do zmiennej QuestionList<br />
|-<br />
|„ „ (trzykrotnie)<br />
|Lists<br />
|Służy do wpisania pytań<br />
|-<br />
|make a list<br />
|Lists<br />
|Służy do dodawania elementów do zmiennej AnswerList<br />
|-<br />
|„ „ (trzykrotnie)<br />
|Text<br />
|Służy do wpisania odpowiedzi<br />
|}<br />
Utwórz zmienne całościowe, przeciągając z kategorii zmiennych (Variables) na obszar roboczy blok Initialize global name to. Kliknij dwukrotnie domyślną nazwę name, aby ją zmienić. Blok Initialize global name to zawiera pole na początkową wartość zmiennej. Zmienna może zawierać liczbę, tekst, a nawet listę – aby ją utworzyć, podłącz blok Make a list do definicji zmiennej.<br />
<br />
Bloki powinny wyglądać następująco:<br />
===Zdefiniuj ukrytą zmienną Index===<br />
Za każdym razem, gdy użytkownik kliknie przycisk NextButton, aby przejść dalej, aplikacja musi pamiętać, przy którym pytaniu jest obecnie gracz. W języku programowania, aby coś zapamiętać, trzeba zdefiniować nową zmienną. W tym przypadku aplikacja musi zapamiętać bieżący numer pytania – indeks listy QuestionList.<br />
Aby zdefiniować zmienną currentQuestionIndex, potrzebujesz następujących bloków:<br />
{| class="wikitable"<br />
!Typ bloku<br />
!Kategoria<br />
!Działanie<br />
|-<br />
|initialize global name to<br />
|Variables<br />
|Definiuje zmienną currentQuestionIndex (zmień nazwę)<br />
|-<br />
|0 (1)<br />
|Math<br />
|Ustaw wartość początkową currentQuestionIndex na 1 (zmień liczbę)<br />
|}<br />
Bloki powinny wyglądać następująco:<br />
<br />
===Wyświetl pierwsze pytanie===<br />
Odłóż na razie kwestię odpowiedzi i skup się na zaprogramowaniu sekwencyjnego przejścia przez pytania. Pożądane zachowanie jest następujące: po uruchomieniu aplikacji na etykiecie o nazwie QuestionLabel pojawia się pierwsze pytanie. Gdy użytkownik kliknie NextButton, wyświetlone zostaje drugie pytanie. Po ponownym kliknięciu pojawia się trzecie pytanie. Po dotarciu do ostatniego pytania kliknięcie przycisku NextButton powoduje ponowne pojawienie się pierwszego pytania w etykiecie QuestionLabel.<br />
<br />
W programie App Inventor określone pozycje na liście są wybierane za pomocą bloku select list item. W tym bloku trzeba podać listę i indeks – pozycję na liście. Jeżeli na liście są trzy pozycje, prawidłowe indeksy to 1, 2 i 3.<br />
<br />
Po uruchomieniu aplikacja QuizMe powinna wybrać pierwsze pytanie z listy i wyświetlić je w komponencie QuestionLabel. Do tego zachowania inicjalizującego działanie aplikacji potrzebne są następujące bloki:<br />
<br />
{| class="wikitable"<br />
!Typ bloku<br />
!Kategoria<br />
!Działanie<br />
|-<br />
|when Screen1.Initialize<br />
|Screen1<br />
|Podczas uruchamiania aplikacji zainicjowana jest ta obsługa zdarzenia<br />
|-<br />
|set QuestionLabel.Text to<br />
|QuestionLabel<br />
|Umieszcza pierwsze pytanie w etykiecie QuestionLabel<br />
|-<br />
|select list item<br />
|Lists<br />
|Wybiera pierwsze pytanie z etykiety QuestionLabel<br />
|-<br />
|get <br />
|Variables<br />
|Ustala listę, z której jest wybierany element. Tutaj: Global QuestionList<br />
|-<br />
|0 (1)<br />
|Math<br />
|Wybiera pierwsze pytanie za pomocą indeksu 1. Ustaw wartość na 1.<br />
|}<br />
Bloki powinny wyglądać następująco:<br />
<br />
===Jak działają bloki?===<br />
Zdarzenie when Screen1.Initialize jest wyzwalane podczas uruchomienia aplikacji. Pierwsza pozycja zmiennej QuestionList zostaje wybrana i umieszczona w bloku set QuestionLabel.Text. Gdy aplikacja zostanie uruchomiona, użytkownik zobaczy pierwsze pytanie.<br />
===Przetestuj to zachowanie===<br />
Jeśli dotychczas nie skomunikowałeś urządzenia mobilnego z programem, zrób to teraz. Co pojawia się na urządzeniu? Jeżeli utworzono listę QuestionList tak, jak wskazano powyżej, w etykiecie QuestionLabel powinna pojawić się pierwsza pozycja tej listy (Kto był doskonałym miotaczem w World Series?).<br />
<br />
==Iteracja pytań==<br />
Zdefiniowałeś już zmienną CurrentQuestionIndex, zapamiętującą pytanie, przy którym znajduje się użytkownik. Zaprogramuj teraz zachowanie przycisku NextButton. Gdy zostanie on kliknięty, aplikacja zwiększy wartość zmiennej, np. zmieni ją z 1 na 2 lub z 2 na 3 itd., a następnie użyje tej wartości do zaznaczenia nowego bieżącego pytania. Do tego zachowania potrzebne są następujące bloki:<br />
{| class="wikitable"<br />
!Typ bloku<br />
!Kategoria<br />
!Działanie<br />
|-<br />
|when NextButton.Click<br />
|NextButton<br />
|Uruchamia obsługę zdarzeń po kliknięciu przycisku<br />
|-<br />
|set currentQuestionIndex to<br />
|Zmienne<br />
|Decyduje o ustawieniu indeksu wybranej listy<br />
|-<br />
|+ <br />
|Math<br />
|Służy do zwiększania wartości zmiennej currentQuestionIndex<br />
|-<br />
|get global currentQuestionIndex<br />
|Zmienne<br />
|Tworzy nową wartość poprzez zwiększenie poprzedniej wartości o 1<br />
|-<br />
|0 (1)<br />
|Math<br />
|Dla + 1<br />
|-<br />
|set QuestionLabel.Text to<br />
|QuestionLabel<br />
|Wyświetla kolejne pytanie<br />
|-<br />
|select list item<br />
|Listy<br />
|Ustawia element listy jako wartość QuestionLabel<br />
|-<br />
|get global QuestionList<br />
|Zmienne<br />
|Wskazuje, która lista będzie wybrana<br />
|-<br />
|get global currentQuestionIndex<br />
|Zmienne<br />
|Wskazuje, który element wybranej listy będzie wybrany<br />
|}<br />
Bloki powinny wyglądać następująco:<br />
<br />
===Jak działają bloki?===<br />
Pierwszy wiersz polecenia zwiększa wartość zmiennej currentQuestionIndex o 1 (jeżeli zmienna zawiera wartość 1, zostaje ona zmieniona na 2, z 2 na 3 itd.). Następnie wykorzystuje nową wartość do wyboru pytania o tym indeksie.<br />
<br />
Przypomnijmy, że w bloku obsługi zdarzeń Screen.Initialize aplikacja wybrała pierwsze do wyświetlenia pytanie:<br />
<br />
Po kliknięciu przycisku NextButton aplikacja nie wybiera konkretnie pierwszej, drugiej czy trzeciej pozycji na liście, tylko pozycję o n-tej wartości zmiennej currentQuestionIndex.<br />
<br />
Polecenia w blokach są wykonywane od prawej do lewej, tzn. aplikacja najpierw określa wartość parametru z bloku Select list item, którym jest zmienna CurrentQuestionIndex. Liczba zawarta w tej zmiennej zostaje użyta jako indeks podczas wykonania poleceń zawartych w bloku Select list item.<br />
<br />
Po pierwszym kliknięciu przycisku NextButton, wartość zmiennej currentQuestionIndex przeskoczy z 1 na 2, aby aplikacja wybrała drugą pozycję z listy QuestionList (Kto był pierwszym doskonałym miotaczem w 2010?). Po drugim kliknięciu przycisku NextButton, wartość zmiennej currentQuestionIndex zostanie zmieniona z 2 na 3, a aplikacja wybierze trzecie pytanie z listy (Kto był pierwszym doskonałym miotaczem nowej ery?).<br />
===Przetestuj to zachowanie===<br />
Przetestuj zachowanie przycisku NextButton, aby sprawdzić, czy aplikacja działa poprawnie. Wciel się w rolę użytkownika i kliknij przycisk NextButton w telefonie. Czy urządzenie wyświetliło drugie pytanie: Kto był pierwszym doskonałym miotaczem w 2010?? Trzecie pytanie powinno pojawić się po kolejnym kliknięciu przycisku. Jeżeli aplikacja działa, pogratuluj sobie i przejdź dalej. Kliknij przycisk NextButton ponownie (po raz trzeci). Powinien zostać wyświetlony błąd: Próba uzyskania elementu 4 z listy o długości 3. Czy wiesz, na czym polega problem?<br />
<br />
Problem z aplikacją polega na tym, że zawsze po kliknięciu przycisku NextButton zwiększa ona zmienną CurrentQuestionIndex o 1. Gdy wartość zmiennej wynosi już 3, a użytkownik kolejny raz kliknie przycisk NextButton, aplikacja zmieni wartość zmiennej z 3 na 4, następnie wywoła blok Select list item, aby odczytać pozycję o aktualnym indeksie CurrentQuestionIndex, czyli w tym przypadku czwartą pozycję. Ponieważ zmienna QuestionList zawiera tylko trzy elementy, Android wykaże błąd.<br />
<br />
Aplikacja musi zadawać pytanie - sprawdzać warunek - gdy nastąpi kliknięcie przycisku NextButton i realizować polecenia zawarte w różnych blokach w zależności od odpowiedzi. Elementem do sprawdzenia jest to, czy zmienna CurrentQuestionIndex już ma wartość 3. Jeżeli tak - należy ustawić CurrentQuestionIndex z powrotem na 0, aby użytkownik wrócił do pierwszego pytania.<br />
<br />
Będziesz potrzebował następujących bloków:<br />
{| class="wikitable"<br />
!Typ bloku<br />
!Kategoria<br />
!Działanie<br />
|-<br />
|if then<br />
|Control<br />
|sprawdzenie, czy użytkownik jest na etapie ostatniego pytania<br />
|-<br />
|= <br />
|Math<br />
|sprawdzenie, czy currentQuestionIndex ma wartość 3<br />
|-<br />
|get global currentQuestionIndex<br />
|Variables<br />
|<br />
|-<br />
|0 (3)<br />
|Math<br />
|3 to numer na liście<br />
|-<br />
|set currentQuestionIndex to<br />
|Variables<br />
|ustawienie na 0, aby wrócić do pierwszego pytania<br />
|-<br />
|0<br />
|Math<br />
|ustawienie na 0, ponieważ kolejne bloki zwiększą wartość do 1<br />
|}<br />
Zmodyfikowany blok obsługi zdarzenia When NextButton.Click powinien wyglądać następująco:<br />
<br />
===Jak działają bloki===<br />
Po kliknięciu przycisku NextButton aplikacja najpierw sprawdza, czy currentQuestionIndex ma wartość 3. Jeżeli tak, wartość tej zmiennej jest ustawiana na 0, aby po zwiększeniu jej w dalszych krokach jej wartość wyniosła 1. Wtedy quiz wróci do pierwszego pytania. Zauważ, że tylko bloki osadzone w bloku if-then są zależne od warunku. Blok zwiększenia wartości i blok Set QuestionLabel.Text to są wykonywane bez względu na jakikolwiek warunek.<br />
<br />
==Aplikacja modyfikowalna: Ułatwianie modyfikowania pytań==<br />
Teraz zmodyfikujemy aplikację, aby można było łatwo dodawać i usuwać elementy z listy. Zmień bloki tak, aby działały na liście o dowolnej długości, a nie tylko liście z dokładnie trzema pozycjami. <br />
Na początek dodaj czwarte pytanie do zmiennej QuestionList i kolejną odpowiedź do AnswerList. W tym celu musisz najpierw zwiększyć liczbę dostępnych pól za pomocą przycisku modyfikującego (mutatora). Aby dowiedzieć się więcej o tym elemencie, zobacz: http://appinventor.mit.edu/explore/ai2/support/concepts/mutators. Bloki powinny wyglądać następująco:<br />
<br />
===Przetestuj zmodyfikowaną aplikację.===<br />
Kliknij przycisk NextButton kilka razy. Zauważysz, że czwarte pytanie nigdy się nie pojawia, bez względu na to, ile razy klikniesz przycisk.<br />
<br />
Problemem jest to, że test sprawdzający, czy użytkownik znajduje się przy ostatnim pytaniu, jest zbyt szczegółowy: pyta, czy zmienna CurrentQuestionIndex ma wartość 3:<br />
<br />
Możesz po prostu zmienić liczbę z 3 na 4, a aplikacja będzie znów działać poprawnie. Problem polega jednak na tym, że za każdym razem, gdy zmodyfikujesz liczbę pytań i odpowiedzi, będziesz musiał pamiętać, aby dokonać także tej zmiany. Takie zależności w programie komputerowym często prowadzą do błędów, w szczególności gdy aplikacja staje się bardziej złożona. Znacznie lepiej jest przygotować program w taki sposób, aby działał niezależnie od liczby pytań. Takie uogólnienie jest jeszcze ważniejsze, gdy lista, z którą pracujesz, zmienia się dynamicznie, na przykład w aplikacji z quizem, gdzie użytkownik może dodawać nowe pytania.<br />
<br />
Lepszym rozwiązaniem jest sprawdzenie warunku w sposób bardziej ogólny. Tak naprawdę chcesz wiedzieć, czy bieżące pytanie – czyli wartość zmiennej currentQuestionIndex jest tak duża, jak ilość elementów w zmiennej QuestionList. Jeżeli aplikacja sprawdzi warunek w bardziej ogólny sposób, to będzie działać, nawet jeżeli dodasz lub usuniesz elementy ze zmiennej QuestionList. Aby zmienić blok obsługi zdarzenia When NextButton.Click, zmień poprzedni test sprawdzający, który odnosił się bezpośrednio do 3. Będziesz potrzebował następujących bloków:<br />
{| class="wikitable"<br />
!Typ bloku<br />
!Szuflada<br />
!Działanie<br />
|-<br />
|length of list<br />
|Lists<br />
|Pyta, ile elementów jest w zmiennej QuestionList<br />
|-<br />
|get global QuestionList<br />
|Variables<br />
|Określa, o którą listę chodzi<br />
|}<br />
Blok obsługi zdarzenia When NextButton.Click powinien teraz wyglądać następująco:<br />
<br />
<br />
===Jak działają bloki?===<br />
Warunek if porównuje teraz wartość zmiennej CurrentQuestionIndex z długością zmiennej QuestionList. Zatem jeżeli zmienna CurrentQuestionIndex ma wartość 4, a długość zmiennej QuestionList wynosi 4, to wartość zmiennej currentQuestionIndex zostanie ustawiona na 0 (a następnie na 1, 2 itd.). Zauważ - bloki nie odwołują się już do 3 ani żadnej innej określonej wartości, dlatego instrukcja będzie działać bez względu na liczbę elementów listy.<br />
<br />
Przetestuj zmodyfikowane zachowanie. Czy po kliknięciu przycisku NextButton aplikacja przechodzi teraz przez cztery pytania, wracając po ostatnim do pierwszego?<br />
<br />
==Przełączanie zdjęcia dla każdego pytania==<br />
Na razie aplikacja wyświetla to samo zdjęcie, bez względu na to, jakie pytanie zostaje zadane. Możesz to zmienić tak, aby po kliknięciu przycisku NextButton pojawiała się fotografia dotycząca danego pytania. W obszarze Media dostępne są cztery dodane wcześniej zdjęcia. Teraz utworzymy trzecią listę - PictureList, której elementami będą nazwy plików zdjęć, a następnie zmodyfikujemy blok obsługi zdarzenia When NextButton.Click, aby program po każdym pytaniu przełączał zdjęcie.<br />
Najpierw utwórz listę PictureList i zainicjuj ją nazwami plików graficznych. Upewnij się, czy nazwy są dokładnie takie same jak nazwy plików, które zostały załadowane do obszaru Media. Oto jak powinien wyglądać blok dla listy PictureList:<br />
<br />
Następnie zmodyfikuj blok obsługi zdarzeń When NextButton.Click, aby zmieniał wyświetlane zdjęcie w zależności od zadanego pytania. Jeżeli ustawisz właściwość Image.Picture na nazwę pliku zdjęcia, które zostało załadowane, właśnie ta fotografia zostanie wyświetlona. Aby zmodyfikować blok When NextButton.Click, potrzebujesz następujących bloków:<br />
{| class="wikitable"<br />
!Typ bloku<br />
!Kategoria<br />
!Działanie<br />
|-<br />
|set Image1.Picture to<br />
|Image1<br />
|ustaw, aby zmieniać zdjęcie<br />
|-<br />
|select list item<br />
|Lists<br />
|należy wybrać zdjęcie odpowiadające na aktualne pytanie<br />
|-<br />
|get global PictureList<br />
|Variables<br />
|wybierz nazwę pliku z tej listy<br />
|-<br />
|get global currentQuestionIndex<br />
|Variables<br />
|wybierz element o n-tym indeksie currentQuestionIndex<br />
|}<br />
Oto jak powinny wyglądać bloki:<br />
<br />
===Jak działają bloki?===<br />
Zmienna CurrentQuestionIndex służy jako indeks dla zmiennej QuestionList. Wartość CurrentQuestionIndex wynosi 1, aplikacja wybiera pierwsze pytanie i pierwsze zdjęcie. Gdy CurrentQuestionIndex wynosi 2, aplikacja wybiera drugie pytanie i drugie zdjęcie. Oczywiście takie działanie zależy od tego, czy listy są ze sobą zsynchronizowane. Tak jest w tym przypadku - pierwszy obraz - LarsenBerra.jpg to zdjęcie Dona Larsena, jednocześnie Don Larsen to odpowiedź na pierwsze pytanie (Kto był doskonałym miotaczem w World Series?). <br />
Przetestuj zmodyfikowane zachowanie. Czy nowe zdjęcie pojawia się po każdym kliknięciu przycisku NextButton?<br />
<br />
==Ocena udzielanych odpowiedzi==<br />
Teraz dodamy bloki, które określają, czy użytkownik odpowiedział na pytanie prawidłowo, czy też nie. Gracz wprowadza odpowiedź do AnswerText, a następnie klika przycisk AnswerButton. Aplikacja musi porównać wpis użytkownika z odpowiedzią na bieżące pytanie, używając bloku if... then... w celu jej sprawdzenia. Etykieta RightWrongLabel powinna być modyfikowana, aby podawać, czy odpowiedź jest prawidłowa, czy nie.<br />
<br />
Do tego zachowania będą potrzebne następujące bloki:<br />
{| class="wikitable"<br />
!Typ bloku<br />
!Kategoria<br />
!Działanie<br />
|-<br />
|when AnswerButton.Click<br />
|AnswerButton<br />
|zachowanie jest wyzwalane, gdy użytkownik kliknie przycisk AnswerButton<br />
|-<br />
|if... then...<br />
|Control<br />
|Użyj mutatora, aby dodać alternatywę (else). Jeżeli odpowiedź jest prawidłowa - zrób jedno, w przeciwnym razie (else) - zrób coś innego<br />
|-<br />
|= <br />
|Math<br />
|sprawdzenie, czy odpowiedź jest prawidłowa<br />
|-<br />
|AnswerText.Text<br />
|AnswerText<br />
|Odpowiedź użytkownika pojawia się w tym polu tekstowym<br />
|-<br />
|select list item<br />
|Lists<br />
|wybrać bieżącą odpowiedź z listy AnswerList<br />
|-<br />
|get global AnswerList<br />
|Variables<br />
|lista, z której jest wybierany element<br />
|-<br />
|get global currentQuestionIndex<br />
|Variables<br />
|numer pytania (i numer odpowiedzi), przy którym jest użytkownik<br />
|-<br />
|set RightWrongLabel.Text to<br />
|RightWrongLabel<br />
|tutaj podaj odpowiedź<br />
|-<br />
|Dobrze!<br />
|Text<br />
|jeżeli odpowiedź jest prawidłowa<br />
|-<br />
|set RightWrongLabel.Text to<br />
|RightWrongLabel<br />
|tutaj podaj odpowiedź<br />
|-<br />
|Źle<br />
|Text<br />
|jeżeli odpowiedź jest nieprawidłowa<br />
|}<br />
Bloki powinny wyglądać następująco:<br />
<br />
===Jak działają bloki?===<br />
Test if sprawdza, czy odpowiedź użytkownika (AnswerText.Text) jest taka sama, jak element na liście AnswerList o indeksie równym wartości zmiennej CurrentQuestionIndex. Jeżeli zmienna CurrentQuestionIndex ma wartość 1, aplikacja porównuje odpowiedź użytkownika z pierwszą pozycją na liście AnswerList, (Don Larsen). Jeżeli zmienna CurrentQuestionIndex zmieni wartość na 2, program zestawia odpowiedź z drugą pozycją na liście, czyli Dallas Branden. Jeśli wynik porównania jest pozytywny, przeprowadzane są bloki then, a treść etykiety RightWrongLabel zostaje ustawiona na Dobrze!. Jeżeli wynik testu jest negatywny (fałszywy), przeprowadzane są bloki alternatywy (else), a treść etykiety RightWrongLabel zostaje ustawiona na Źle.<br />
<br />
Przetestuj zmodyfikowaną aplikację. Spróbuj odpowiedzieć na jedno z pytań. Powinna pojawić się ocena, czy odpowiedź była dokładnie taka sama, jak na liście AnswerList. Sprawdź zarówno prawidłowe, jak i nieprawidłowe odpowiedzi (Uwaga - uwzględniana jest wielkość liter!). Kliknij przycisk NextButton i odpowiedz na drugie pytanie. Czy aplikacja nadal działa? Powinna, ale zauważ, że gdy klikniesz przycisk NextButton, tekst Dobrze! lub Źle oraz poprzednia odpowiedź nadal będą wyświetlane. Choć nie wpływa to zasadniczo na naszą grę, to takie szczegóły interfejsu z pewnością zostaną zauważone przez użytkowników Twojej aplikacji.<br />
<br />
Aby wyzerować etykietę RightWrongLabel i AnswerText, umieść poniższe bloki w bloku obsługi zdarzeń When NextButton.click:<br />
{| class="wikitable"<br />
!Typ bloku<br />
!Kategoria<br />
!Działanie<br />
|-<br />
|set RightWrongLabel.Text to<br />
|RightWrongLabel<br />
|Ustawia wartość etykiety na…<br />
|-<br />
|„ „<br />
|Text<br />
|pusty tekst<br />
|-<br />
|set AnswerText.Text to<br />
|AnswerText<br />
|Ustawia wartość etykiety na…<br />
|-<br />
|„ „<br />
|Text<br />
|pusty tekst<br />
|}<br />
Bloki powinny wyglądać następująco:<br />
<br />
===Jak działają bloki?===<br />
Po kliknięciu przycisku NextButton użytkownik przechodzi do następnego pytania, dlatego początkowe wiersze bloku obsługi zdarzeń zerują etykietę RightWrongLabel i pole AnswerText.<br />
Przetestuj to zachowanie Odpowiedz na pytanie i kliknij przycisk Wyślij, a następnie - NextButton. Czy Twoja poprzednia odpowiedź i jej ocena zniknęły?<br />
<br />
==Ostateczna postać programu==<br />
Oto gotowa aplikacja QuizMe:<br />
<br />
Utwórz wykonywalną wersję aplikacji, wybierając menu Build/App (provide QR code for .apk). Gdy pojawi się kod kreskowy, użyj czytnika kodów w telefonie, aby pobrać i zainstalować aplikację.<br />
<br />
===Modyfikacje===<br />
Quiz w tej wersji jest już gotowy. Czy masz ochotę przemyśleć pewne zmiany?<br />
<br />
Zamiast wyświetlać zdjęcie dla każdego pytania, spróbuj odtworzyć dźwięk lub krótkie wideo. Za pomocą dźwięku możesz zmienić quiz w aplikację Jaka to melodia?.<br />
<br />
Quiz akceptuje ściśle określone odpowiedzi. Jeśli gracz odpowiedziałby, lekko przekształcając tekst (np. podając inicjał zamiast imienia), program uzna to za błąd. Można to zmienić na kilka różnych sposobów. Jednym z nich jest użycie bloku text.contains, aby sprawdzić, czy odpowiedź użytkownika zawiera prawidłową odpowiedź. Inny sposób to dostarczenie wielu odpowiedzi na każde pytanie i sprawdzenie przez iterację (użycie bloku for each), czy któraś z nich pasuje.<br />
<br />
Przekształć quiz tak, aby przedstawiał odpowiedzi do wyboru. Lista odpowiedzi będzie musiała być listą list, a każda podrzędna lista będzie musiała zawierać opcje odpowiedzi. Użyj komponentu ListPicker, aby umożliwić użytkownikowi wybranie odpowiedzi.<br />
<br />
<br />
==Podsumowanie==<br />
Oto niektóre koncepcje omówione w tym przewodniku:<br />
<ul><li>Aplikacje można tworzyć w sposób ogólny, aby pracować z dowolną listą danych.</li><br />
<li>Zmienne indeksu są wykorzystywane do śledzenia bieżącej pozycji na liście. Zwiększając wartość zmiennej indeksu, należy uważać na przekroczenie końca listy.</li></ul><br />
<br />
==Zeskanuj próbną aplikację do telefonu==<br />
Aby zainstalować i uruchomić aplikację próbną, zeskanuj poniższy kod kreskowy:<br />
<br />
==Pobierz kod źródłowy==<br />
Jeżeli chcesz pracować z tą próbką w programie App Inventor:<br />
<ul><li>pobierz na komputer kod źródłowy: [http://appinventor.mit.edu/explore/sites/all/files/ai2tutorials/QuizMe/QuizMe_MIT.aia http://appinventor.mit.edu/explore/sites/all/files/ai2tutorials/QuizMe/QuizMe_MIT.aia]</li><br />
<li>otwórz program App Inventor,</li><br />
<li>kliknij opcję My Projects,</li><br />
<li>wybierz Import project (.aia) from my computer...</li><br />
<li>znajdź i zatwierdź pobrany kod źródłowy.</li></ul></div>M Kelniarzhttp://wiki.mistrzowiekodowania.pl/index.php?title=Plik:T6-18.pngPlik:T6-18.png2015-03-15T18:22:24Z<p>M Kelniarz: </p>
<hr />
<div></div>M Kelniarzhttp://wiki.mistrzowiekodowania.pl/index.php?title=Plik:T6-17.pngPlik:T6-17.png2015-03-15T18:22:13Z<p>M Kelniarz: </p>
<hr />
<div></div>M Kelniarzhttp://wiki.mistrzowiekodowania.pl/index.php?title=Plik:T6-16.pngPlik:T6-16.png2015-03-15T18:21:59Z<p>M Kelniarz: </p>
<hr />
<div></div>M Kelniarzhttp://wiki.mistrzowiekodowania.pl/index.php?title=Plik:T6-15.pngPlik:T6-15.png2015-03-15T18:21:44Z<p>M Kelniarz: </p>
<hr />
<div></div>M Kelniarzhttp://wiki.mistrzowiekodowania.pl/index.php?title=Plik:T6-14.pngPlik:T6-14.png2015-03-15T18:21:28Z<p>M Kelniarz: </p>
<hr />
<div></div>M Kelniarzhttp://wiki.mistrzowiekodowania.pl/index.php?title=Plik:T6-13.pngPlik:T6-13.png2015-03-15T18:21:11Z<p>M Kelniarz: </p>
<hr />
<div></div>M Kelniarzhttp://wiki.mistrzowiekodowania.pl/index.php?title=Plik:T6-12.pngPlik:T6-12.png2015-03-15T18:20:56Z<p>M Kelniarz: </p>
<hr />
<div></div>M Kelniarz