Преместване на чертежа¶
В предишните примери направихме няколко рисунки, съставени от основни форми. По този начин беше необходимо да се определи правилната позиция за всяка от тези форми, за да се поберат всички парчета заедно. За някои чертежи беше възможно (и в някои необходими задачи) координатите на отделните точки да се изчисляват въз основа на известните координати на други точки. Това изчисление можеше да се извърши извън програмата и тогава изчислените координати просто биха могли да бъдат въведени в програмата. По-добре е обаче да извършите такива изчисления в самата програма по няколко причини:
Може да не изчислим координатите правилно при първия опит. В такава ситуация е по-лесно да промените инструкциите за изчисление (т.е. програмата), отколкото да изчислите всичко ръчно от началото.
Когато сами създаваме чертежа, може да се окаже, че след първата версия на програмата може да искаме да добавим нещо, например от лявата страна на чертежа, но че нямаме достатъчно място. В този случай целият чертеж трябва да бъде преместен надясно, така че x координатите на всички точки да бъдат увеличени с една и съща стойност. Ако ръчно сме изчислили координатите на точките, трябва да ги изчислим отново. При добре организирана програма за рисуване е достатъчно да промените едно число, за да преместите целия чертеж вдясно. Този процес може да се наложи да се повтаря няколко пъти, докато не сме доволни от позицията на изтеглената част, така че да го изпробвате е много по-лесно, когато програмата прави изчислението вместо нас.
Ако искаме да начертаем един и същ чертеж на няколко места в прозореца, ползите от изчисляването вътре в програмата се появяват отново.
Сега ще систематизираме изчислението на координатите малко повече и ще го използваме за по-лесното преместване на изтеглените обекти. Преди да започнем, би било добре да проверите предисторията и да отговорите на тези въпроси:
- (50, 60)
- Try again.
- (50, 80)
- Try again.
- (40, 70)
- Correct!
- (60, 70)
- Try again.
- (40, 60)
- Try again.
Q-55: Какви са координатите на точка 10 пиксела вляво от точката (50, 70)?
- (50, 60)
- Try again.
- (50, 80)
- Correct!
- (40, 70)
- Try again.
- (60, 70)
- Try again.
- (40, 60)
- Try again.
Q-56: Какви са координатите на точка 10 пиксела под точката (50, 70)?
- pg.draw.rect(canvas, color, (70, 120, 50, 60))
- Try again.
- pg.draw.rect(canvas, color, (100, 150, 110, 120))
- Try again.
- pg.draw.rect(canvas, color, (100, 150, 50, 60))
- Try again.
- pg.draw.rect(canvas, color, (70, 120, 80, 90))
- Correct!
- pg.draw.rect(canvas, color, (70, 180, 80, 90))
- Try again.
Q-57: Правоъгълникът е нарисуван с помощта на pg.draw.rect(canvas, color, (100, 150, 80, 90))
. Как човек може да нарисува правоъгълник със същия размер, разположен на 30 пиксела вляво и 30 пиксела над този правоъгълник?
- pg.draw.circle(canvas, color, (100, 120), 40)
- Correct!
- pg.draw.circle(canvas, color, (100, 160), 40)
- Try again.
- pg.draw.circle(canvas, color, (120, 100), 40)
- Try again.
- pg.draw.circle(canvas, color, (160, 100), 40)
- Try again.
- pg.draw.circle(canvas, color, (20, 120), 40)
- Try again.
Q-58: Правоъгълникът е нарисуван с помощта на pg.draw.circle(canvas, color, (100, 200), 40)
. Как човек може да нарисува кръг със същия размер над този кръг и да го докосне?
Промени, за да направи рисунката лесно подвижна¶
Нека да видим как се очертава облак в следния пример:
Представихме облака с три кръга, един по-голям в средата и два по-малки около него:
pg.draw.circle(canvas, pg.Color("white"), (200, 200), 50)
pg.draw.circle(canvas, pg.Color("white"), (150, 200), 30)
pg.draw.circle(canvas, pg.Color("white"), (250, 200), 30)
Ако искахме да нарисуваме този облак на различна височина, бихме могли да повторим тези три команди, всеки път с някаква нова стойност за \(y\) координата на центровете на тези три кръга вместо 200, както е на първата рисунка. Например:
pg.draw.circle(canvas, pg.Color("white"), (200, 200), 50)
pg.draw.circle(canvas, pg.Color("white"), (150, 200), 30)
pg.draw.circle(canvas, pg.Color("white"), (250, 200), 30)
pg.draw.circle(canvas, pg.Color("white"), (200, 80), 50)
pg.draw.circle(canvas, pg.Color("white"), (150, 80), 30)
pg.draw.circle(canvas, pg.Color("white"), (250, 80), 30)
pg.draw.circle(canvas, pg.Color("white"), (200, 320), 50)
pg.draw.circle(canvas, pg.Color("white"), (150, 320), 30)
pg.draw.circle(canvas, pg.Color("white"), (250, 320), 30)

По този начин програмата не само се разраства по-бързо, отколкото трябва, но също така трябва да правим всяка промяна на три места (например, ако искаме да опитаме 330 вместо 320, тази промяна трябва да се извърши на три места). Три промени не са много, но ако приемем този начин на правене на нещата, бихме имали все повече проблеми в по-сложни чертежи или в сложни програми като цяло.
Вместо това е по-добре да създадете функция и да прекарате \(y\) координата на центровете като параметър:
def cloud(yc):
pg.draw.circle(canvas, pg.Color("white"), (200, yc), 50)
pg.draw.circle(canvas, pg.Color("white"), (150, yc), 30)
pg.draw.circle(canvas, pg.Color("white"), (250, yc), 30)
cloud(200)
cloud(80)
cloud(320)
Новата програма се чете и променя по-лесно. За повече облаци или по-сложни облаци предимството на този подход би било още по-голямо.
Сега нека помислим как трябва да преместим облака вляво или вдясно. Трябва да увеличим или намалим \(x\) координатите на всички кръгове (200, 150, 250) с една и съща стойност. Например, ако напишем 260, 210, 310 като \(x\) координати, целият облак ще бъде преместен с 60 пиксела вдясно.
Би било добре, ако успеем да използваме само едно число, за да определим хоризонталното положение на облака. За да постигнем това, отбелязваме, че центровете на по-малките кръгове са на 50 пиксела от центъра на средния кръг вляво и вдясно. Тези разстояния не се променят с движението на облака. Това означава, че ако обозначим \(x\) координата на центъра на средния кръг с \(X_c\), тогава центровете на по-малките кръгове имат \(x\) координати \(X_c - 50 \). Благодарение на това отношение (което не зависи от позицията на облака), сега можем също да въведем параметъра \(x\) към функцията, която рисува облака:
def cloud(xc, yc):
pg.draw.circle(canvas, pg.Color("white"), (xc, yc), 50)
pg.draw.circle(canvas, pg.Color("white"), (xc - 50, yc), 30)
pg.draw.circle(canvas, pg.Color("white"), (xc + 50, yc), 30)
cloud(200, 200)
cloud(200, 80)
cloud(200, 320)
Всеки от тези три облака вече може лесно да бъде преместен, например, 60 пиксела вдясно, като напишете 260 като първи параметър вместо 200 във функциите. Също толкова лесно е да направите рисунка с няколко облака. Цвят или нюанс на сивото също могат да бъдат функционален параметър. По този начин някои облаци могат да бъдат по-тъмни, а някои по-светли.
Когато използваме всичко по-горе, можем да създадем програма, която рисува няколко облака от различни нюанси, например:
Нека обобщим с малки обобщения какво трябва да се направи, за да можем да показваме една рисунка на различни места:
Трябва да изберем една точка, чиито координати са зададени директно. Наричаме тази избрана точка главна точка, (понякога тази точка се нарича и котва). В примера на облаците основната точка е центърът на средния кръг.
След като изберете основната точка, координатите на всички други значими точки се определят спрямо нея чрез добавяне или изваждане на определено изместване към координатите на основната точка. В примера с облака, за да получите: math: x координата на центъра на левия кръг, от: math:` x` координата на основната точка (центъра на средния кръг), изваждаме 50 пиксела и за десния кръг добавяме 50 пиксела.
В общия случай на чертежа може да има форми, различни от кръгове. Значителните точки, които определят позициите на тези форми са:
за линия: нейните краища
за многоъгълник: неговите точки
за кръг: неговият център
за правоъгълник: горния му ляв ъгъл
за елипса: горният ляв ъгъл на правоъгълника, в който е вписан този елипс
Всички тези точки трябва да бъдат дадени по отношение на основната точка, тоест техните координати трябва да бъдат изразени като координати на основната точка, увеличени или намалени с някаква стойност.
Проверете разбирането си за предишните обяснения и отговорете на въпросите.
- pg.draw.circle(canvas, pg.Color("red"), (x, y), 50, 1)
- Try again.
- pg.draw.circle(canvas, pg.Color("red"), (x+120, y+90), 50, 1)
- Try again.
- pg.draw.circle(canvas, pg.Color("red"), (x+20, y-10), 50, 1)
- Correct!
- pg.draw.circle(canvas, pg.Color("red"), (x-20, y+10), 50, 1)
- Try again.
Q-59: Искаме да персонализираме чертеж, състоящ се от няколко фигури, така че всичко да е нарисувано спрямо котвата с координатите x=100, y=100. Едно от твърденията, които формират рисунка, е
Какво изявление трябва да замени даденото?
- pg.draw.line(canvas, pg.Color("red"), (x-50, y-50), (150, 150))
- Try again.
- pg.draw.line(canvas, pg.Color("red"), (x-50, y-50), (x+50, y+50))
- Correct!
- pg.draw.line(canvas, pg.Color("red"), (x-50, x+50), (y-50, y+50))
- Try again.
- pg.draw.line(canvas, pg.Color("red"), (x+50, y+50), (x+150, y+150))
- Try again.
Q-60: Искаме да персонализираме чертеж, състоящ се от няколко фигури, така че всичко да е нарисувано спрямо котвата с координатите x=100, y= 100. Едно от твърденията, които формират рисунка, е
Какво изявление трябва да замени даденото?
- pg.draw.rect(canvas, pg.Color("red"), (x-50, y-50, x, y))
- Try again.
- pg.draw.rect(canvas, pg.Color("red"), (x, y, 100, 100))
- Try again.
- pg.draw.rect(canvas, pg.Color("red"), (x+50, y+50, 100, 100))
- Try again.
- pg.draw.rect(canvas, pg.Color("red"), (x-50, y-50, 100, 100))
- Correct!
Q-61: Искаме да персонализираме чертеж, състоящ се от няколко фигури, така че всичко да е нарисувано спрямо котвата с координатите x=100, y= 100. Едно от твърденията, които формират рисунка, е
What statement should replace the given one?
- Вместо pg.draw.circle(canvas, color, (x, y), r, d) ползваме pg.draw.circle(canvas, color, (x+100, y), r, d).
- Correct!
- Вместо pg.draw.circle(canvas, color, (x, y), r, d) ползваме pg.draw.circle(canvas, color, (x-100, y-100), r, d).
- Try again.
- Вместо pg.draw.rect(canvas, color, (x, y, w, h), d) ползваме pg.draw.circle(canvas, color, (x+100, y, w+100, h), d).
- Try again.
- Вместо pg.draw.rect(canvas, color, (x, y, w, h), d) ползваме pg.draw.rect(canvas, color, (x+100, y, w, h), d).
- Correct!
- Вместо pg.draw.rect(canvas, color, (x, y, w, h), d) ползваме pg.draw.rect(canvas, color, (x-100, y, w, h), d).
- Try again.
Q-62: Искаме да преместим чертеж, състоящ се от няколко форми вдясно със 100 пиксела. Маркирайте правилните твърдения.
Следват няколко примера за преобразуване на фиксиран чертеж в подвижен.
Мече - позиция¶
Посочена е следната програма, която показва главата на играчката на мечката:
Програмата извиква седем пъти функцията framed_circle, която рисува дадения кръг с черна рамка (макар че можеше да бъде избегната за трите малки черни кръга). За да можем да променим позицията на чертежа, нека да изберем основната точка (котва). Направете го в центъра на голям кръг, тоест главите на мечката. Координатите на тази точка са (250, 150). Сега трябва да изразим координатите на центровете на всички останали кръгове спрямо основната точка. Вземете за пример дясното ухо на мечката.
\(x\) координата на центъра на дясното ухо е \(310 = 250 + 60\), докато \(y\) координатата е \(80 = 150 - 70\). От тук можем да видим, че координатите на центъра на дясното ухо могат да бъдат записани в програмата като (cx + 60, cy - 70), където (cx, cy) са координатите на главната точка.
Следвайте същата процедура за останалите кръгове и изпълнете функцията draw_teddy.
Тази програма ни позволява лесно да показваме плюшени мечета на различни места на екрана. Например, извикването на функция
draw_teddy(width // 2, height // 2)
който рисува мечка с основната точка в центъра на прозореца (както беше), може да бъде заменен със следните две:
draw_teddy(width // 2 - 120, height // 2)
draw_teddy(width // 2 + 120, height // 2)
Опитайте това! Би било много по-трудно да нарисуваме друга мечка, ако не бяхме адаптирали първоначалната програма за тази употреба.
Къща - позиция¶
Да речем, че сте написали тази програма и целта ви е да преработите програмата, така че къщата да бъде лесно преместена:
Нека основната точка е: code: (x, y) = (50, 150). Попълнете започнатото ремоделиране на програмата в полето по-долу, където чертежът се извършва във функцията: code: draw_house(x, y, wall_color)’. След като се уверите, че чертежите в двете програми изглеждат еднакво (с изключение на това, че те рисуват в прозорци с различни размери), заменете code:`draw_house(50, 150, pg.Color (” khaki “)) със следващ 4, за да получите снимката както при натискане на бутона „Play Task“:
draw_house(150, 90, pg.Color(220, 220, 220))
draw_house(220, 130, pg.Color("white"))
draw_house(350, 160, (255,255,150))
draw_house( 50, 150, pg.Color("khaki"))