Prijavi problem


Obeleži sve katergorije koje odgovaraju problemu

Jos detalja - opišite nam problem


Uspešno ste prijavili problem!
Status problema i sve dodatne informacije možete pratiti klikom na link
Na žalost nismo trenutno u mogućnosti da obradimo Vaš zahtev.
Molimo Vas da pokušate kasnije.

Programiranje grafike pomoću Pygame, priručnik za gimnaziju

Мало сложеније анимације

Семафор

Напиши програм који симулира рад семафора. Прво се приказује зелено светло које траје 4 секунде, након тога се укључује жуто светло које траје секунду, након тога црвено које траје 3 секунде, затим истовремено црвено и жуто која трају секунду, након чега се поново укључује зелено и циклус понавља.

У низу svetla можемо чувати редом која се светла укључују и колико свако од њих траје. За свако светло чувамо уређени пар који као своју прву компоненту садржи тројку истинитосних вредности које говоре да ли је укључено редом црвено, жуто и зелено светло. Друга компонента је трајање светла у милисекундама. Тако, на пример, ((True, True, False), 1000) означава да је црвено-жуто светло укључено током једне секунде, док ((False, False, True), 4000) означава да је зелено светло укључено током једне секунде.

Чуваћемо и редни број светла које тренутно треба да буде укључено и у сваком кораку ћемо га увећавати за 1 (у почетку може да буде постављено на 0, тако да рад семафора креће од црвеног светла). Када се цео циклус проврти, поново се враћамо на почетак (на зелено светло), тако што бројач светла тада постављамо на нулу. То можемо учинити једноставно било гранањем (након сваког увећавања провераваћемо да ли је бројач светла достигао укупан број светала и ако јесте, враћаћемо га на нулу) било модуларном аритметиком (након сваког увећавања израчунаћемо остатак при дељењу укупним бројем светала).

Анимацију ћемо засновати на тајмеру који ћемо навијати тако да се огласи сваки пут када треба да се промени светло. Нагласимо да свако ново навијање тајмера (позив pg.time.set_timer) поништава старо. Дакле, сваки пут када се региструје догађај pg.USEREVENT из низа ћемо читати податке о томе која светла треба да буду укључена и колико дуго. На основу тога вршићемо цртање семафора и затим ћемо поново навијати тајмер на основу прочитане дужине трајања. На крају ћемо увећавати редни број светла, како бисмо се припремили за следећу промену.

Што се тиче цртања, потребно је да проценимо величину три круга и њихов положај на екрану. Претпоставићемо да је размак између свака два светла једнак 10 пиксела, исто колики је и размак између горње ивице прозора и горњег светла и размак између доњег светла и доње ивице прозора. Дакле, гледано вертикално, висина екрана је попуњена са 4 размака (сваки од њих је 10 пиксела) и 3 пречника светла. Дакле 6 полупречника светала и 4 размака од по 10 пиксела једнаки су висини екрана, одакле лако можемо израчунати величину полупречника сваког светла. Центар сваког светла је хоризонтално смештен на половину екрана. Што се тиче вертикалне позиције центара, прво светло је од горње ивице удаљено за један размак и један полупречник светла, друго је удаљено за два размака (размак од горње ивице до горњег светла и размак између првог и другог светла) и три полупречника светла (пречник првог светла и полупречник другог), док је центар трећег светла од горње ивице удаљен за три размака (размак од горње ивице, размак између првог и другог и размак између другог и трећег светла) и пет полупречника светла (пречнике првог и другог и полупречник трећег светла).

ЕКГ срца

Напиши програм који приказује анимацију ЕКГ сигнала срца.

ЕКГ сигнал представљен је изломљеном линијом. У сваком кораку анимације цртаћемо изломљену линију која има једну дуж више него у претходном кораку. Број дужи које линија тренутно садржи чуваћемо у променљивој broj_duzi. На почетку тела петље увећавамо тај број за 1. Претпостављаћемо да је хоризонтално растојање између сваке две суседне тачке сигнала једнако dx. Укупна ширина коју заузима изломљена линија се онда може добити множењем броја дужи и вредности dx. Када та вредност постане већа од ширине екрана, број дужи враћамо на 1 и крећемо цртање сигнала из почетка.

Изломљену линију цртамо тако што у петљи цртамо једну по једну њену дуж. Бројачка променљива i означава редни број дужи који цртамо и креће се од 0 до броја дужи умањеног за један. Та дуж спаја тачку која има редни број i и редни број i+1. Да бисмо нацртали дуж, потребно је да знамо координате њених крајњих тачака. Координата x тачке са редним бројем i се лако добија множењем i*dx. Што се тиче координата y, оне се периодично понављају. Анализом облика сигнала можемо проценити да се облик сигнала може проценити серијом бројева dy = [0, 0, 1, -1, 5, -5, 1, 0, 0, 0]. Наиме, прве две дужи су потпуно хоризонталне, наредна мало скаче на горе, наредна исто толико скаче на доле, затим имамо велики скок (око 5 пута већи него претходни) на горе, затим исти такав скок на доле, затим враћање на висину малог скока на горе и на крају равну линију неко време. На основу вредности у овој листи одређујемо y координате крајњих тачака дужи. Координату одређујемо тако што од вертикалне средине екрана одузмемо вредност из листе помножену неким фактором скалирања (ако је фактор скалирања 10, то значи да скок за 5 јединица представља скок од 50 пиксела). Пошто се сигнал периодично понавља, након обиласка елемената листе, треба кренути од почетка, што можемо лако постићи тако што се код тачке i посматра елемент на позицији која се добије израчунавањем остатка при дељењу броја i дужином листе.

На крају, остаје питање одређивања нијансе боје сваке дужи. Како би се постигао ефекат исчезавања, боју дужи ћемо одређивати тако да последња нацртана дуж буде потпуно зелена, а прва нацртана дуж потпуно црна (док ћемо боје дужи између прве и последње одређивати тако да буду неке нијансе зелене боје, између ове две крајности). Ако усвојимо линеарни модел, потребно је да пронађемо линеарну функцију која ће за i=0 дати количину зелене 0, а за i=broj_duzi-1 дати количину зелене 255 (количина плаве и црвене боје ће стално бити на нули. Веома једноставно се може уочити да је таква линеарна функција i/(broj_duzi-1)*255. Потребно је једино обратити пажњу на специјални случај када постоји само једна дуж (њу можемо обојити у чисту зелену боју).

Овај модел се може још додатно побољшати ако се учини да су све дужи осим оних последњих неколико потпуно црне, а да се онда линеарна скала осветљености примењује само на тих последњих неколико дужи.

Рецаманова секвенца

Жабац Индијана Џонс решава тежак задатак да би се спасао из опасне замке и дошао до блага. Свуда око њега се обрушила земља и он стоји на првом стубу, на сред провалије. Испред њега се налази дугачка стаза од стубова којом може да се извуче. Сви стубови су распоређени дуж праве линије и он се налази на почетном (обележеног бројем 0) и растојање између њих је један метар. У тајној књизи упутстава пише да у сваком наредном кораку мора да скочи један више него у претходном. Пошто је он жабац са супер моћима, то за њега не представља никакав проблем. Веома брзо би одскакутао преко стубова испред њега, да у тајној књизи упутстава пише да када год скоком уназад долази на неки стуб на коме раније није био, он мора да скочи уназад.

Први стуб на коме се жабац налази је 0. Он скаче 1 метар и пошто иза њега нема стубова (пао би у провалију), он мора да скочи унапред, на стуб број 1. У наредном скоку скаче два метра. Опет би га скок уназад довео у провалију, тако да скаче унапред и долази на стуб број 3. У наредном скоку скаче три метра. Скок уназад би га довео сада на стуб 0, где је већ био, па зато може да скочи унапред на стуб број 6. У наредном скоку скаче четири метра. Пошто би скоком уназад доскочио на стуб број 2, на коме раније није био, он мора да уради тако. Након тога скаче на стуб број 7 итд.

Секвенца бројева стубова које жабац обилази назива се Рацаманова секвенца и њени почетни елементи су 0, 1, 3, 6, 2, 7, … Ова секвенца се веома лепо графички представља. Између свака два суседна елемента поставља се полукруг, а ти су полукругови наизменично окренути ка горе и ка доле (као да жабац у једном кораку скаче изнад, а у другом испод стубова). Напиши програм који приказује скокове жапца.

Веома интересантна хипотеза је да ће на било који стуб жабац доскочити у неком тренутку. Провери да ли то важи за првих неколико десетина стубова.

Током извршавања задатка чуваћемо текући елемент секвенце (за то ћемо користити променљиву xt), као и текућу разлику између текућег и наредног елемента секвенце (за то ћемо користити променљиву razlika). Текући елемент иницијализујемо на нулу, а разлику на 1. Пошто је потребно да проверавамо да ли се неки елемент раније јављао, чуваћемо и све претходне елементе секвенце. За то нам је најједноставније (мада не и најефикасније) да употребимо листу (назовимо је recaman). На почетку ћемо у ту листу убацити само почетни елемент секвенце (нулу). У сваком кораку главне петље израчунаваћемо број xt - razlika и проверавати да ли је могуће да он постане наредни елемент секвенце. То ће бити случај ако је у питању природан број (тј. ако је xt - razlika >= 0) и ако се тај број није раније јављао (тј. ако важи not(xt - razlika in recaman)). Ако се установи да xt - razlika може да буде наредни кандидат, онда се xt ажурира на вредност xt - razlika, а у супротном се ажурира на вредност xt + razlika. Након сваког ажурирања вредности xt, ту вредност додајемо и на крај листе recaman (за додавање на крај можемо употребити append).

Остаје још питање како цртати спиралу. Она ће се састојати од полукругова који ће наизменично ићи навише, па наниже. Оријентацију полукруга лако можемо одредити на основу парности броја razlika (провером да ли је razlika % 2 == 0). У једном случају почетни угао лука ће бити 0, а завршни math.pi радијана (тада је полукруг окренут ка горе), а у другом случају обратно (тада је полукруг окренут ка доле). За цртање полукруга потребно је још да знамо координате горњег левог темена квадрата у који је полукруг уписан и његове димензије. Да би слика лепше изгледала, извршићемо трансформацију координатног система тако што ћемо скалирати (зумирати) слику (на пример, фактором 5). То значи да ће разлика између суседних тачака на x оси бити 5 пиксела. Полупречник полукруга се може израчунати као пола разлике између претходне и текуће тачке, помножен фактором скалирања. Ту разлику имамо сачувану у променљивој razlika, пре њеног увећавања за 1 на крају петље. У случају када се скок врши на лево (када се xt ажурира на xt - razlika), тада се леви крај квадрата налази на позицији одређеној вредношћу xt - razlika (десни крај је тада на позицији одређеној вредношћу xt), док се у случају када се скок врши на десно (када се xt ажурира на xt + razlika) леви крај квадрата налази на позицији одређеној вредношћу xt (десни крај је тада на позицији одређеној вредношћу xt + razlika). Најједноставније нам је да током анализе одредимо одговарајући леви крај полукруга (нпр. у променљивој levi_kraj_polukruga), тако да приликом цртања имамо ту вредност на располагању (координату на прозору онда добијамо множењем са фактором скалирања). Коодината y левог горњег темена квадрата се може лако одредити тако што се од координате вертикалне средине прозора (половине висине) одузме полупречник полукруга.

Анимацију на крају остварујемо на најједноставнији могући начин (тако што цртамо у петљи и на крају тела петље паузирамо неки кратак временски интервал - на пример, 100 милисекунди).