داشتم فکر میکردم که یه اسم مناسب برای اینجا انتخاب کنم...
که هم به برنامه نویسی مربوط باشه
هم به اسم خودم
همینطور که داشتم فکر میکردم یاد حرکت یکی از دوستان(جواهری) افتادم که اومده بود و اسمش رو با فونت لوگو java نوشته بود و و به جای ۴ حرف اولش لوگو جاوا رو گذاشته بود...
بعد گفتم اسم منم این پتانسیل داره که Javad رو ۴ حرف اولش رو نماد جاوا بزارم و اینجوری باشه که Java + d
دیدم اما من که اصلا علاقه ای به جاوا ندارم کار هم نکردم
چه زبانی رو هم کار کردم هم دوست دارم؟
C,C++,C#,...
و اگه جای java بیام لوگو C بزارم به کلمه CD میرسم.
و از اون جایی که CD فاز نوستالژیک داره و بهم حس و حال خوبی میده و احتمالا مطالبی که داخل اینجا میزارم برای شما دوستان قدیمی هست، اما جالبه رو بزارم...
پس همراه باشید با کانال 💿CD
💿Records 0
🗃️CD Archive
که هم به برنامه نویسی مربوط باشه
هم به اسم خودم
همینطور که داشتم فکر میکردم یاد حرکت یکی از دوستان(جواهری) افتادم که اومده بود و اسمش رو با فونت لوگو java نوشته بود و و به جای ۴ حرف اولش لوگو جاوا رو گذاشته بود...
بعد گفتم اسم منم این پتانسیل داره که Javad رو ۴ حرف اولش رو نماد جاوا بزارم و اینجوری باشه که Java + d
دیدم اما من که اصلا علاقه ای به جاوا ندارم کار هم نکردم
چه زبانی رو هم کار کردم هم دوست دارم؟
C,C++,C#,...
و اگه جای java بیام لوگو C بزارم به کلمه CD میرسم.
و از اون جایی که CD فاز نوستالژیک داره و بهم حس و حال خوبی میده و احتمالا مطالبی که داخل اینجا میزارم برای شما دوستان قدیمی هست، اما جالبه رو بزارم...
پس همراه باشید با کانال 💿CD
💿Records 0
🗃️CD Archive
Telegram
CD
🗃CD Archive 🗃
💿Records 0 : introduction
💿Records 1 : Base 10 (fun)
💿Records 2 : Moon rotation animation in CMD (fun)
💿Records 3 : 3D cube rotation animation in CMD (fun)
💿Records 4 : Git
💿Records 5 : Download video stream from web
💿Records 6 : TOR (Disc…
💿Records 0 : introduction
💿Records 1 : Base 10 (fun)
💿Records 2 : Moon rotation animation in CMD (fun)
💿Records 3 : 3D cube rotation animation in CMD (fun)
💿Records 4 : Git
💿Records 5 : Download video stream from web
💿Records 6 : TOR (Disc…
طی تکامل انسان وقتی شروع کرد به شمردن از انگشت های دستش کمک گرفت تا باهاش بشماره...
حالا چون 10 تا انگشت دست داریم
شمارش بر مبنای 10 انجام شد...
و انسان های اولیه بیشترین عددی که میتونستین با انگشت های دستشون بشمارن عدد 10 بود...
اما تو دنیایی امروز شما با 10 تا انگشت چه بازهای از اعداد میتونید بشمارید؟
هر انگشت ما دو حالت داره
باز و بسته
مثل کامپیوتر که فقط جریان قطع برق و وصل برق رو میفهمه...
حالا بیایم به جای اینکه کل انگشت هامون رو یک مبنا در نظر بگیرم و از 0 تا 10 نمایش بدیم.
بیایم و هر انگشت رو مبنا قرار بدیم
و چون دوتا حالت باز و بسته داره مبنای دو نظر میگیرم.
انگشت اول
2^0
انگشت دوم
2^1
.
.
.
انگشت دهم
2^9
مقدار داشته باشه...
حالا کمترین عددی که میتونید نمایش بدید حالتی هست که همه انگشت ها بسته باشه و مقدار 0 بگیره، به عدد 0 میرسیم...
و بیشترین عددی که میتونیم نمایش بدیم حالتی هست که همه انگشت ها باز باشه و مقدار ارزش اون انگشت رو داشته باشیم که میشه
1+2+4+8+...+512
یا به عبارتی
(2^10)-1=1023
اگه انگشت های شصتمون هم مثل باقي انگشت ها سه بخشی بود
میتونستیم تا
(4^10)-1=1,048,575
بشماریم...
انسان های اولیه با دیدگاهشون به 10تا انگشت هاشون 10 تا ارزش دادن
الان میتونید با دیدی که دارید به 10 تا انگشتتون 1023 ارزش بدید
هر کس با دیدگاه خودش به یه چیزی ارزش میده!
💿Records 1
🗃️CD Archive
حالا چون 10 تا انگشت دست داریم
شمارش بر مبنای 10 انجام شد...
و انسان های اولیه بیشترین عددی که میتونستین با انگشت های دستشون بشمارن عدد 10 بود...
اما تو دنیایی امروز شما با 10 تا انگشت چه بازهای از اعداد میتونید بشمارید؟
هر انگشت ما دو حالت داره
باز و بسته
مثل کامپیوتر که فقط جریان قطع برق و وصل برق رو میفهمه...
حالا بیایم به جای اینکه کل انگشت هامون رو یک مبنا در نظر بگیرم و از 0 تا 10 نمایش بدیم.
بیایم و هر انگشت رو مبنا قرار بدیم
و چون دوتا حالت باز و بسته داره مبنای دو نظر میگیرم.
انگشت اول
2^0
انگشت دوم
2^1
.
.
.
انگشت دهم
2^9
مقدار داشته باشه...
حالا کمترین عددی که میتونید نمایش بدید حالتی هست که همه انگشت ها بسته باشه و مقدار 0 بگیره، به عدد 0 میرسیم...
و بیشترین عددی که میتونیم نمایش بدیم حالتی هست که همه انگشت ها باز باشه و مقدار ارزش اون انگشت رو داشته باشیم که میشه
1+2+4+8+...+512
یا به عبارتی
(2^10)-1=1023
اگه انگشت های شصتمون هم مثل باقي انگشت ها سه بخشی بود
میتونستیم تا
(4^10)-1=1,048,575
بشماریم...
انسان های اولیه با دیدگاهشون به 10تا انگشت هاشون 10 تا ارزش دادن
الان میتونید با دیدی که دارید به 10 تا انگشتتون 1023 ارزش بدید
هر کس با دیدگاه خودش به یه چیزی ارزش میده!
💿Records 1
🗃️CD Archive
Telegram
CD
🗃CD Archive 🗃
💿Records 0 : introduction
💿Records 1 : Base 10 (fun)
💿Records 2 : Moon rotation animation in CMD (fun)
💿Records 3 : 3D cube rotation animation in CMD (fun)
💿Records 4 : Git
💿Records 5 : Download video stream from web
💿Records 6 : TOR (Disc…
💿Records 0 : introduction
💿Records 1 : Base 10 (fun)
💿Records 2 : Moon rotation animation in CMD (fun)
💿Records 3 : 3D cube rotation animation in CMD (fun)
💿Records 4 : Git
💿Records 5 : Download video stream from web
💿Records 6 : TOR (Disc…
یک روز سر حل تمرین برای آمادگی آزمون درس مبانی کامپیوتر داشتیم مبحث for & if رو کار میکردیم و برای تمرین مثال های مثل رسم مثلث، لوزی و... رو با ستاره میزدیم.
به شوخی گفتم سر امتحان بهتون میگم دایره بزنید.
و همون جا خودم شروع کردن زدن.
همونطور که میدونید تو صفحه مختصات به مرکز مبدا مختصات فرمول دایره به شعاع r برابر هست با
حالا صرفا لازم هست که فضای دوبعدی مون رو شبیه سازی کنیم.
با انجام دوتا for تو در تو از منفی r تا مثبت r حرکت کنه.
⚠️چرا برای درون دایره و بیرون دایره از دو تا علامت * یا space استفاده کردیم؟
چون فاصله هر خط تو CMD به اندازه دوتا کارکتر هست، و اگه با یکدونه بنویسیم دایرهمون تبدیل میشه به بیضی.
به شوخی گفتم سر امتحان بهتون میگم دایره بزنید.
و همون جا خودم شروع کردن زدن.
همونطور که میدونید تو صفحه مختصات به مرکز مبدا مختصات فرمول دایره به شعاع r برابر هست با
(x^2)+(y^2)<(r^2)
حالا صرفا لازم هست که فضای دوبعدی مون رو شبیه سازی کنیم.
با انجام دوتا for تو در تو از منفی r تا مثبت r حرکت کنه.
#include <stdio.h>
#include <math.h>
#include <stdlib.h>
int main()
{
int r;
printf("Please Enter Radius of the moon(Max=45):");
scanf("%d",&r);
for(int y = r; y > -r; y--){
for(int x = -r; x < r; x++)
{
if(pow(x,2) + pow(y,2) < pow(r,2)){
printf("**");
}
else{
printf(" ");
}
}
printf("\n");
}
return 0;
}
⚠️چرا برای درون دایره و بیرون دایره از دو تا علامت * یا space استفاده کردیم؟
چون فاصله هر خط تو CMD به اندازه دوتا کارکتر هست، و اگه با یکدونه بنویسیم دایرهمون تبدیل میشه به بیضی.
حالا که تونستیم دایره رسم کنیم میخوایم یک انیمیشن برای نمایش چرخش ماه نمایش بدیم!
چرا ماه رو به صورت حلال میبینیم؟
سایه زمین میفته روی ماه و بخشی از ماه (که سایه زمین روش هست) نور خورشید رو بازتاب نمیکنه!
پس کاری که باید بکنیم ساده است :
دوتا دایره تعریف کنیم یکیش رو ثابت نگه داریم و دایره دیگری رو حرکت بدیم و از بالا سمت چپ تا پایین سمت راست دایره دوم رو حرکت میدیم!
و شرطمون رو به این تغییر میدیم که روی دایره اول باشه ولی روی دایره دوم نباشه!
اگه بود کارکتر رو چاپ بکنه در غیر اینصورت اسپیس چاپ کنه !
چرا ماه رو به صورت حلال میبینیم؟
سایه زمین میفته روی ماه و بخشی از ماه (که سایه زمین روش هست) نور خورشید رو بازتاب نمیکنه!
پس کاری که باید بکنیم ساده است :
دوتا دایره تعریف کنیم یکیش رو ثابت نگه داریم و دایره دیگری رو حرکت بدیم و از بالا سمت چپ تا پایین سمت راست دایره دوم رو حرکت میدیم!
و شرطمون رو به این تغییر میدیم که روی دایره اول باشه ولی روی دایره دوم نباشه!
اگه بود کارکتر رو چاپ بکنه در غیر اینصورت اسپیس چاپ کنه !
این هم از کدش
#include <stdio.h>
#include <math.h>
#include <stdlib.h>
void draw (int i, int j, int r,int k)
{
if(pow((j),2)+pow((i),2)<= pow(r,2) && !(pow((j-k),2)+pow((i-k),2)<= pow(r,2)))
{
printf("0O");
return ;
}
else
{
printf(" ");
return ;
}
}
int main()
{
int r;
printf("Please Enter Radius of the moon(Max=45):");
scanf("%d",&r);
for(int k=-(sqrt(2)*r);k<=(sqrt(2)*r);k++)
{
printf("\x1b[2J");
for(int j=-r;j<=r;j++){
for(int i=-r;i<=r;i++){
draw(i,j,r,k);
}
printf("\n");
}
}
return 0;
}
کاری که امروز میخوایم بکنیم ساخت یک مکعب 3بعدی در حال چرخش هست.
بریم که مراحل مطالعات لازم رو براش شروع کنیم
بریم که مراحل مطالعات لازم رو براش شروع کنیم
خب اول از همه میرسیم به تبدیل مختصات سهبعدی که باید انجام بدیم و چیزی که با سرچ بدست آوردم و از صفحه wikipedia پیدا کردم این هست!
CD
حالا با کمک maple و ضربشون در ماتریس [i,k,j] به ماتریس زیر رسیدم... Vector[row](3, [(i*cos(B) - (-j*sin(A) + k*cos(A))*sin(B))*cos(C) + (j*cos(A) + k*sin(A))*sin(C), -(i*cos(B) - (-j*sin(A) + k*cos(A))*sin(B))*sin(C) + (j*cos(A) + k*sin(A))*cos(C), i*sin(B)…
تابع calculateX در این برنامه، مسئول محاسبه مختصات جدید x یک نقطه در فضای سهبعدی بعد از چرخش آن حول محورهای مختلف (چرخش در فضای سهبعدی) است. این تابع با استفاده از زوایای چرخش
A، B و C (به ترتیب حول محورهایx، y و z)، مختصات جدید x را محاسبه میکند.
این تابع سه ورودی دارد که مختصات اصلی یک نقطه در فضای سهبعدی هستند:
i: مختصهی x
j: مختصهی y
k: مختصهی z
تابع calculateX به همراه توابع مشابه دیگر (calculateY و calculateZ) مسئول انجام چرخش سهبعدی بر روی مختصات مکعب است تا این مکعب به صورت چرخان در صفحهنمایش دوبعدی ظاهر شود.
A، B و C (به ترتیب حول محورهایx، y و z)، مختصات جدید x را محاسبه میکند.
این تابع سه ورودی دارد که مختصات اصلی یک نقطه در فضای سهبعدی هستند:
i: مختصهی x
j: مختصهی y
k: مختصهی z
تابع calculateX به همراه توابع مشابه دیگر (calculateY و calculateZ) مسئول انجام چرخش سهبعدی بر روی مختصات مکعب است تا این مکعب به صورت چرخان در صفحهنمایش دوبعدی ظاهر شود.
float calculateX(int i, int j, int k) {
return j * sin(A) * sin(B) * cos(C) - k * cos(A) * sin(B) * cos(C) +
j * cos(A) * sin(C) + k * sin(A) * sin(C) + i * cos(B) * cos(C);
}
float calculateY(int i, int j, int k) {
return j * cos(A) * cos(C) + k * sin(A) * cos(C) -
j * sin(A) * sin(B) * sin(C) + k * cos(A) * sin(B) * sin(C) -
i * cos(B) * sin(C);
}
float calculateZ(int i, int j, int k) {
return k * cos(A) * cos(B) - j * sin(A) * cos(B) + i * sin(B);
}تابع
ورودیهای تابع:
-
-
-
-
مراحل عملکرد:
1. محاسبهی مختصات سهبعدی جدید:
- تابع ابتدا با استفاده از توابع calculateX، calculateY و calculateZ، مختصات سهبعدی جدید نقطه را بعد از اعمال چرخشها (با توجه به زوایای ( A )، ( B )، و ( C )) محاسبه میکند. این توابع، مختصات نقطه را پس از چرخش حول محورهای مختلف به دست میآورند.
2. محاسبهی مختصات عمق (z):
- مقدار مختصهی ( z ) بعد از چرخش به فاصلهای از دوربین اضافه میشود تا نقطه از دید دوربین نمایش داده شود:
3. محاسبهی "معکوس فاصله از دوربین" (ooz):
- مقدار
4. تبدیل مختصات سهبعدی به دوبعدی:
- با استفاده از مقدارهای محاسبهشده، تابع مختصات دوبعدی (مختصات x و y برای نمایش در صفحهنمایش) را محاسبه میکند. این مقادیر به عنوان مختصات پیکسلی نقطه در صفحهی دوبعدی استفاده میشوند:
این فرمولها با استفاده از
5. رسم نقطه روی صفحهنمایش:
- پس از محاسبهی مختصات ( xp ) و ( yp ) (مختصات دوبعدی در صفحهنمایش)، تابع بررسی میکند که آیا این نقطه در محدودهی نمایش (درون مرزهای صفحهنمایش) قرار دارد یا خیر. اگر نقطه در محدوده باشد و مقدار
در این حالت، مقدار
نتیجه کلی:
تابع
calculateForSurface در این برنامه وظیفه محاسبه مختصات دوبعدی یک نقطه از سطح مکعب را بر عهده دارد. این تابع مختصات سهبعدی یک نقطه از سطح مکعب را دریافت میکند، آنها را با توجه به چرخشهای مکعب به مختصات دوبعدی تبدیل میکند و سپس آن نقطه را روی صفحهنمایش دوبعدی بهصورت کاراکتر ASCII نمایش میدهد.ورودیهای تابع:
-
cubeX: مختصهی ( x ) در فضای سهبعدی.-
cubeY: مختصهی ( y ) در فضای سهبعدی.-
cubeZ: مختصهی ( z ) در فضای سهبعدی.-
ch: کاراکتر ASCII که قرار است در محل محاسبهشده نمایش داده شود.مراحل عملکرد:
1. محاسبهی مختصات سهبعدی جدید:
- تابع ابتدا با استفاده از توابع calculateX، calculateY و calculateZ، مختصات سهبعدی جدید نقطه را بعد از اعمال چرخشها (با توجه به زوایای ( A )، ( B )، و ( C )) محاسبه میکند. این توابع، مختصات نقطه را پس از چرخش حول محورهای مختلف به دست میآورند.
2. محاسبهی مختصات عمق (z):
- مقدار مختصهی ( z ) بعد از چرخش به فاصلهای از دوربین اضافه میشود تا نقطه از دید دوربین نمایش داده شود:
z = calculateZ(cubeX, cubeY, cubeZ) + distanceFromCam;
3. محاسبهی "معکوس فاصله از دوربین" (ooz):
- مقدار
ooz برابر معکوس مقدار ( z ) است که برای محاسبهی مقیاسبندی استفاده میشود:ooz = 1 / z;
4. تبدیل مختصات سهبعدی به دوبعدی:
- با استفاده از مقدارهای محاسبهشده، تابع مختصات دوبعدی (مختصات x و y برای نمایش در صفحهنمایش) را محاسبه میکند. این مقادیر به عنوان مختصات پیکسلی نقطه در صفحهی دوبعدی استفاده میشوند:
xp = (int)(width / 2 + horizontalOffset + K1 * ooz * x * 2);
yp = (int)(height / 2 + K1 * ooz * y);
این فرمولها با استفاده از
K1 (یک ثابت برای مقیاسبندی)، مختصات سهبعدی ( x ) و ( y ) را به مختصات دوبعدی صفحهنمایش تبدیل میکنند.5. رسم نقطه روی صفحهنمایش:
- پس از محاسبهی مختصات ( xp ) و ( yp ) (مختصات دوبعدی در صفحهنمایش)، تابع بررسی میکند که آیا این نقطه در محدودهی نمایش (درون مرزهای صفحهنمایش) قرار دارد یا خیر. اگر نقطه در محدوده باشد و مقدار
ooz بزرگتر از مقدار موجود در بافر عمق (zBuffer) باشد (یعنی نقطه نزدیکتر به دوربین باشد): if (idx >= 0 && idx < width * height) {
if (ooz > zBuffer[idx]) {
zBuffer[idx] = ooz;
buffer[idx] = ch;
}
}
در این حالت، مقدار
ooz در بافر عمق ذخیره میشود و کاراکتر ASCII مربوطه (ch) در موقعیت محاسبهشدهی آن قرار میگیرد.نتیجه کلی:
تابع
calculateForSurface یک نقطه از سطح مکعب را بعد از اعمال چرخشها و تغییرات سهبعدی به مختصات دوبعدی تبدیل کرده و آن را با کاراکتر ASCII مربوطه روی صفحهی کنسول رسم میکند. همچنین از طریق مقایسهی عمق نقطه (مقدار z)، تضمین میکند که سطحهای نزدیکتر به دوربین بر روی سطحهای دورتر نمایش داده شوند.void calculateForSurface(float cubeX, float cubeY, float cubeZ, int ch) {
x = calculateX(cubeX, cubeY, cubeZ);
y = calculateY(cubeX, cubeY, cubeZ);
z = calculateZ(cubeX, cubeY, cubeZ) + distanceFromCam;
ooz = 1 / z;
xp = (int)(width / 2 + horizontalOffset + K1 * ooz * x * 2);
yp = (int)(height / 2 + K1 * ooz * y);
idx = xp + yp * width;
if (idx >= 0 && idx < width * height) {
if (ooz > zBuffer[idx]) {
zBuffer[idx] = ooz;
buffer[idx] = ch;
}
}
}در این بخش از کد، از تابع
خط اول:
buffer: این آرایهای است که کاراکترهای ASCII را برای نمایش مکعب در صفحهنمایش ذخیره میکند.
backgroundASCIICode: یک کد ASCII که نمایانگر کاراکتر پسزمینه (فضای خالی) است. این مقدار برابر با
width * height: تعداد کل خانههای موجود در آرایه
این خط از کد کل بافر
خط دوم:
zBuffer: آرایهای که عمق هر نقطه (مقدار \( z \)) را در خود نگه میدارد. از این آرایه برای اطمینان از این استفاده میشود که نقاط نزدیکتر به دوربین روی نقاط دورتر نمایش داده شوند.
- `0`: تمام خانههای این آرایه با صفر مقداردهی میشوند. این یعنی در ابتدا هیچ نقطهای از مکعب در صفحه رسم نشده است.
width * height * 4`: اندازهی کل آرایه
این خط از کد آرایهی
هدف کلی:
این دو خط کد در ابتدای هر فریم:
1. buffer را با کاراکتر پسزمینه (معمولاً فضای خالی) پر میکند تا صفحهنمایش تمیز شود.
2. zBuffer را صفر میکند تا بتواند عمق نقاط جدید را بدون تأثیر از مقادیر قبلی محاسبه کند.
این عملیاتها برای آمادهسازی هر فریم جدید ضروری هستند تا انیمیشن چرخش مکعب به درستی اجرا شود.
memset استفاده میشود تا آرایههای buffer و zBuffer با مقادیر مشخصی مقداردهی اولیه شوند. به طور دقیقتر:خط اول:
memset(buffer, backgroundASCIICode, width * height);
buffer: این آرایهای است که کاراکترهای ASCII را برای نمایش مکعب در صفحهنمایش ذخیره میکند.
backgroundASCIICode: یک کد ASCII که نمایانگر کاراکتر پسزمینه (فضای خالی) است. این مقدار برابر با
' ' (فضای خالی) است.width * height: تعداد کل خانههای موجود در آرایه
buffer است که معادل با تعداد کل کاراکترهایی است که روی صفحهنمایش کنسول نشان داده میشوند.این خط از کد کل بافر
buffer را با کاراکتر پسزمینه پر میکند (مثلاً فضای خالی یا یک کاراکتر دیگر). این کار هر فریم قبل از اینکه مکعب دوباره رسم شود، انجام میشود تا صفحهنمایش تمیز شود.خط دوم:
memset(zBuffer, 0, width * height * 4);
zBuffer: آرایهای که عمق هر نقطه (مقدار \( z \)) را در خود نگه میدارد. از این آرایه برای اطمینان از این استفاده میشود که نقاط نزدیکتر به دوربین روی نقاط دورتر نمایش داده شوند.
- `0`: تمام خانههای این آرایه با صفر مقداردهی میشوند. این یعنی در ابتدا هیچ نقطهای از مکعب در صفحه رسم نشده است.
width * height * 4`: اندازهی کل آرایه
zBuffer که برابر با تعداد کل پیکسلهای صفحه ضربدر اندازهی هر عنصر (۴ بایت برای هر مقدار عمق) است.این خط از کد آرایهی
zBuffer را قبل از هر فریم با صفر مقداردهی میکند تا در هر فریم جدید مقادیر عمق نقاط از نو محاسبه شوند.هدف کلی:
این دو خط کد در ابتدای هر فریم:
1. buffer را با کاراکتر پسزمینه (معمولاً فضای خالی) پر میکند تا صفحهنمایش تمیز شود.
2. zBuffer را صفر میکند تا بتواند عمق نقاط جدید را بدون تأثیر از مقادیر قبلی محاسبه کند.
این عملیاتها برای آمادهسازی هر فریم جدید ضروری هستند تا انیمیشن چرخش مکعب به درستی اجرا شود.
CD
در این بخش از کد، از تابع memset استفاده میشود تا آرایههای buffer و zBuffer با مقادیر مشخصی مقداردهی اولیه شوند. به طور دقیقتر: خط اول: memset(buffer, backgroundASCIICode, width * height); buffer: این آرایهای است که کاراکترهای ASCII را برای نمایش مکعب…
این بخش از کد وظیفه دارد سطحهای مختلف مکعب را محاسبه و برای هر سطح آنها را با استفاده از کاراکترهای ASCII مختلف روی صفحه نمایش دهد. این کار با استفاده از دو حلقهی تو در تو انجام میشود که نقاط مختلف روی سطوح مکعب را بررسی میکنند و برای هر نقطه، تابع
توضیحات کلی:
- حلقههای تو در تو: این حلقهها کل سطح مکعب را نقطه به نقطه بررسی میکنند و برای هر نقطه مختصات سهبعدی آن را به مختصات دوبعدی تبدیل میکنند.
- کاراکترهای مختلف برای سطوح مکعب: هر سطح مکعب با یک کاراکتر ASCII متفاوت رسم میشود تا بتوانید هر سطح را به وضوح از دیگر سطوح تشخیص دهید.
- تابع calculateForSurface: این تابع مختصات دوبعدی نقطهای از سطح مکعب را محاسبه میکند و در صورت برآورده شدن شرایط (مثل عمق)، آن را روی صفحهنمایش قرار میدهد.
جزئیات هر خط:
1. حلقههای تو در تو:
- این دو حلقه مختصات نقاط مختلفی را روی سطوح مکعب بررسی میکنند.
- متغیر cubeX و cubeY به ترتیب نقاطی را در طول محورهای ( x ) و ( y ) روی سطحهای مختلف مکعب تکرار میکنند.
- حلقهها از مقدار -cubeWidth تا +cubeWidth برای هر دو متغیر تکرار میشوند. این یعنی کل سطح مکعب با در نظر گرفتن cubeWidth به عنوان اندازه هر ضلع پیمایش میشود.
- incrementSpeed: میزان تغییرات ( x ) و ( y ) در هر تکرار، که تعیین میکند نقاط با چه فاصلهای از هم بررسی شوند.
2. فراخوانی calculateForSurface برای هر سطح مکعب:
این تابع برای هر سطح مکعب ۶ بار برای نقاط مختلف فراخوانی میشود تا همهی شش سطح مکعب رسم شوند:
- سطح 1 (جلو):
این خط مسئول رسم سطح جلویی مکعب است که در مختصات ( z = -cubeWidth ) قرار دارد. هر نقطه روی این سطح با کاراکتر
- سطح 2 (راست):
این خط مسئول رسم سطح سمت راست مکعب است که در مختصات ( x = cubeWidth ) قرار دارد. این سطح با کاراکتر
- سطح 3 (چپ):
این خط مسئول رسم سطح سمت چپ مکعب است که در مختصات ( x = -cubeWidth ) قرار دارد و با کاراکتر
- سطح 4 (پشت):
این خط مسئول رسم سطح پشت مکعب است که در مختصات ( z = cubeWidth ) قرار دارد و با کاراکتر
- سطح 5 (بالا):
این خط مسئول رسم سطح بالای مکعب است که در مختصات ( y = -cubeWidth ) قرار دارد و با کاراکتر
- سطح 6 (پایین):
این خط مسئول رسم سطح پایین مکعب است که در مختصات ( y = cubeWidth ) قرار دارد و با کاراکتر
هدف:
این حلقهها برای رندر کردن و نمایش هر شش سطح مکعب استفاده میشوند. با این کار مکعب سهبعدی بهصورت چرخان در صفحهنمایش دوبعدی ASCII نمایش داده میشود.
calculateForSurface فراخوانی میشود تا مختصات دوبعدی آن نقطه روی صفحهنمایش محاسبه و نمایش داده شود.توضیحات کلی:
- حلقههای تو در تو: این حلقهها کل سطح مکعب را نقطه به نقطه بررسی میکنند و برای هر نقطه مختصات سهبعدی آن را به مختصات دوبعدی تبدیل میکنند.
- کاراکترهای مختلف برای سطوح مکعب: هر سطح مکعب با یک کاراکتر ASCII متفاوت رسم میشود تا بتوانید هر سطح را به وضوح از دیگر سطوح تشخیص دهید.
- تابع calculateForSurface: این تابع مختصات دوبعدی نقطهای از سطح مکعب را محاسبه میکند و در صورت برآورده شدن شرایط (مثل عمق)، آن را روی صفحهنمایش قرار میدهد.
جزئیات هر خط:
1. حلقههای تو در تو:
for (float cubeX = -cubeWidth; cubeX < cubeWidth; cubeX += incrementSpeed) {
for (float cubeY = -cubeWidth; cubeY < cubeWidth; cubeY += incrementSpeed) {
- این دو حلقه مختصات نقاط مختلفی را روی سطوح مکعب بررسی میکنند.
- متغیر cubeX و cubeY به ترتیب نقاطی را در طول محورهای ( x ) و ( y ) روی سطحهای مختلف مکعب تکرار میکنند.
- حلقهها از مقدار -cubeWidth تا +cubeWidth برای هر دو متغیر تکرار میشوند. این یعنی کل سطح مکعب با در نظر گرفتن cubeWidth به عنوان اندازه هر ضلع پیمایش میشود.
- incrementSpeed: میزان تغییرات ( x ) و ( y ) در هر تکرار، که تعیین میکند نقاط با چه فاصلهای از هم بررسی شوند.
2. فراخوانی calculateForSurface برای هر سطح مکعب:
این تابع برای هر سطح مکعب ۶ بار برای نقاط مختلف فراخوانی میشود تا همهی شش سطح مکعب رسم شوند:
- سطح 1 (جلو):
calculateForSurface(cubeX, cubeY, -cubeWidth, '@'); // Side 1
این خط مسئول رسم سطح جلویی مکعب است که در مختصات ( z = -cubeWidth ) قرار دارد. هر نقطه روی این سطح با کاراکتر
@ رسم میشود.- سطح 2 (راست):
calculateForSurface(cubeWidth, cubeY, cubeX, '$'); // Side 2
این خط مسئول رسم سطح سمت راست مکعب است که در مختصات ( x = cubeWidth ) قرار دارد. این سطح با کاراکتر
$ نمایش داده میشود.- سطح 3 (چپ):
calculateForSurface(-cubeWidth, cubeY, -cubeX, '~'); // Side 3
این خط مسئول رسم سطح سمت چپ مکعب است که در مختصات ( x = -cubeWidth ) قرار دارد و با کاراکتر
~ نمایش داده میشود.- سطح 4 (پشت):
calculateForSurface(-cubeX, cubeY, cubeWidth, '#'); // Side 4
این خط مسئول رسم سطح پشت مکعب است که در مختصات ( z = cubeWidth ) قرار دارد و با کاراکتر
# نمایش داده میشود.- سطح 5 (بالا):
calculateForSurface(cubeX, -cubeWidth, -cubeY, ';'); // Side 5
این خط مسئول رسم سطح بالای مکعب است که در مختصات ( y = -cubeWidth ) قرار دارد و با کاراکتر
; نمایش داده میشود.- سطح 6 (پایین):
calculateForSurface(cubeX, cubeWidth, cubeY, '+'); // Side 6
این خط مسئول رسم سطح پایین مکعب است که در مختصات ( y = cubeWidth ) قرار دارد و با کاراکتر
+ نمایش داده میشود.هدف:
این حلقهها برای رندر کردن و نمایش هر شش سطح مکعب استفاده میشوند. با این کار مکعب سهبعدی بهصورت چرخان در صفحهنمایش دوبعدی ASCII نمایش داده میشود.
for (float cubeX = -cubeWidth; cubeX < cubeWidth; cubeX += incrementSpeed) {
for (float cubeY = -cubeWidth; cubeY < cubeWidth; cubeY += incrementSpeed) {
calculateForSurface(cubeX, cubeY, -cubeWidth, '@'); // Side 1
calculateForSurface(cubeWidth, cubeY, cubeX, '$'); // Side 2
calculateForSurface(-cubeWidth, cubeY, -cubeX, '~'); // Side 3
calculateForSurface(-cubeX, cubeY, cubeWidth, '#'); // Side 4
calculateForSurface(cubeX, -cubeWidth, -cubeY, ';'); // Side 5
calculateForSurface(cubeX, cubeWidth, cubeY, '+'); // Side 6
}
}x1b[H یک کد کنترلی ANSI است که نشاندهندهی حرکت مکاننما (cursor) به بالای صفحهنمایش است.
x1b برابر با کاراکتر Escape (ESC) است.
[H دستور حرکت مکاننما به خانهی اول (بالا سمت چپ) صفحه است.
این بخش کد باعث میشود مکاننما در هر فریم به موقعیت شروع صفحه بازگردد تا محتوای جدید به جای اینکه زیر محتوای قبلی چاپ شود، از بالا دوباره چاپ گردد. این کار برای ایجاد توهم انیمیشن ضروری است، زیرا هر فریم جدید به جای پاک کردن صفحه و دوباره چاپ کردن، کل صفحه را دوبارهنویسی میکند.
x1b برابر با کاراکتر Escape (ESC) است.
[H دستور حرکت مکاننما به خانهی اول (بالا سمت چپ) صفحه است.
این بخش کد باعث میشود مکاننما در هر فریم به موقعیت شروع صفحه بازگردد تا محتوای جدید به جای اینکه زیر محتوای قبلی چاپ شود، از بالا دوباره چاپ گردد. این کار برای ایجاد توهم انیمیشن ضروری است، زیرا هر فریم جدید به جای پاک کردن صفحه و دوباره چاپ کردن، کل صفحه را دوبارهنویسی میکند.
printf("\x1b[H");
for (int k = 0; k < width * height; k++) {
putchar(k % width ? buffer[k] : 10);
}