Arduino oyun konsolu. Sadə arduino televizor qutusu. Parametrlərin axtarışı funksiyaları



"Arifmetik assembler" şərti adı ilə oyun yaratmağa başlayaq. Oyunçu 128×90 ölçülü sahə ətrafında hərəkət etmək imkanı olan joystiklə idarə olunur. Sıfır joystik sapmalarında oyunçu mərkəzdədir. Joystikin maksimum əyilməsi oyunçunun maksimum hərəkətinə uyğundur. Müəyyən bir vaxt intervalı ilə yuxarıdan aşağıya doğru hərəkət edən rəqəmsal obyektlər yaradılır. Ekranın aşağı mövqeyinə çatdıqda, rəqəm obyekti yox olur və oyunçunun xalını bu rəqəmin dəyərinə qədər azaldır. Oyunçu ekranda rəqəmsal obyektin qarşısını alırsa, bu rəqəm obyektinin yox olmasına və oyunçunun xal sayğacının artmasına səbəb olur. Müəyyən bir tezliklə oyunçunun simvolu öz dəyərini 0 rəqəmindən 9-a dəyişir. Rəqəmli obyekti tutarkən, oyunçunun xal sayğacı rəqəm obyektinin və oyunçunun rəqəminin cəminə bərabər miqdarda artırılır, əgər oyunçunun rəqəmi rəqəm obyektinin rəqəminə bərabərdir, onda oyunçunun hesab sayğacı ədədlərin məhsulu ilə artır. Müəyyən xal hədlərinə çatdıqdan sonra oyunun daha yüksək səviyyəsinə keçid var ki, bu da hərəkət sürətinin və obyektlərin rəqəmlərini yaratma sürətinin artmasına səbəb olur. Bundan əlavə, oyunun 4-cü səviyyəsindən oyunçunun rəqəm obyekti ilə toqquşması təkcə oyunçunun sayğacının artmasına deyil, həm də azalmasına səbəb olur (əgər oyunçunun rəqəmi rəqəm obyektinin rəqəmindən azdırsa). Oyunçunun balı 0-dan aşağı düşərsə, oyun yenidən başlayır.

Baş verənlərin videosunu təqdim edirik

Eskiz və TVOut kitabxana faylları ilə arxivi linkdən yükləyə bilərsiniz

Və oyunun yaradılması prosesi

Oyun Dəyişənlərinin Yaradılması

Oyuna nəzarət etmək üçün oyunun cari vəziyyətini saxlamaq üçün obyektlər yaradaq. Oyunçunu təmsil edən simvol və rəqəmsal obyektləri təmsil edən simvollar mətn məlumatı kimi göstərilir, buna görə də biz bütün oyun sahəsini xətlərə ayıracağıq və bütün obyekt hərəkətləri bir xarakterin sahədəki tanışlığa çıxışı kimi həyata keçiriləcək. MAX_X=31 və MAX_Y=14 dəyişənləri oyun sahəsinin ölçüsünü üfüqi və şaquli tanışlıq boşluqlarının sayı ilə müəyyən edir. Dəyişən MAX_OBJ=30 eyni zamanda oyun sahəsindəki rəqəm obyektlərinin maksimum sayını müəyyən edir. int FIGURA massivi oyun sahəsində yerləşən obyekt-fiqurlar haqqında məlumatları aşağıdakı kimi saxlayır:

  • FIGURA[i] – rəqəm obyektinin rəqəmli qiyməti (0 – boş obyekt);
  • FIGURA[i] – rəqəm obyektinin cari x koordinatı;
  • FIGURA[i] – fiqur obyektinin cari y-koordinatı.

Təsvir edən digər dəyişənləri saxlamaq üçün Hazırki vəziyyət oyunlar, gəlin OYUN strukturunu yaradaq. Struktur sahələrinin siyahısı:

  • xk oyunçunun x(/4) koordinatıdır;
  • yk oyunçunun y(/6) koordinatıdır;
  • tekCursor - kursorun cari qiyməti;
  • blinkCursor - cari yanıb-sönən kursor vəziyyəti;
  • vblink - vk-də yanıb-sönmə sürəti;
  • vk – oyunçunun hərəkət sürəti – A0,A1 girişlərinin yoxlanılması;
  • vo_10 - oyunçu nömrəsinin dəyişmə sürəti;
  • vo_11 - obyektlərin-rəqəmlərin görünmə sürəti;
  • vo_12 - rəqəmsal obyektlərin hərəkət sürəti;
  • count_objects - sahədəki rəqəmli obyektlərin sayı;
  • səviyyə - oyun səviyyəsi;
  • toplar - xalların sayı.

int MAX_X=31; int MAX_Y=14; // oyun məlumat strukturu struct GAME // oyun məlumatları üçün struktur ( int xk; // x(/4) oyunçunun koordinatı int yk; // y(/6) oyunçunun koordinatı int tekCursor; // cari kursor dəyəri int blinkCursor; // kursorun cari vəziyyəti yanıb-sönmək int vblink; // vk long vk-də yanıb-sönmə sürəti; // oyunçunun hərəkət sürəti – A0, A1 long vo_10 girişlərinin yoxlanılması; // oyunçunun rəqəminin dəyişmə sürəti long vo_11; // rəqəmlərin görünmə sürəti long vo_12; // rəqəmlərin hərəkət sürəti int count_objects; // int səviyyəsindəki obyektlərin sayı; // oyun səviyyəsi int topları; // xalların sayı ); int MAX_OBJ=30; int FIGURA=((0,0,0),(0,0,0),(0,0,0),(0,0,0),(0,0,0), (0,0,0) ),(0,0,0),(0,0,0),(0,0,0),(0,0,0), (0,0,0),(0,0,0), (0,0,0),(0,0,0),(0,0,0), (0,0,0),(0,0,0),(0,0,0),(0) ,0,0),(0,0,0), (0,0,0),(0,0,0),(0,0,0),(0,0,0),(0,0) ,0), (0,0,0),(0,0,0),(0,0,0),(0,0,0),(0,0,0) );

Joystikdən istifadə edərək oyunçunun mövqeyinə nəzarət etmək.

Oyunçunun ekrandakı mövqeyi joystickin əyilməsi ilə müəyyən edilir. Joystik sancaqları Arduino lövhəsinin A0, A1 analoq portlarına qoşulur. Portlar GAME.vk parametri ilə müəyyən edilmiş vaxtdan sonra sorğulanır, bu məlumatlar cari diapazondan 0-124-dən yeni diapazona (ekran eni və hündürlüyü dəyərləri) proporsional olaraq dəyəri köçürən map() funksiyası tərəfindən işlənir. Sonra bu dəyər tanışlıq koordinatlarına çevrilir. Bu tanışlıqda boşluq xarakterini oyunçunun əvvəlki mövqeyinə qoyduqdan sonra oyunçunun personajının şəklini köçürmək lazımdır. Pleyeri göstərmək üçün yanıb-sönən simvol istifadə olunur - nömrə və boşluq.

//******************** yeni oyunçu mövqeyinin qurulması void set_iam() ( TV.set_cursor(min(123,GAME1.xk*4),min(84,GAME1) .yk*6)); , 96); GAME1.xk=GAME1.xk/4; GAME1.yk=GAME1.yk/6; GAME1.vblink–; if(GAME1.vblink)<0) { GAME1.blinkCursor=1-GAME1.blinkCursor; GAME1.vblink=5+GAME1.blinkCursor*5; } TV.set_cursor(min(123,GAME1.xk*4),min(84,GAME1.yk*6)); if(GAME1.blinkCursor==1) TV.print(GAME1.tekCursor); else TV.print(” “); }

Oyunçunu təmsil edən simvol GAME.vo_10 parametri ilə müəyyən edilmiş vaxtdan sonra set_new_cursor() funksiyasını çağırmaqla dəyişir, dəyişiklik random() funksiyasından istifadə edərək təsadüfi baş verir.

//******************** yeni növ oyunçu simvolunun qurulması void set_new_cursor() ( GAME1.tekCursor=random(0,10); )

Rəqəmsal obyektlərin yaradılması və hərəkəti.

Rəqəm obyektləri GAME.vo11 parametri ilə müəyyən edilmiş vaxtdan sonra yaradılır. set_new_object() funksiyası çağırılır. Bütün rəqəmli obyektlər haqqında məlumat FIGURA massivində saxlanılır. Proqram massivdə ilk boş indeksi axtarır (FIGURA=0) və ona yeni rəqəm obyekti qoyur. Yeni obyektin ədədi dəyəri və üfüqi koordinatı təsadüfi funksiya tərəfindən yaradılır və şaquli koordinat sıfıra təyin olunur. Yeni rəqəm obyektini təmsil edən simvol göstərilir.

//******************** yeni nömrə obyekti etibarsız görünür set_new_object() ( int null_index=0; if(GAME1.count_objects)<>( for(int i=0;i;i++)<>( if(FIGURA[i]==0) (null_index=i;break;) ) FIGURA=təsadüfi(1,9); FIGURA=təsadüfi(0,MAX_X); ŞƏKİL=0; // lövhəyə çıxış TV.set_cursor(FIGURA*4,0); TV.print(FIGURA); GAME1.count_objects++; ) )

Rəqəmsal obyektlərin hərəkət funksiyası (go_object()) GAME.vo12 parametri ilə müəyyən edilmiş vaxtdan sonra çağırılır. Rəqəmli obyektlərin hərəkətinin vizuallaşdırılması simvolun obyektin əvvəlki mövqeyindən silinməsi (boşluq simvolunun qeyd edilməsi) və obyekt simvolunun yeni mövqeyə yazılması (rəqəm obyektinin tanışlığının şaquli koordinatı bir artır) ilə baş verir. ). Ekranın aşağı hissəsinə çatdıqda, nömrə obyekti silinir (FIGURA[i] massiv elementinə 0 yazılır), həmçinin oyunçunun balı azalır.

//******************** rəqəm obyektinin hərəkəti void go_object() ( for(int i=0;i;i++)<>( if(FIGURA[i]>0) ( TV.set_kursor(FIGURA[i]*4,FIGURA[i]*6); TV.print(" "); if(FIGURA[i])<>( FIGURA[i]++; TV.set_kursor(FIGURA[i]*4,FIGURA[i]*6); TV.print(FIGURA[i]); ) başqa ( TV.tone(294,200); topları dəyişdirin(FIGURA) [i]*(-1)); FIGURA[i]=0; GAME1.objects_count-; ) ) ) )

Oyunçu və rəqəm obyektləri arasında toqquşma olub olmadığını yoxlayın.

Oyunçu simvolunu ekranda hərəkət etdirərkən, oyunçunun rəqəm obyektləri ilə toqquşmasını yoxlamaq lazımdır. Bunun üçün collision() funksiyasından istifadə edirik. Oyunçuya uyğun simvolu təyin etdikdən sonra FIGURA massivinin elementlərini rəqəm obyektlərinin koordinatlarının oyunçu simvolunun koordinatlarına uyğunluğunu yoxlayırıq. Koordinatlar uyğun gələrsə, aşağıdakıları edin:

  • FIGURA massivindən rəqəm obyekti məhv edilir (FIGURA[[i]-də qeyd 0);
  • rəqəmli obyektlərin sayının 1 sayğacı azalır (GAME.count_objects)
  • oyunçunun hesab sayğacı dəyişdirilir (change_balls() funksiyası çağırılır).

//******************** toqquşma yoxlayın, etibarsız toqquşma() ( for(int i=0;i;i++)<>( if(FIGURA[i]>0) ( if(FIGURA[i]==GAME1.xk && FIGURA[i]==GAME1.yk) ( TV.tone(740,200); if(FIGURA[i]==GAME1 .tekCursor) topları dəyişdirin(GAME1.tekCursor*GAME1.tekCursor); başqa halda (FIGURA[i]>GAME1.tekCursor && GAME1.level>3) topları dəyişdirin(FIGURA[i]*(-1)); başqa topları dəyişdirin(FIGURA[ i]+GAME1.tekKursor); FIGURA[i]=0; GAME1.count_objects–; ) ) ) )

Oyunçunun xal sayğacını dəyişdirmək funksiyası (change_balls()) arqument kimi oyunçunun xal sayğacının artırılması (azaldılması) lazım olan nömrəni alır. Bu rəqəm rəqəm obyektinin və oyunçunun rəqəminin cəminə bərabərdir. Əgər oyunçunun rəqəmi rəqəm obyektinin rəqəminə bərabərdirsə, rəqəmlərin hasilinə bərabər qiymət verilir. Oyunun çətinliyini 4-cü səviyyədən artırmaq üçün oyunçunun rəqəmsal obyektlə toqquşması təkcə oyunçunun sayğacının artmasına deyil, həm də azalmasına səbəb olur (əgər oyunçunun rəqəmi rəqəm obyektinin rəqəmindən azdırsa). ).

Oyunçu hesab sayğacı.

Change_balls() funksiyası oyunçunun hesab sayğacını giriş arqumentinin dəyəri ilə dəyişir. Hesab sayğacı 0-dan aşağı düşərsə, oyun başa çatır, ekran təmizlənir və oyun başlanır. Bundan əlavə, sayğac müəyyən dəyərlərə çatdıqda, oyun yeni, daha yüksək səviyyəyə keçir. Yeni səviyyə üçün dəyərlərin qurulması new_level() funksiyası tərəfindən həyata keçirilir.

//******************** xalların dəyişdirilməsi ləğv edildi dəyişdirmə_topları(int top) ( GAME1.toplar=GAME1.toplar+top; əgər(GAME1.toplar)<0) start_game(); if(GAME1.balls>(GAME1.level+1)*100) new_level(GAME1.level); set_data_table(); )

Yeni səviyyəyə keçmək.

Oyunun yeni səviyyəsinə keçərkən, generasiya sürəti və hərəkət edən obyektlərin-rəqəmlərin sürəti üçün yeni dəyərlər təyin olunur. Əvvəlcə oyunçunun nömrəsinin dəyişmə sürətinin dəyərini, oyunçunun hərəkət sürətini dəyişdirməli idi, lakin oyunun testi zamanı bundan imtina etmək qərarına gəldim. Yeni oyun səviyyəsi üçün dəyişən dəyərlərin təyin edilməsi hərəkətləri new_level() funksiyasında yerinə yetirilir

//******************** oyun səviyyəsini dəyişdirin yeni_səviyyə (int tek_level) ( GAME1.level++; GAME1.vo_10=5000; GAME1.vo_11=2000-(GAME1) .səviyyə -1)*100; GAME1.vo_12=1000-(GAME1.level-1)*100; )

Oyun məlumatlarını tabloda göstərin.

Oyunçu məlumatı olan tablo ekranın aşağı hissəsində yerləşir. O, toplanmış xalların sayının və oyunun səviyyəsinin cari dəyərlərini göstərir. Oyunçunun hesab sayğacı dəyişdikdə, GAME strukturu dəyişənlərində və tabloda toplanan xalların sayının və oyun səviyyəsinin dəyərini dəyişən set_data_tablo() funksiyası çağırılır.

//******************** göstəricilər tablosunda göstərilir void set_data_tablo() ( TV.print(20,91,” toplar= “); TV.print( 70,91 ," level= "); TV.print(48,91,GAME1.tops); TV.print(98,91,GAME1.level); )

Oyun soundtrack.

Oyunun səs dizaynı üçün TVOut kitabxanasının ton (tezlik, müddət) funksiyasından istifadə edəcəyik. Nömrə obyekti oyun sahəsinin altına çatdıqda - TV.tone(294,200) (go_object() funksiyası), pleyer və rəqəm obyekti toqquşduqda - TV.tone(740,200) (collision() funksiyası). Layihəyə bir neçə notun ardıcıl oxunmasından fraqment daxil etmək istəyirsinizsə, hər notun ton(tezlik, müddət) əmri ilə çıxışından sonra, gecikmə() əmri ilə heç bir müddəti olan gecikmə daxil etməlisiniz. müddət parametrindən azdır,6 - ikisinin ardıcıl oxunması, lakin fasilə ilə.

TV tonu (294,200); TV.gecikmə(400); TV tonu (740,200);

Oyunun əsas döngəsi.

Proqramın əsas dövrəsi GAME.vk, GAME.vo_10, GAME-də müəyyən edilmiş vaxt intervalından sonra nəzərdən keçirdiyimiz set_iam(), collision(), go_object(), set_new_object(), set_new_cursor() funksiyalarını çağırmaqdan ibarətdir. .vo_11, GAME.vo_12 dəyişənləri.

int game1() ( while(GAME1.balls>0 && GAME1.level<6) { long time2=millis(); if(time2-time11>GAME1.vk) (set_iam(); toqquşma(); time11=time2; ) if(time2-time12>GAME1.vo_12) (go_object();time12=time2;) if(time2-time13>GAME1.vo_11) (set_new_object) ();zaman13=zaman2;) if(zaman2-zaman14>OYUN1.vo_10) (yeni_kursor();zaman14=zaman2;) TV.gecikme_frame(10); ) if(GAME1.toplar<0) return 0; else if(GAME1.level>5) 0 qaytarın; başqa 1 qaytarın; )

Oyun seçmək üçün menyu əlavə edilir.

Özünüzü əlavə edə biləcəyiniz üç oyunu göstərmək üçün eskizə menyu əlavə edək.

void loop() ( switch(menu(pmenu)) ( case 1:start_game(); while(game1()>0); break; default: break; ) ) //***** oyun seçimi üçün menyu int menyu (int poz) ( TV.clear_screen(); pmenu=max(poz,1); int pmenu1=pmenu; TV.println(60,30,"Oyun 1"); TV.println(60,50,"Oyun 2 ″); TV.println(60,70,”Oyun 3″); TV.draw_rect(50,5+20*pmenu,40,10,AĞ,İNVERT); TV.delay(500); while(digitalRead(12 )= =LOW) ( if(analogRead(A1))<100) pmenu=max(pmenu-1,1); else if(analogRead(A1)>900) pmenu=min(pmenu+1.3); başqa; if(pmenu1!=pmenu) ( TV.delay(500); TV.draw_rect(50.5+20*pmenu1,40,10,QARA,INVERT); TV.draw_rect(50.5+20*pmenu,40, 10,AĞ, INVERT); pmenu1=pmenu; ) ) pmenu qaytarmaq; )

Tərcüməçidən bir söz: bir dəfə, ölkə və ağaclar böyük olanda və mənim təxəyyülüm sadəcə sərhədsiz olanda, bir xəyalım var idi - proqramlaşdırıla bilən mikrokalkulyator Electronics MK-61 (yaxşı, hər cür qrafika, əyri, şəkillər var) bir şəkil göstərmək imkanı ) televizor ekranında. Dövrlər sovet vaxtı vəhşi idi, nəinki Oyun konsolu və çox şəxsi MİKROkompüter (“Pravets 8D” və ya “Mütəxəssis” və ya “Sikkler”), lakin videoregistratorlar da maraq doğururdu. Ümumiyyətlə, camaat tamaşa tələb edirdi və “Yerə gedən yol” (“Texnologiya – Gənclik” jurnalı) ümumi adı altında proqramlaşdırıla bilən kalkulyatorlar üçün maarifləndirici və əyləncəli nəşrlərin dövrəsini xatırlayanlar məni başa düşəcəklər.

Bir sözlə, yaxşı süjetli fantastika romanı formasında iki axmaq təsadüfi tanışın - peşəkar astronavt və böyük kibernetçinin Aydan Yerə səyahəti təsvir edilmişdir. Bütün süjetin ayrıca kəskinliyini onların sözdə səyahət etmələri verdi. "Lunolete", yəni kimyəvi mühərrikli kiçik kosmik gəmi, aylar və digər göy cisimləri üzərində görmə şəraitində hərəkət etmək üçün nəzərdə tutulmuşdur. bilyard topu kimi sadə relyef ilə. Dövrün hər sayında həm yaxınlıqdakı bir göy cisminin güclü (nisbətən) cazibə qüvvəsi şəraitində, həm də Yerin və Ayın cazibə qüvvələrinin qəhrəmanlarının təsir etdiyi zaman hər bir manevrin sadələşdirilmiş həqiqəti, lakin kifayət qədər ağlabatan riyazi təsviri var idi. göy mərmisi, eləcə də uçuşun növbəti mərhələsinin hesablanması proqramı. Ümumiyyətlə, kalkulyatorun ekranında rəqəmlərə baxmaq tam olaraq kifayət deyil, amma ekranda gözəl əyrilər istədim (MCC-də olduğu kimi).

Digər tərəfdən, unutmayaq ki, hətta Arduino ailəsinin ibtidai mikrokontrollerləri də performans baxımından nəinki o vaxtkı flaqmanların - MK-52 və MK-61-in mikroprosessorlarından, həm də bəzilərinin hesablama imkanlarından da üstündür. Son dövrlərin 8 bitlik oyun konsolları (Atary 2600 və digər Rambo Bəli ser).

Ümumiyyətlə, giriş bir az uzun oldu, ona görə də bugünkü dərsimizin mövzusuna - Arduino-dan televizor ekranına video təsvirin çıxarılmasına keçək.

Təəssüf ki, Arduino-nun dizayn xüsusiyyətləri sizə yalnız monoxrom (qara və ağ) şəkillər çıxarmağa imkan verir, baxmayaraq ki, bu bəzi layihələrdə faydalı ola bilər və CSF noobları o qədər dəqiq qaldıracaq ...

Birinci addım. Hissələr və Proqram təminatı

Sizə lazım olacaq:

Parçalar və birləşmələr:

  1. Arduino mikro nəzarətçi
  2. TV (onsuz, mütləq heç bir yerdə)
  3. Arduino üçün inkişaf lövhəsi və ya qalxan
  4. Nominal dəyəri 470 ohm və 1 kΩ olan 2 rezistor
  5. 2 2 pinli kişidən kişiyə montaj adapterləri
  6. Qalxanlı tv kabeli sonunda bir lalə ilə

Proqram təminatı:

  1. Arduino inkişafı/firmware mühiti. Rəsmi Link

İkinci addım. Məclis

Hazır TV-adapterin təsvirinin keyfiyyətsizliyinə görə müəllifin adından üzr istəyirəm. Bu, təlimatları yazarkən əvvəlcə onları yazmalı və sonra bütün mərhələlərin diqqətli foto çəkilişi ilə montaja davam etməlisiniz. Bizim vəziyyətimizdə hər şey tam əksinə oldu, buna görə də bitmiş adapterin buludlu görüntüsündən heç nə başa düşmək sadəcə mümkün deyil.

Daha yaxşı, nəyi harada və necə lehimləmək lazım olduğunu izah edir dövrə diaqramı, yalnız bir neçə hissədən ibarət olmaqla yanaşı.


Pinout:

Sinxronizasiya - mikrokontrolörün rəqəmsal pin 9

Video - mikrokontrolörün rəqəmsal pin 8

GND - mikrokontrolörün GND pin

Üçüncü addım. Proqramlaşdırma

Ən əyləncəli hissəsi proqramlaşdırmadır.

Əsasən artıq çıxıb. yeni versiya Televiziya kitabxanaları, lakin müəllif tərəfindən istifadə edilən R5.91-dən daha çox səhv və qeyri-sabitdir, ona görə də yuxarıdakı linkdən kitabxananı yükləmək daha yaxşıdır.

Ekranın surətindən kodu yenidən yazmağa çox tənbəl olan tənbəllər üçün proqramın mətni:

#daxildir TV çıxışı; işarəsiz simvol x, y; etibarsız quraşdırma () ( TV.start_render(_NTSC); ) boş dövrə () ( TV.clear_screen (); TV.print_str(10, 10, "TVout FTW!!!"); TV.delay(60); )

Güman edilir ki, fəaliyyətin əsas prinsipləri və Arduino proqramlaşdırma- belə mikrokontrollerləri bilirsiniz, buna görə müəllif fikirlərini ağac boyunca yaymamaq qərarına gəldi, aşağıdakı kitabxana əmrləri ilə tanış olmağı tövsiyə etdi:

  • start(rejim) Ekranda məlumatı göstərməyə başlayın. Standart təsvir ölçüsü - 128x96
  • start(rejim,x,y) Ekranda məlumatı göstərməyə başlayın. İstifadəçi arqumentləri ilə müəyyən edilən icazə x,y
  • end() Video buferini təmizləyin
  • force_vscale(sfactor) Hər sətri göstərmək üçün dəfələrin sayını məcbur edin.
  • force_outstart(zaman) Aktiv xətt üzrə çıxışa başlamaq üçün vaxtı məcbur edin.
  • force_linestart(line) Çıxışa başlamaq üçün xətti məcbur edin.
  • set_vbi_hook(func) Şaquli boşluq dövründə bir dəfə çağırılacaq funksiyanı təyin edin.
  • set_hbi_hook(func) Hər üfüqi boşluq dövründə bir dəfə çağırılacaq funksiyanı təyin edin.
  • hres() Komanda üfüqi təsvirin dəyərini qaytarır,
  • vres() Komanda şaquli qətnamənin dəyərini qaytarır,
  • char_line() Əmr sətirdə yerləşəcək simvolların sayının dəyərini qaytarır.
  • set_pixel(x,y,color) Verilmiş koordinatlarda pikselin rəngini təyin edir
  • get_pixel(x,y) Verilmiş koordinatlardakı pikseli istinad nöqtəsi kimi təyin edir.
  • fill(color) Ekranı verilmiş rənglə doldurur.
  • clear_screen() Ekranın təmizlənməsi.
  • invert() Ekrandakı şəkli tərsinə çevirin.
  • shift(məsafə,istiqamət) Ekranı verilmiş məsafədə 6 istiqamətdən hər hansı birində sürüşdürür.
  • draw_line(x0,y0,x1,y1,color) Koordinatlardan (x0,y0) koordinatlara (x1,y1) xətt çəkin.
  • draw_row(sətir,x0,x1,color) x0-dan x1-ə qədər olan cərgəni verilmiş rənglə doldurun.
  • draw_column(column,y0,y1,color) y0-dan y1-ə qədər koordinatları olan sütunu verilmiş rənglə doldurun.
  • draw_rect(x,y,w,h,color,fillcolor) Mənşəyi (x,y) koordinatlarında (h,w) olan düzbucaqlı çəkin və verilmiş rənglə doldurun.
  • draw_rect(x,y,w,h,color) Mənşəyi (x,y) və ölçüləri(h,w) olan düzbucaqlı çəkin.
  • draw_circle(x,y,radius,color,fillcolor) Mərkəzində (x,y) radiuslu (RADIUS) dairə çəkin və onu göstərilən rənglə doldurun
  • draw_circle(x,y,radius,color) Mərkəzində (x,y) radiusu (RADIUS) olan dairə çəkin.
  • bitmap(x,y,bmp,i,en,hündürlük) Verilmiş şəkli koordinatlarda göstərin..
  • print_char(x,y,c) Koordinatlarda (x,y) simvolu çap edin.
  • set_cursor(x,y) Növbəti simvolu göstərmək üçün mövqeyi təyin edin.
  • select_font(font) Mətni göstərmək üçün şrifti təyin edir.
  • print() Mətni çıxarın.
  • println() Sadə sətir çap edin.
  • printPGM() Proqram yaddaşından mətn sətirini çap edin.
  • ton(tezlik) Verilmiş tezliyə malik ton.
  • ton(tezlik,müddət) Müəyyən olunmuş tezlik və müddətin tonu.
  • noTone() Ton çıxışını dayandırın.

Dördüncü addım. Tamamlama

Gün işığında və sonra yuxuda öz tənzimlənən pristavkamı yaratmaq fikrim var idi. Əslində, o zaman mənim qarşımda radiotexnikanın zəngin və zəngin dünyası açıldı. Əvvəllər ciddi elektronikanın inkişafı ilə məşğul olmadığım üçün seçimim daha sadə varianta düşdü - Arduino və onun ən çox yayılmış modelidir Uno.

İş planı

1. Kitabxana ilə məşğul olun
2. Lehimli video çıxış lövhəsi
3. Kodu yazın
4. Bədəni kəsin

Bu cür layihələrdə son xarici komponent xüsusi əhəmiyyət kəsb etmir.

Addım 1. Nəyin nə olduğunu başa düşmək

Bir neçə on dəqiqəlik ümidsiz axtarışdan sonra belə qənaətə gəldim ki, hətta Dendy kimi prefiks yarada bilməyəcəm. Yaxşı, nə edim, bir dəfə başladım, məsələni sona çatdıracağam.

Arduino və ümumiyyətlə radio elektronika ilə bağlı layihələrə həsr olunmuş saytda (reklam deyil) oxşar bir iş haqqında məqalə tapdım. Kitabxanadan istifadə etmək qərara alınıb TV çıxışı, çünki prefiks tv-shnayadır. Onu işə salmaq üçün bir az zəhmət çəkdi.

Tələb olunan kitabxana funksiyaları

Rejimin təyini funksiyaları

Funksiya başlamaq() video çıxışını işə salır (defolt ekran qətnaməsi 128x96-dır).
Sintaksis:
TVOut.begin(rejim);
TVOut.begin (rejim, x, y);

Seçimlər:
rejim - video siqnal standartı:
_PAL - PAL rejimi;
_NTSC - NTSC rejimi.
Qaytarılan dəyər:
0 - uğurlu qoşulma halında, 4 - uğursuzluq halında (çıxış buferi üçün kifayət qədər yaddaş yoxdur).

Gecikmə funksiyaları

Funksiya gecikmə() göstərilən təsviri gecikdirir.
Sintaksis:

TVOut.delay(ms);
Seçimlər:

ms - dəqiqliklə ms ilə gecikmə: PAL üçün 20 ms və NTSC üçün 16 ms.

delay_frame() funksiyası göstərilən təsviri gecikdirir.
Sintaksis:

TVOut.delay_frame(çərçivələr);
Seçimlər:

çərçivələr - gecikdiriləcək kadrların sayı...
Bu funksiya ekranın yenilənməsi nəticəsində yaranan ekran titrəməsini minimuma endirmək və ya aradan qaldırmaq üçün faydalıdır.

Parametrlərin axtarışı funksiyaları

Funksiya hres()üfüqi ekran qətnaməsini qaytarır.
Sintaksis:

TVOut.hres();
Seçimlər:

Yox.
Qaytarılan dəyər:

imzasız char - üfüqi ekran həlli.

vres() funksiyası ekranın şaquli təsvir ölçüsünü qaytarır.
Sintaksis:

TVOut.vres();
Seçimlər:

Yox.
Qaytarılan dəyər:

imzasız char - şaquli ekran həlli.

Funksiya char_line()çıxış zamanı bir sətirdə mümkün olan maksimum simvol sayını qaytarır mətn məlumatı.
Sintaksis:

TV çıxışı. char_line();
Seçimlər:

Yox.
Qaytarılan dəyər:

işarəsiz simvol - simvolların sayı.

Əsas qrafik xüsusiyyətləri

Funksiya set_pixel() verilən koordinatlarla nöqtədə ekran pikselinin rəngini təyin edir.
Sintaksis:

TVOut.set_pixel(x,y,rəng);
Seçimlər:

x,y – piksel koordinatları;
rəng - piksel rəngi:
0 - qara;
1 - ağ;
2 - ters rəng.
Funksiya get_pixel() verilmiş koordinatları olan nöqtədən ekran pikselinin rəngini alır.
Sintaksis:

TVOut.get_pixel(x,y);
Seçimlər:

x,y - piksel koordinatları.
Qaytarılan dəyər:

rəng - piksel rəngi:
0 - qara;
1 - ağ;
2 - ters rəng.
fill() funksiyası ekranı verilmiş rənglə doldurur.
Sintaksis:

TVOut doldurma (rəng);
Seçimlər:

rəng - doldurma rəngi:
0 - qara;
1 - ağ;
2 - ters rəng.
Funksiya aydın_ekran() ekranı göstərilən rənglə dolduraraq təmizləyir.
Sintaksis:

TVOut.clear_screen(rəngli);
Seçimlər:

rəng - doldurma rəngi:
0 - qara;
1 - ağ;
2 - ters rəng.

Funksiya invert() ekranın məzmununu çevirir.
Sintaksis:

TVOut.invert();
Seçimlər:

Yox.
shift_direction() funksiyası ekranın məzmununu dəyişir.
Sintaksis:

TVOut.shift_direction(məsafə, istiqamət);
Seçimlər:

məsafə - ekran məzmununu dəyişdirmək üçün məsafə.
istiqamət - sürüşmə istiqaməti:
UP=0 – yuxarı;
AŞAĞI=1 – aşağı;
LEFT=2 - sola;
RIGHT=3 - sağa.

Funksiya çəkmək_xətti() ekranda iki nöqtəni xətt ilə birləşdirir.
Sintaksis:

TVOut.draw_line(x0,y0,x1,y1,color);
Seçimlər:

x0,y0 birinci nöqtənin koordinatlarıdır;
x1,y1 – ikinci nöqtənin koordinatları;
rəng - doldurma rəngi:
0 - qara;
1 - ağ;
2 - ters rəng.
Funksiya çəkmək_sətir() sətirin iki nöqtəsi arasında sətri müəyyən edilmiş rənglə doldurur.
Sintaksis:

TVOut.draw_row(sətir,x0,x1,rəng);
Seçimlər:

sıra – cərgənin şaquli koordinatı;
x1,x2 – xətt nöqtələrinin üfüqi koordinatları;
rəng - doldurma rəngi:
0 - qara;
1 - ağ;
2 - ters rəng.
draw_column() funksiyası sütunun iki nöqtəsi arasında göstərilən rənglə sətri doldurur.
Sintaksis:

TVOut.draw_column(sütun,y0,y1,rəng);
Seçimlər:

sütun – sütunun üfüqi koordinatı;
y1,y2 – sütun nöqtələrinin şaquli koordinatları;
rəng - doldurma rəngi:
0 - qara;
1 - ağ;
2 - ters rəng.
Funksiya draw_rect() ekranda düzbucaqlı çəkir.
Sintaksis:

TVOut.draw_rect(x,y,w,h,rəng);
TVOut.draw_rect(x,y,w,h,rəng,fillcolor);

Seçimlər:

x,y – yuxarı sol nöqtənin koordinatları;
w,h – çəkilmiş düzbucaqlının eni və hündürlüyü;
rəng - düzbucaqlının sərhədlərinin rəngi:
0 - qara;
1 - ağ;
2 - ters rəng.
fillcolor - düzbucaqlının rəngini doldurun:
0 - qara;
1 - ağ;
2 - ters rəng.
Funksiya çəkmək_dairə() ekranda dairə çəkir.
Sintaksis:

TVOut.draw_circle(x,y,r,rəng);
TVOut.draw_circle(x,y,r,rəng,fillcolor);

Seçimlər:

x,y – çevrənin mərkəzinin koordinatları;
r - dairənin radiusu;
rəng - dairənin sərhədlərinin rəngi:
0 - qara;
1 - ağ;
2 - ters rəng.
fillcolor - dairənin rəngini doldurun:
0 - qara;
1 - ağ;
2 - ters rəng.
Funksiya bitmap() bitmap göstərir.
Sintaksis:

TVOut.bitmap(x,y,bmp,w,h);
Seçimlər:

x,y – çıxış nöqtəsinin yuxarı sol küncünün koordinatları;
bmp təsvirin saxlandığı yaddaş massivinin göstəricisidir;
w,h - göstərilən təsvirin eni, hündürlüyü;
Aşağıda çıxış bitmapları üçün kodun yaradılması prosesini nəzərdən keçirəcəyik.

Mətn məlumatlarını göstərmək üçün funksiyalar

Mətn məlumatının çıxış funksiyalarından istifadə etmək üçün kitabxanaya daxil edilmiş faylları və ya xüsusi şriftləri birləşdirməlisiniz. Fərdi şrift dəstini birləşdirmək üçün eskizə bir başlıq faylı daxil etməlisiniz:
#daxildir
Kitabxanaya aşağıdakı şrift dəstləri daxildir:

font4x6;
font6x8;
font8x8;
font8x8ext.
Funksiya seçmək_şrift() mətn məlumatını göstərmək üçün şrifti seçir.
Sintaksis:

TVOut.select_font(şrift);
Seçimlər:

şrift eskizə daxil edilmiş şriftdir.

print_char() funksiyası simvolu ekrana çap edir.
Sintaksis:

TVOut.print_char(x,y,char);
Seçimlər:

x,y - simvolu göstərmək üçün ekranda mövqe;
char cari şriftdən simvoldur.

Funksiya set_kursor() mətn məlumatını ekranda göstərmək üçün kursor mövqeyini təyin edir.
Sintaksis:

TVOut.set_kursor(x,y);
Seçimlər:

x,y - kursor üçün koordinatlar.
Funksiya çap () sətir, simvol və ya nömrəni ekrana çap edir.
Sintaksis:

TVOut.print(x,y,string);
TVOut.print(x,y,char,base);
TVOut.print(x,y,int,base).

Seçimlər:

x,y - kursor koordinatları.
əsas çıxış formatı:
BYTE=0;
DEC = 10 (standart);
HEX = 16.

Funksiya println() sətir, simvol və ya nömrə, ardınca yeni sətir simvolu göstərir:
Sintaksis:

TVOut.println(x,y,string);
TVOut.println(x,y,char,base);
TVOut.println(x,y,int,base).

Seçimlər:

x,y - kursor koordinatları.
əsas çıxış formatı:
BYTE=0;
DEC = 10 (standart);
HEX = 16.

Audio çıxış funksiyaları

Audio çıxış funksiyaları audio çıxış vasitəsilə televizora xüsusi tezlik siqnalı göndərməyə imkan verir.
Funksiya ton() müəyyən tezlikli səs siqnalını çıxarır.
Sintaksis:

TVOut.tone(tezlik,müddət);
TVOut.tone(tezlik).

Seçimlər:

tezlik – səs siqnalının tezliyi;
müddət – siqnal müddəti.
Funksiya noTone() audio çıxışı dayandırır.
Sintaksis:

TVOut.noTone().

Addım 2. Video çıxışının lehimlənməsi

Əvvəla, kompozit av-out (RCA) vasitəsilə video siqnalı çıxarmaq üçün lövhəni lehimləməliyik. Aşağıdakı sxemə görə lehimləyirik:


Nominal dəyəri 470 ohm və 1k ohm olan iki rezistoru bir-birinə paralel yerləşdiririk və onlara lalə kabelindən "artı" lehimləyirik. Sonra, teli 470 ohm rezistordan Arduino-nun yeddinci pininə aparacağıq, çünki o video çıxışına cavabdehdir ( video) və 1k ohm rezistordan teli doqquzuncu pinə aparacağıq, çünki sinxronizasiyadan məsuldur ( sinxronizasiya). Və lalə kabelindən Arduino-da "yerə" qədər "mənfi". Daha çox oxu ( İngilis dili)

Addım 3. Kodu yazırıq (oyun)

Mən nəyi və necə bağlanacağımı izah etməyəcəyəm, çünki lazımi məlumatları həmişə olduğu kimi İnternetdə tapmaq olar. Mən tapmaq çox çətin olan və ya ümumiyyətlə mövcud olmayan bir şeyi təsvir edirəm.

ilə başlayaraq salamlama ekranı, onsuz harada. Ancaq burada vacib bir sual müdaxilə edir, bu möcüzəni necə adlandırmaq olar? Mən beyin fırtınası etdim və fikirləşdim - Şimo. Çin dilində, əlbəttə ki, yaxşı, hətta texnoloji səslənir, amma fərqi yoxdur.

Başlayın. ilə ekranın ortasından xətt çəkin TV.draw_line(60,0,60,96,1);. Ekranın tam ortasında bir top görünür. Onun hərəkət funksiyasını yazaq boş top hərəkəti (int vel, daxili bucaq). istifadə edərək quraşdırın TV.set_pixel(x,y,1);, mən dəyişənləri adlandırdım.

Sonra, topu manipulyasiya etməzdən əvvəl, ekran yeniləməsini, daha doğrusu, topun ekranda "miras almaması" üçün təyin edirik, buna görə də növbəti mövqeyə keçərkən əvvəlkini qara rənglə boyamalısınız. Bunun üçün hər şeydən əvvəl resept yazmalıyıq TV.set_pixel(x,y,0);. Dəyişən koordinatlardakı bütün dəyişikliklərdən sonra mövqe qəbulunu və kiçik bir gecikməni qeyd etməlisiniz - TV.gecikmə(50);. Təxminən belə çıxmalıdır:

Boş top hərəkəti (int vel, daxili bucaq) ( TV.set_pixel(x,y,0); //Koordinat manipulyasiyası TV.set_pixel(x,y,1); )

İndi koordinat dəyişiklikləri haqqında. Cəmi səkkiz istiqamət (1-8), dəyişən int bucağı. Və burada artıq sadədir, fırlanmadan asılı olaraq dəyişənlərə hər hansı bir hissəsini çıxarırıq və ya əlavə edirik. int sürəti. Mən belə etdim:

If(bucaq == 1) ( y -= vel; ) if(bucaq == 3) ( x += vel; ) if(bucaq == 5) ( y += vel; ) if(bucaq == 7) ( x -= vel; ) if(bucaq == 2) ( x += dəyirmi(və/2); y -= dəyirmi(və/2); ) if(bucaq == 4) ( x += dəyirmi(və/ 2); y += dəyirmi(və/2); ) if(bucaq == 6) ( x -= dəyirmi(və/2); y += dəyirmi(və/2); ) if(bucaq == 8) ( x -= dəyirmi(vel/2); y -= dəyirmi(vel/2); )

İndi raketlərin hərəkətləri. Burada vacib bir aydınlıq var - mən yalnız boyunca koordinatlardan istifadə etdim y, çünki raketlərin mövqeləri x dəyişməyin. Aşağıdakı funksiyanı yazın void racketsmove(). Sonra, raketləri, dəyişənləri çəkin int yb1, int yb2, TV.draw_line(10, yb1+8, 10, yb1-8, 1);TV.draw_line(110, yb2+8, 110, yb2-8, 1);. Ekranın yenilənməsi, yəni "izsiz" topla işə bənzəyir.

Raketlər düymələrlə idarə olunur. Düymələri, sancaqları bağlayırıq 2 3 - birinci raketka 4 5 - ikinci raket. Düymələrin basılmasını yoxlayırıq və koordinatları dəyişirik.

Budur belə bir funksiya:

Void racketsmove() ( TV.draw_line(10, yb1+8, 10, yb1-8, 0); TV.draw_line(110, yb2+8, 110, yb2-8, 0); if((yb1 - 8) > 1) ( if(digitalRead(2) == YÜKSƏK) ( yb1 -= 2;) ) if((yb1 + 8)< 95) { if(digitalRead(3) == HIGH) {yb1 += 2;} } if((yb2 - 8) >1) ( if(digitalRead(4) == YÜKSƏK) (yb2 -= 2; ) ) if((yb2 + 8)< 95) { if(digitalRead(5) == HIGH) {yb2 += 2;} } TV.draw_line(10, yb1+8, 10, yb1-8, 1); TV.draw_line(110, yb2+8, 110, yb2-8, 1); }

İndi isə qayıdaq top. İndi gəlin onun divarlardan və raketlərdən toqquşmasını və itməsini yazaq. Funksiya - voidballcol(). Bunun üçün sadəcə olaraq onun obyektlərə nisbətən yerini, sonra isə bucağını yoxlayırıq. Sonra bu bucağı başqa birinə dəyişdiririk. Bucağı təxmin etmək asandır.

Yansıma bucağı düşmə bucağına bərabərdir

Raketlərin müəyyən sahələri üçün bəzi fiziki istisnalar etmək mümkündür.

Void ballcol() ( if(x == 1 || x == 119 || (x == 10 && y)< (yb1 + 3) && y > < (yb2 + 3) && y > < (yb1 - 3) && y >(yb1 - 8)) ( a = 2; ) if(x == 10 && y > (yb1 + 3) && y< (yb1 + 8)) { a = 4; } if(x == 110 && y < (yb2 - 3) && y >(yb2 - 8)) ( a = 8; ) if(x == 110 && y > (yb2 + 3) && y< (yb2 + 8)) { a = 6; } if(y == 95 || y == 1) { if(a==1){a=5;}else if(a==2){a=4;}else if(a==3){a=7;}else if(a==4){a=2;}else if(a==5){a=1;}else if(a==6){a=8;}else if(a==7){a=3;}else if(a==8){a=6;} } }

Ən çətin hissə bitdi, dərindən nəfəs ala bilərsiniz.

Hal-hazırda, sadəcə olaraq, bir xal sistemi, taymer və yenidən işə salmalıyıq.

Taymeri ilə başlayaq. İkinci bir dəyişən var üzür(mütləq hər zaman saxlanılır), dəyişən int tm(aldığımız dəqiqələrin sayı ts). Dəyəri təyin edin tməməliyyat tm = ts/60;. Və dəyərləri ekranda göstərin, TV.print(81,1,tm); TV.print(97,1,"."); TV.print(100,1,int(ts-(tm*60)));.

Davam edək. Yenidən başlatma funksiyası çağırılır yenidən işə salın (). Burada dəyişənlərin ilkin dəyərlərini qaytarırıq.

Yenidən başlatmanı ləğv edin() ( TV.clear_screen(); x = 60; y = 48; yb1 = 48; yb2 = 48; a = 8; ts = 900.0; c1 = 0; c2 = 0; )

Final, xal sistemi, çox sadədir. Google-u açın və "Stolüstü Tennis Qaydaları" yazın. Hansı xalların verildiyini axtarırıq. Penaltilərlə bağlı hissəni tapırıq və sonra aşağıdakıları uğurla tapırıq: "Rəqibin ilk sıçrayışdan sonra ona göndərilən topu düzgün əks etdirməyə vaxtı yoxdursa, xal qazanılmış sayılır." Sual yaranır, zərbələri necə saymaq olar və s.?.. Və zərbələri saymağa ehtiyac yoxdur, çünki iki ölçülü qrafika ilə stolüstü tennisimiz.

Biz sakitcə çıxış yolu tapırıq və həmişə olduğu kimi yan divarlara nisbətən koordinatları yoxlayırıq. Əgər toqquşma baş verərsə, o zaman sahənin əks tərəfindəki oyunçuya bir xal veririk. Funksiya - voidballscount(). Taymer çıxdıqda - ilk oyunçunun xallarını müqayisə edirik (dəyişən int c1) və ikinci oyunçu (dəyişən int c2), qalibi elan edin, gecikdirin və yenidən işə çağırın.

Topların hesabını ləğv edin() ( if(x == 1) ( c2++; ) if(x == 119) ( c1++; ) if(c1 >< c2 && ts == 0) { TV.println(10, 45, "Player 2 won!"); delay(10000); restart(); } else if(c1 == c2 && ts == 0) { TV.println(10, 45, "You are equal"); delay(10000); restart(); }

Budur, dostlar, oyunun kodunu tam yazmışıq. Olduqca gülməli çıxdı və siz oynaya bilərsiniz.


Tənbəllər üçün bütün kodu yazacağam.

Tam skript

Cəmi 218 sətir var. #daxildir #daxildir TV çıxışı; int x, y, a, c1, c2, yb1, yb2, tm, tsh, s; üzənlər; boolean dayandırıldı = yalan; void quraşdırma() ( TV.begin(NTSC, 120, 96); TV.clear_screen(); TV.select_font(font6x8); TV.println(0, 50, "Shimo'ya xoş gəlmisiniz"); TV.delay(5000) ; TV.clear_screen(); x = 60; y = 48; yb1 = 48; yb2 = 48; a = 8; ts = 900.0; s = 2; ) boş döngə () ( if(!paused) ( TV.draw_line (60,0,60,96,1);TV.select_font(font8x8);racketsmove();ballscount();TV.print(1,1,c1);TV.print(18,1,":") ;TV.print(26,1,c2); tm = ts / 60; ts -= 0,04; if(ts< 0) { ts = 0; } TV.draw_rect(81,1,38,10,0,0); TV.print(81,1,tm); TV.print(97,1,"."); TV.print(100,1,int(ts-(tm*60))); ballcol(); /*if(ts < 600) { s = 4; } if(ts < 300) { s = 6; }*/ ballmove(s, a); TV.delay(50); if(digitalRead(6) == HIGH) { paused = true; delay(1000); } } else { TV.println(40,4,"pause"); if(digitalRead(6) == HIGH) { paused = false; delay(1000); TV.clear_screen(); } } } void ballscount() { if(x == 1) { c2++; } if(x == 119) { c1++; } if(c1 >c2 && ts == 0) ( TV.println(10, 45, "1-ci oyunçu qazandı!"); gecikmə (10000); yenidən başladın(); ) əks halda (c1)< c2 && ts == 0) { TV.println(10, 45, "Player 2 won!"); delay(10000); restart(); } else if(c1 == c2 && ts == 0) { TV.println(10, 45, "You are equal"); delay(10000); restart(); } } void ballcol() { if(x == 1 || x == 119 || (x == 10 && y < (yb1 + 3) && y >(yb1 - 3)) || (x == 110 && y< (yb2 + 3) && y >(yb2 - 3))) ( əgər(a==1)(a=5;)əgər (a==2)(a=8;)əgər (a==3)(a=7;)else əgər(a==4)(a=6;)başqa əgər(a==5)(a=1;)başqasa əgər(a==6)(a=4;)başqasa əgər(a==7)( a=3;)else if(a==8)(a=2;) ) if(x == 10 && y)< (yb1 - 3) && y >(yb1 - 8)) ( a = 2; ) if(x == 10 && y > (yb1 + 3) && y< (yb1 + 8)) { a = 4; } if(x == 110 && y < (yb2 - 3) && y >(yb2 - 8)) ( a = 8; ) if(x == 110 && y > (yb2 + 3) && y< (yb2 + 8)) { a = 6; } if(y == 95 || y == 1) { if(a==1){a=5;}else if(a==2){a=4;}else if(a==3){a=7;}else if(a==4){a=2;}else if(a==5){a=1;}else if(a==6){a=8;}else if(a==7){a=3;}else if(a==8){a=6;} } } void racketsmove() { TV.draw_line(10, yb1+8, 10, yb1-8, 0); TV.draw_line(110, yb2+8, 110, yb2-8, 0); if((yb1 - 8) >1) ( if(digitalRead(2) == YÜKSƏK) ( yb1 -= 2; ) ) if((yb1 + 8)< 95) { if(digitalRead(3) == HIGH) { yb1 += 2; } } if((yb2 - 8) >1) ( if(digitalRead(4) == YÜKSƏK) ( yb2 -= 2; ) ) if((yb2 + 8)< 95) { if(digitalRead(5) == HIGH) { yb2 += 2; } } TV.draw_line(10, yb1+8, 10, yb1-8, 1); TV.draw_line(110, yb2+8, 110, yb2-8, 1); } void ballmove(int vel, int angle) { TV.set_pixel(x,y,0); if(angle == 1) { y -= vel; } if(angle == 3) { x += vel; } if(angle == 5) { y += vel; } if(angle == 7) { x -= vel; } if(angle == 2) { x += round(vel/2); y -= round(vel/2); } if(angle == 4) { x += round(vel/2); y += round(vel/2); } if(angle == 6) { x -= round(vel/2); y += round(vel/2); } if(angle == 8) { x -= round(vel/2); y -= round(vel/2); } TV.set_pixel(x,y,1); } void restart() { TV.clear_screen(); x = 60; y = 48; yb1 = 48; yb2 = 48; a = 8; ts = 900.0; c1 = 0; c2 = 0; }

Addım 4. Bədəni kəsin

Kassanı 4 mm-lik kontrplakdan lazer kəsicidə (və ya freze maşınında, dəqiq bilmirəm) kəsmək qərarına gəldim. Mən onu InkScape-də çəkdim, bir az qarışdırdım və freze formatına çevirdim.


Gamepad üçün kiçik lövhələri kəsdim və düymələr üçün onlarda deşiklər qazdım. Yaxşı çıxdı, amma təəssüf ki, şəkli itirdim.

Nəticə

İş prosesində Arduino ilə sadə oyun televiziya oyun konsolu yaradıldı standart oyun Ping Pong, oynaya biləcəyimiz və hətta ilişib qala biləcəyimiz iki gamepad ilə.

Hey Geek Times!
Bu gün sizə belə olmayan birini deyəcəyəm maraqlı hekayə arduino əsasında sadə oyun konsolunu necə yaratdığım və onun üçün sevimli oyun mühərriki - Unity-də sadə bir oyun hazırladığım haqqında.

Oyunlar

Demək olar ki, dörd ildir ki, məşhur oyun mühərriki Unity-də (keçmiş Unity3D) oyunlar inkişaf etdirirəm. Bu müddət ərzində mən bir neçə kiçik oyun yaratmağı bacardım mobil cihazlar, həmçinin həcmli çox istifadəçili layihə.
Bu sahə mənim üçün çox maraqlıdır və orada işləmək mənə böyük zövq verir.

Cihazlar

Ancaq bəzən yeni bir şey sınamaq istəyi olur və belə günlərin birində arduinonu sınamaq qərarına gəldim.
Öz cihazlarımı necə yaratmağım və onları necə proqramlaşdırmağımla çox maraqlandım. Niyə arduino? İnternetdə və hətta eyni mərkəz və geek vaxtlarında niyə arduino almağınız barədə çoxlu yazılar var. Ancaq qeyd edirəm ki, mənim üçün arduino seçimində həlledici amil istifadənin asanlığıdır.

Və necə birləşdirmək olar?

Bir dəfə İnternetdə istifadəçilərdən birinin sadə arduino əsaslı oyun konsolunu necə yığdığı, onu kiçik 84x48 piksel LCD displeylə təchiz etdiyi və üzərində bir neçə sadə oyun yazması haqqında rekorda rast gəldim: tennis və arkanoid.
Bu inkişaf məni çox maraqlandırdı və atmega328 mikrokontrolleri əsasında oyun konsolunun öz versiyasını yaratmağa qərar verdim.

Konsolun özü

Əvvəlcə LUT dizayn etdim və hazırladım çap dövrə lövhəsi portativ konsol üçün. Bu səhv idi - əvvəlcə proqramı bir debug lövhəsində, məsələn, arduino uno-da sınaqdan keçirməli oldum, çünki proqramları nəzarətçiyə tez və rahat yükləmək imkanı verməmişəm. Mən də dövrənin özündə səhv etdim, onu məftillərlə düzəltmək olardı, amma yenə də ayıbdır.
Səhv etdiyimi başa düşdükdən sonra düymələri board vasitəsilə arduino uno-ya bağladım və ekranı birbaşa bağladım.
Budur, baş verənlər:



İndi oyunlara

Oyunlar yaratmaq üçün Unity oyun mühərrikindən istifadə etmək qərarına gəldim. Mən Mono C#-dan arduino üçün proqrama kompilyator yazmadım, amma asanlıqla oyun qura biləcəyiniz bir sıra skriptlər yazmaq qərarına gəldim.
Bütün skriptləri 3 qrupa böldüm - hərəkətlər, şərtlər və kombinatorlar.
Düşünürəm ki, hərəkətlərin məqsədini və şərtlərini izah etməyə ehtiyac yoxdur, amma kombinatorun nə üçün olduğunu izah edəcəyəm. Birləşdirici şərtin yerinə yetirilib-yetirilmədiyini yoxlayır və sonra hərəkəti yerinə yetirir.
Skriptlərdən, daha doğrusu onların mövcudluğundan və birləşmələrindən alqoritm arduino üçün proqram yaradır.

Və oyun nədir?

Sadə bir şeylə başlamaq qərarına gəldim. Və bildiyiniz ən sadə oyun nədir? Düzdü, tennis. Ancaq mən tam tennislə məşğul olmaq qərarına gəldim, amma biri üçün tennis oynamağa qərar verdim - ikinci raketin əvəzinə bir raket, bir top və bir divar var.
Mən onu yazılı konstruktordan yığdım, kompilyasiya etdim və nəzarətçiyə yüklədim. işləyir!

İndi hər şeyi qaydasına salaq

Oyun başlayanda və mən kifayət qədər oynadığımda qərara gəldim ki, lövhəni yenidən düzəltməyə, ona xəyanət etməyə dəyər gözəl mənzərə, smd komponentlərindən istifadə edin və bütün lazımsızları çıxarın. Mən dövrəni yenidən düzəltdim və lövhə düzəltdim.
Belə oldu



Mənbələr

Mənbə kodu çox sadədir.
Unity nə edir - redaktorda istifadəçi istifadəçi interfeysi obyektlərindən oyunu yığır, onlara fəaliyyət skriptlərini, şərtləri və kombinatorları asır.
Kompilyatorun etdiyi (skript parser.cs) odur ki, o, bütün obyektlər arasından keçir, onların skriptlərinə baxır və build.ino faylının mətninə mikrokontrollerdə bu skriptlərin analoqlarının icrasına cavabdeh olan kod parçaları əlavə edir.

Mənbəyə keçid - drive.google.com/open?id=0B5INc3_98cSJMEMxZmlWUTh1Ukk
Oyun başlayanda tərtib edilir. və Assets/build/text/built.ino qovluğunda saxlandı
Bu eskiz nəzarətçiyə yüklənməlidir.

Həbsdə

Demək istəyirəm ki, çox maraqlı idi.
2 fəaliyyətimi birləşdirmək imkanı əldə etdim - oyun inkişafı və cihaz yaradılması.
Ümid edirəm ki, siz də bununla maraqlanırsınız və indi siz də öz gözəl cihazınızı düzəldəcəksiniz =)