Tag Archives: .Net

Պրոցեդուրային գեներացում: Մաս 1

1.1 Ներածություն
Այս խորագրի ներքո այսուհետ կներկայացվեն հոդվածներ ժամանակակից ծրագրավորման առջև դրված հետաքրքիր խնդիրների դասի՝ պրոցեդուրային գեներացման (procedural generation) վերաբերյալ: Պրոցեդուրային գեներացումը նվիրված է հաշվիչ մեքենաների միջոցով պսեվդո-պատահական պատկերների ստացմանը և մեծ կիրառություն ունի համակարգչային գրաֆիկայում և խաղերի դիզայնում: Հոդվածները հաճախ կուղեկցվեն ծրագրային կոդի հատվածներով, հարկ եղած դեպքում կոդը կուղեկցվի հարակից բացատրություններով: Օրինակները աշխատացնելու համար պահանջվող գրադարանների և կոմպոնենտների մասին կնշվի առանձին, ամեն օրինակի հետ:
Պրոցեդուրային գեներացումը անհնար կլիներ առանց պսեվդո-պատահական թվերի ստացման մեթոդների: Մենք չենք սևեռի մեր ուշադրությունը այս ոլորտի վրա, փոխարենը կօգտագործենք պսեվդո-պատահական թվեր գեներացնող .Net Framework-ի գրադարանի System.Random դասը:

1.2 Ռեալիստիկ լանդշաֆտի ստացում, միջնակետի տեղաշարժման ալգորիթմ

Դիտարկենք հետևյալ խնդիրը: Պահանջվում է գեներացնել և պատկերել իրական [Երկիր մոլորակի] լանդշաֆտի ուրվագծին նման ուրվագիծ: Պարզության համար կդիտարկենք ոչ թե եռաչափ լանդշաֆտի գեներացումը, այլ երկչափինը: Կարելի է վերաբերվել դրան որպես եռաչափ լանդշաֆտի ուղղահայաց հատույթի: Նայեք նկարին, որպեսզի պարզ լինի, ինչի մասին է խոսքը:
image

Նման պատկեր կարելի է տեսնել օրինակ երեկոյան հեռվից սարերի/բլուրների խմբին նայելիս: Նման խնդրի լուծման զանազան ալգորիթմներ կան, առավել պարզը դրանցից (ընդ որում, պարզ != վատ) միջնակետի տեղաշարժման ալգորիթմն է:

1. Սկզբում ունենք մի հորիզոնական հատված

midpoint02. Հատվածի ամեն սեգմենտը միջնակետում բաժանում ենք 2 մասի, միջնակետը [-range, range] միջակայքում ընկած պատահական չափով տեղաշարժում ենք վերև կամ ներքև
midpoint3. range թիվը բազմապատկում ենք roughness-ով (խորդուբորդության գործակից): Այն 0.0 – 1.0 միջակայքի ինչ-որ թիվ է: Որքան փոքր է այն, այնքան հղկված ու «փափուկ» է ստացվում ուրվագիծը:
4. Կրկնում ենք 2 և 3 քայլերը պահանջված անգամ: Դժվար չէ նկատել, որ ամեն անգամ 2-րդ քայլն անելուց հետո հատվածների քանակը կրկնապատկվում է:

Դիտողություն: Ռեալիստիկ պատկեր ստանալու համար կարելի է ալգորիթմն աշխատացնել սեգմենտների բավականին մեծ քանակ պահանջելով: Կարելի է նաև ստանալ համեմատաբար քիչ թվով կետեր (սեգմենտների փոքր թիվ տալ մուտքում) և դրանք ինտերպոլացնել գծայնորեն:

Դիտողություն 2: Շատերի մոտ կարող է այս ալգորիթմը ռեկուրսիվ իրականացնելու «ախորժակ» առաջանա: Մի շտապեք, իտերատիվ տարբերակը ճիշտ իրականացնելիս ավելի էֆեկտիվ է:

Այս, առաջին հայացքից պարզ հրամանները կարող են տալ շատ հզոր արդյունք: Իրականում այս ալգորիթմը ծնունդ է առել ծրագրավորման բոլորովին այլ՝ պատկերների ֆրակտալ կոմպրեսիայի ոլորտում կատարված հետազոտությունների արդյունքում: Սա ուղղված է պատկերները պահելու համար պիքսելների մասին ինֆորմացիա պահելու փոխարեն այլ տվյալներ պահելուն, պատկերի զբաղեցրած հիշողության ծավալը փոքրացնելու նպատակով:

Ստորև բերվում է C#-ով գրված ֆունկցիա, որն իրականացնում է ալգորիթմը:

private List<Point> GeneratePoints(int S, float roughness, int range)
{
List<Point> pts = new List<Point>();
pts.Insert(0, new Point(800, 200));
pts.Insert(0, new Point(0, 200));
int segments = 1;
Random rand = new Random();

            while (segments < S)
{
for (int i = 0; i < segments; i++)
pts.Insert(1 + 2 * i, new Point((pts[2*i].X + pts[2*i + 1].X) / 2, (pts[2*i].Y + pts[2*i + 1].Y) / 2 + rand.Next(-range, range)));

                segments *= 2;
range = (int)((float)range * roughness);
}

return pts;
}

Կարող եք բեռնել և փորձարկել նաև Midpoint Displacement ծրագիրը: Այն թույլ է տալիս աշխատանքի ընթացքում կարգավորել սեգմենտնետի քանակը, հեռահարությունն ու խորդուբորդության գործակիցը: Այն աշխատացնելու համար անհրաժեշտ է ունենալ .Net Framework Redistributable 4.0-ն:

midpoint

Եթե ցանկանում եք ստանալ այս ծրագրի կոդը, գրեք մեկնաբանություններում կամ էլեկտրոնային փոստով:
Հաջորդ անգամ (հաջորդ սերիայում Open-mouthed smile) կդիտարկենք նույն խնդիրը լուծող մեկ այլ մեթոդ՝ Pimsleur (չգիտեմ հայերեն էս ոնց են արտասանում…) Noise ֆունկցիայի վրա հիմնված: Կդիտարկենք նաև տարածված ծրագրերում և խաղերում այս մեթոդների կիրառությունների օրինակներ:

Advertisements

Թողնել մեկնաբանություն

Filed under Ծրագրավորում

Օձ .Net – Մաս 2

Շարունակենք կատարելագործել մեր Օձ .Net ծրագիրը: Հիշեցնեմ, որ առաջին մասում մենք կարճ ծանոթություն ունեցանք GDI+ գրաֆիկական API-ի հետ և մոտավոր պատկերացում կազմեցինք, թե ինչ ճարտարապետություն ունի Windows Forms ծրագիրը: Այս մասում  կսովորենք օգտագործել Timer դասը ու կիմանանք երկու եղանակ, թե ինչպես կարելի է սիստեմային պատահարներից (event) առաջացած հաղորդագրությունները (messages) կապել համապատասխան ֆունկցիաների հետ, որոնք կոչվում են պատահարը մշակող ֆունկցիաներ (event handler):

Timer-ի օգտագործումը
Timer Control-ը, որը առաջին հայացքից թվում է անպիտան մի բան, շատ բազմազան կիրառություն ունի գրաֆիկական ինտերֆեյսում ծրագրեր գրելու ժամանակ: Մեր ծրագրում  Timer-ը կօգտագործենք, որպեսզի կազմակերպենք օձի շարժումը: Նախ և առաջ պետք է ծրագրի դասում հայտարարել Timer դասի անդամ: Դրա համար դասի մեջ ավելացրեք (ֆունկցիաներից դուրս) հետևյալ տողը:

private Timer timer = new Timer();
Հարց կտաք, թե ինչու այն հայտարարեցինք private: Առայժմ կարիք չկա, որ timer անդամին հնարավոր լինի դիմել դասի դրսից: Եթե այդպիսի կարիք առաջ գա, հետագայում կարող եք դիմման ատրիբուտը փոխել: Ուշադրություն՝ մեր ծրագրում օգտագործում ենք System.Windows.Forms.Timer namespace-ում հայտարարված Timer դասը: Այլ namespace-ներում, օրինակ՝ System.Threading-ում ևս կան նույնանուն դասեր: Խուսափեք իդենտիֆիկատորի հետ կապված կոնֆլիկտներից: Այժմ, երբ timer անդամն արդեն ունենք, պետք է ծրագրի դասի կառուցիչում արժեքներ տալ նրա որոշ անդամների: public Snakes()

ֆունկցիայի մեջ ավելացրեք հետևյալ տողերը՝

timer.Interval = 500;

timer.Tick += new EventHandler(OnTimerTick);

Սրանցից առաջինով տալիս ենք այն ժամանակահատվածը, որը անցնելուն պես պետք է կանչվի համապատասխան event handler-ը: Ժամանակահատվածը տրվում է միլիվայրկյաններով: Ուշադրություն դարձրեք հաջորդ տողին՝ այս տողը առանձնանում է յուրահատուկ սինտակսիսով. հենց այս տողն է վերը նշված եղանակներից մեկը, որով event handler ֆունկցիան կապում ենք event-ի հետ: Այսինքն սրանով ասում ենք, որ OnTimerTick անունով ֆունկցիան կսկսի աշխատել ամեն անգամ, երբ գրանցվի timer.Tick պատահարը:
Եթե ուշադրություն դարձնեք ծրագրի առաջին մասի կոդին, մենք արդեն կիրառել ենք event-ը event handler-ին կապելու մյուս եղանակը՝

protected override void OnPaint(PaintEventArgs e)

Այս տողով մենք գերբեռնել ենք Form դասի մեջ հայտարարված OnPaint ֆունկցիան, որը տրված է որպես Paint պատահարի մշակող ֆունկցիա: Հիշենք, որ Օձ ծրագրի դասը ժառանգել էինք Form դասից, այլապես չէինք կարողանա գերբեռնել protected դիմման ատրիբուտով մեթոդը:
Վերադառնանք խնդրին: Այժմ, երբ timer օբյեկտը արժեքավորած է և պատրաստ է աշխատանքին, մնում է միայն public Snakes()կառուցիչի վերջում ավելացնել հետևյալ տողը՝

timer.Start();

Սրանով մեր timer-ը սկսում է աշխատել և համակարգը պարբերաբար սկսում է գեներացնել timer.Tick պատահարից առաջացած հաղորդագրություններ:
Այժմ նկարագրենք OnTimerTick մեթոդը:

//Code by Jhora Zakaryan, YSU, 2010
void OnTimerTick(object sender, EventArgs e)
{
Rectangle r1 = Snake[0];
for(int i =  0; i < snakelen-1; i++)
Snake[i] = Snake[i+1];
switch (direction)
{
case 0:
snposx++;
break;
case 1:
snposy++;
break;
case 2:
snposx—;
break;
case 3:
snposy—;
break;
}
if (snposx < 0)
snposx = fieldsize;
if (snposy < 0)
snposy = fieldsize;
Snake[snakelen-1] = new Rectangle((snposx % fieldsize) * ifieldx, (snposy % fieldsize) * ifieldy, ifieldx, ifieldy);
Invalidate(Snake[snakelen — 1]);
Invalidate(r1);
Update();
}

Սկզբում ստեղծում ենք r1 ուղղանկյունը և դրա մեջ պահում ենք օձի պոչի ուղղանկյունը: Սրա միտումը պարզ կդառնա վերջում: Այնուհետև for ցիկլում Snake մասիվի էլէմենտները մեկ դիրք տեղափոխում ենք ձախ: Արդյունքում վերանում է պոչի ուղղանյկունը և գլխի ուղղանկյունից աջ հայտնվում է ևս մեկ գլխի ուղղանկյուն: Վերջինիս փոխարեն հետագայում մեկ այլ ուղղանկյուն ենք ստեղծում, որի կոորդինատները կախված են օձի շարժման ուղղությունից: Այդ կոորդինատները որոշվում են հաջորդող switch-ում: C/C++ ծրագրավորողներ, ուշադրություն դարձրեք, C#-ի switch-ում ճյուղավորման յուրաքանչյուր ճյուղից հետո break/return/goto-ն պարտադիր է: Այն կարելի է բաց թողնել միայն դատարկ ճյուղից հետո: direction անդամ-փոփոխականի միջոցով օձի շարժման ուղղությունը որոշում ենք հետևյալ սխեմայով՝

switch կառույցին հաջորդող 2 if-երը սկզբում չէի նախատեսել ավելացնել կոդի մեջ: Դրանք ավելացնելուց առաջ կանգնած էի մի թերության առաջ: Հիշենք, որ օձի գլխի դիրքը որոշելու համար օգտագործում էինք (snposx-4)%fieldsize*ifieldx, snposy%fieldsize*ifieldy արտահայտությունները, որտեղ % օպերանդը ապահովում էր, որ օձը դուրս չգա ու չկորի ծրագրին հատկացված պատուհանից ու ցիկլիկ սողա client area-ում: Սակայն երբ օրինակ snposy-ը փոքր էր դառնում 0-ից, կոորդինատը միևնույն է բացասական էր դառնում և օձը կորում էր տեսադաշտից: Այս երկու if-երով լուծվեց նշված պրոբլեմը:
Հաջոր երկու տողերում գրված Invalidate ֆունկցիաներով թարմացնում ենք client area-ի՝ օձի գլխին և նախկին պոչին համապատասխան ուղղանկյունները: Իրոք, դժվար չէ նկատել, որ ամեն անգամ, երբ օձը «քայլ է կատարում», փոխվում է միայն նրա գլխի կոորդինատը, և վերանում է պոչը նախկին դիրքից: Այսպիսով, օձին, կամ առավելևս ամբողջ client area-ն ամբողջությամբ վերանկարելու կարիք չկա: Update() ֆունկցիան ապահովում է, որ փոփոխությունները անմիջապես արտացոլվեն էկրանին, և ոչ թե հաջորդ անգամ OnPaint ֆունկցիան կանչելու ժամանակ:

Ստեղնաշարի աշխատանքի ապահովումը
Օձ .Net-ին նվիրված հոդվածների երկրորդ մասում մնաց ավելացնենք ստեղնաշարի աշխատանքի ապահովումը: Դրա համար շատ բան պետք չէ: Նախ ծրագրի դասի կառուցիչում ավելացրեք
this.KeyDown += new KeyEventHandler(OnKeyDown);
տողը, որի նշանակությունը ձեզ արդեն ծանոթ է:
Ապա դասի մեջ ավելացրեք OnKeyDown ֆունկցիան՝

void OnKeyDown(object sender, KeyEventArgs e)
{
switch (e.KeyCode)
{
case Keys.Up:
if (direction != 1)
direction = 3;
return;
case Keys.Down:
if (direction != 3)
direction = 1;
return;
case Keys.Left:
if (direction != 0)
direction = 2;
return;
case Keys.Right:
if (direction != 2)
direction = 0;
return;
}
}

Դե, այսեղ առանձնապես բացատրելու բան չկա, միայն ասեմ, որ if-երը ավելացրել եմ նրա համար, որ օրինակ աջ շարժվող օձը չկարողանա միանգամից 180 աստիճան պտույտ գործի և ձախ շարժվի:
Հա, ու հիշում եք, մենք պայմանավորվել էինք չգծել սև ցանցը, որպեսզի ծրագիրն արագ աշխատի: Այժմ դրա կարիքը չկա, և ցանկության դեպքում ցանցը է նկարել, քանի որ օձի շարժումը OnTimerTick-ում կազմակերպել ենք այնպես, որ այն չի պահանջում ամբողջ «տախտակի» վերանկարումը:
Կեցցե՛նք մենք՝ մեր օձը շարժվում է 😉 Կցում եմ screenshot-ներ.


Առայժմ այսքանը, հոդվածին կցում եմ նաև ծրագրի ամբողջական աշխատող կոդը .docx ֆայլում:

snakepart2

Շարունակելի…

Մեկնաբանություններ (2)

Filed under Ծրագրավորում

Օձ. Net – Մաս 1

Արդեն 2 շաբաթ է, ինչ ուսումնասիրում եմ Microsoft .Net պլատֆորման՝ մասնավորապես Windows միջավայրում կլիենտային ծրագրերի ստեղծման Windows Forms տեխնոլոգիան: Ուզում եմ կիսվել իմ ձեռք բերած փորձով: Բլոգում կթողարկեմ Օձ .Net վերնագրով հոդվածներ: Մեր հեռահար նպատակն է C# լեզվով գրել հին ու բարի Snakes խաղի ժամանակակից տարբերակը: Ասեմ միանգամից, որ մեր նախագծից գերժամանակակից գրաֆիկա ու շեյդերների տեղատարափ սպասող ընթերցողը կարող է միանգամից թողնել ընթերցումը և ինտերնետում կամ որևէ այլ տեղ որոնել DirectX SDK-ի կամ նման այլ գրաֆիկական գրադարանի մասին հոդվածներ: Ասեմ, որ հոդվածիս կկցեմ նախագծի ամբողջ կոդը: Ընթացքում հնարավորինս պարզ ձևով կբացատրեմ կոդի բացատրություն պահանջող կտորները: Կշոշափվեն նաև C#-ի և .Net-ի հետ կապված հարցեր: Ծրագիրը թարգմանելու համար ձեզ պետք կգա C#-ի թարգմանիչ, որը անվճար կարելի է բեռնել Microsoft-ի կայքից, Ցանկալի է ունենալ ժամանակակից IDE (Integrated Development Environment), ինչպիսին է օրինակ Microsoft Visual Studio .Net-ը: Ծրագիրը աշխատացնելու համար անհրաժեշտ է .Net Framework 2.0 կամ ավելի նոր տարբերակը: Նախաբանն այսքանն էր, իսկ այժմ անցնենք գործին:

Մի քանի խոսք նախագծի մասին
Դե բնական է, խաղի «վիզուալ միջուկը» գրելու համար պետք է օգտվել ինչ-որ գրաֆիկական API-ից: Հատուկ .Net պլատֆորմայի համար նախագծվել է երկչափ վեկտորական գրաֆիկայի ու տեքստի արտածման GDI+ API-ն, որն իրենից ներկայացնում է հին Windows API-ի GDI-ի (Graphics Device Interface) համալրված ու կատարելագործված տեսակը: Ես նախատեսել եմ, որ ծրագրում ոչ մի ռաստերային ռեսուրսներ (bitmap նկարներ և այլն) չօգտագործեմ (մի տեսակ հաճելի է զուտ վեկտորային պատկերը): Առաջին մասում մենք կհասցնենք ստեղծել Windows-ի Form (հայերեն լեզվով ասած՝ պատուհան), «պատկերենք» նրա մեջ 20×20 չափերով տախտակ ու նկարենք ինչ որ դիրքում մեր օձին: Պատկերենք բառը այստեղ վերցված է փակագծերի մեջ, որովհետև էֆեկտիվության նկատառումներով տախտակի վանդակներ, որպես այդպիսիք չենք նկարելու: Փոխարենը ժամանակավորապես (պրոֆիլակտիկ նպատակներով) ցանց կնկարենք պատուհանի մեջ, որպեսզի տեսնենք, ճիշտ ենք տեղադրում օձին, թե ոչ:

Ստորև բերվում է ծրագրի կոդը:

using System;
using System.Drawing;
using System.Drawing.Drawing2D;
using System.Windows.Forms;
class Snakes : Form
{
static public int direction = 0, ifieldx, ifieldy,
fieldsize, snakelen = 5;
public int snposx = 7, snposy = 8;
private Rectangle[] Snake;
public static void Main()
{
Application.Run(new Snakes());
}
public Snakes()
{
Text = “Օձ .Net”;
Width = 400;
Height = 400;
BackColor = Color.ForestGreen;
ResizeRedraw = true;
fieldsize = 20;
ifieldx = this.ClientRectangle.Width / fieldsize;
ifieldy = this.ClientRectangle.Height / fieldsize;
Snake = new Rectangle[]{
new Rectangle((snposx-4)%fieldsize*ifieldx, snposy%fieldsize*ifieldy, ifieldx, ifieldy),
new Rectangle((snposx-3)*ifieldx, snposy*ifieldy, ifieldx, ifieldy),
new Rectangle((snposx-2)*ifieldx, snposy*ifieldy, ifieldx, ifieldy),
new Rectangle((snposx-1)*ifieldx, snposy*ifieldy, ifieldx, ifieldy),
new Rectangle(snposx*ifieldx, snposy*ifieldy, ifieldx, ifieldy),
new Rectangle(0, 0, 0, 0),
new Rectangle(0, 0, 0, 0),
new Rectangle(0, 0, 0, 0)
};
}

protected override void OnPaint(PaintEventArgs e)
{
Graphics gfx = e.Graphics;
Pen p = new Pen(Color.Black, 0);
//gfx.SmoothingMode = SmoothingMode.HighQuality;
//gfx.PixelOffsetMode = PixelOffsetMode.HighQuality;
Brush snakeb = Brushes.Indigo;
int i = 0;
for (i = 0; i < fieldsize*ifieldx; i += ifieldx)
{
gfx.DrawLine(p, new Point(i, 0), new Point(i, ifieldy * fieldsize));
}
for (i = 0; i < fieldsize*ifieldy; i += ifieldy)
{
gfx.DrawLine(p, new Point(0, i), new Point(ifieldx * fieldsize, i));
}
gfx.FillRectangles(snakeb, Snake);
}
}

Մեր Snakes դասը ժառանգած է System.Windows.Forms.Form դասից: Static Public տեսակի սահմանված են direction, ifieldx, ifieldy, snakelen փոփոխականներ: Առաջինը հետագայում ցույց է տալու օձի շարժման ուղղությունը, երկրորդն ու երրորդը՝ երևակայական տախտակի վանդակի չափսերը, վերժինը՝ ինչպես կարելի է կռահել անունից, օձի երկարությունն է և սկսբնարժեքավորած է 5: snposx և snposy փոփոխականներում պահված է օձի գլխի տվյալ պահի կոորդինատները տախտակի վրա: Օձը իրենից ներկայացնում է Rectangle դասի մասիվ:
С#-ում static մոդիֆիկատորը նշանակում է, որ static հայտարարված փոփոխականը/ֆունկցիան/օբյեկտը/և այլն հասանելի է առանց այդ դասի նմուշ (instance) ստեղծելու: Այլ կերպ ասած, դասի static անդամները ստեղծվում են ծրագրի աշխատանքի սկսվելուց: Ահա թե ինչու Main ֆունկցիան միշտ հայտարարվում է static: Application.Run(new Snakes()) դիմումով Snakes-ի կառուցիչով ստեղծվում է Form և այն բերվում է էկրան: Ավելի ծավալուն ու հետաքրքիր է Snakes-ի կառուցիչը: Այստեղ արժեքավորվում են Form դասի որոշ Property-ները: Property-ն նորամուծություն է C#-ում և ինչ-որ միջին տեղ է զբաղեցնում ֆունկցիայի և անդամ-փոփոխականի միջև: Նրանում կարելի է ստանդարտ set և get ֆունկցիաներ սահմանել, որոնց միջոցով կարելի է կատարել մուտքագրվող տվյալների ստուգում: Form.Text-ում պահվում է Form-ի վերնագիրը (caption),  Form.Width ու Form.Height-ը Form-ի (ուշադրությու՛ն Form-ի, և ոչ թե դրա Client Area-ի): Form.ResizeRedraw-ի true լինելու դեպքում պատուհանի չափերը փոխելուց կանչվում է OnPaint ֆունկցիան (այն կքննարկենք մի փոքր ուշ):  Ի միջի այլոց նշեմ, որ C#-ը լիովին ապահովում է Unicode-ի նորմալ արտածումը, այնպես որ առանց խուսափելու կարելի է հայերեն, ռուսերեն և ցանկացած լեզվով տեքստ օգտագործել որպես սիմվոլային տողեր, ինչպես նաև որպես իդենտիֆիկատորներ .CS ֆայլերում: Այնուհետև մեր դասի կառուցիչում արժեքներ ենք վերագրում fieldsize-ին: Հաշվի առնելով դրա արժեքը, հաշվում ենք ifieldx, ifieldy-ը: Արժեքներ ենք վերագրում նաև Snake-ի էլեմենտներին: Ուշադրություն դարձրեք օրինակ
(snposx — 4) % fieldsize * ifieldx  արտահայտությանը: Այն ավելի մանրամասն կքննարկենք հաջորդ մասերում, երբ կփորձենք շարժել մեր օձին: Սա թույլ չի տալիս, որ օձը դուրս գա մեր ցանցից: Երբ, օրինակ, այն դուրս է գալիս ցանցի աջ կողմից, դրա գլուխը հայտնվում է ցանցի ձախ կողմում: Մասիվի վերջին երեք էլեմենտները պահեստային կարգավիճակում են: Մեր օձը խաղի ընթացքում, ըստ մտահղության, բոյովանալու է J:
Եվ վերջապես քննարկենք OnPaint գերբեռնված ֆունկցիան: Այն ամենը, ինչ GDI+-ի միջոցով նկարելու ենք էկրանին, նկարելու ենք այստեղ: Գրաֆիկական սարքին դիմելու համար ստեղծում ենք Graphics դասի օբյեկտ, որը փոխանցվում է OnPaint ֆունկցիային արգումենտի տեսքով: Սրան հաջորդող հայտարարված սև Pen-ով գծելու ենք ցանցը: snakeb Brush-ով  ներկելու ենք օձի մարմինը կազվող Rectangle-ները: GDI+-ում կա ստանդարտ, նախապես որոշված 141 ARGB գույն (բացի սիստեմային գույներից), դրանք բոլորը հասանելի են որպես Color դասի Property-ներ: Մեկնաբանությունների մեջ առնված երկու տողերը միացնում են AntiAliasing-ը: Պիքսելների մշակման այս մեթոդը լայնորեն կիրառվում է վեկտորական գրաֆիկայում և midtone-ների միջոցով ավելի հարթ ու հղկված է դարձնում վեկտորական պատկերների եզրերը: Եթե Ձեր համակարգիչը բավականին հզոր է, կարող ես միացնել AntiAliasing-ը և տեսնել տարբերությունը:
Հաջորդող 2 for ցիկլերում նկարվում են ցանցի նախ ուղղահայաց, հետո հորիզոնական գծերը: Ուշադրություն դարձրեք, որ GDI+-ում գիծ գծելու համար անհրաժեշտ է միայն մի ֆունկցիայի դիմում: Վերջին մեթոդը ներկում է Snake մասիվի տարրեր հանդիսացող Rectangle-ները, դրանով տեսանելի դարձնելով մեր օձը: Արդյունքում պետք է ստանաք նման մի բան.

Համոզվելպւց հետո, որ օձը կանգնած է ճիշտ տեղում, ունի ճիշտ գույնը և երկարությունը, կարելի է մաքրել ցանցը պատկերող կոդը, քանի որ այն այլևս մեզ պետք չի գա:
Շարունակելի…

Մեկնաբանություններ (2)

Filed under Ծրագրավորում