بایگانی برچسب‌ها: برنامه نویسی اسکریپتی

به روز رسانی اوبونتو از نسخه های LTS به STS

توزیع اوبونتو، معمولا در دونسخه ارائه میشه. نسخه های «پشتیبانی طولانی مدت» یا همون LTS (مخفف Long Term Support ) که اگر اشتباه نکنم هر کدوم تا پنج سال، پشتیبانی دریافت میکنند. این پشتیبانی به معنای پشتیبانی از سمت کنونیکال (شرکت سازنده این توزیع)، دریافت آپدیت های امنیتی و همچنین به روز شدن مستندات توزیع است.

نسخه های STS که طبق روتین ارائه اوبونتو هر شش ماه یه بار میان، قبلا دو سال پشتیبانی می‌شدند ولی مثل این که الان این پشتیبانی کمتر شده و همون شش ماه (یا یک سال، دقیقا نمیدونم و یادم نیست) پشتیبانی رو دریافت میکنن. این نسخه ها به قول معروف «روی لبه تکنولوژی حرکت میکنند» و معمولا تکنولوژی های جدیدی رو در خودشون جای دادن.

هر کدوم از این نسخه ها، مزایای خودش رو داره. خیلی از افراد رو دیدم که با هر آپدیتی، سریعا سیستم عامل خودشون رو آپدیت میکنند و خیلی ها هم ترجیح میدند دو سال یک بار، نسخه های LTS رو آپدیت کنند و یا حتی کل پنج سالی که برای LTS ها پشتیبانی در نظر گرفته شده، روی اون بمونن. اما برگردیم به دسته اول!

فرض کنیم شما آخرین اوبونتوی LTS (در حال حاضر ۱۸.۰۴ ) رو نصب کردید و میخواهید به STS جدید (در حال حاضر ۱۹.۰۴) به‌روز رسانی کنید. برای این کار، نیاز به چند مرحله داریم. اول لازمه که update-manager رو نصب کنیم :

sudo apt install update-manager-core

و البته معمولا این بسته روی اوبونتو نصب شده. فقط در صورتی که نصب نباشه، این دستور نصبش میکنه. نصب هم باشه یا به شما میگه که آخرین نسخه رو نصب کردید یا به روز رسانی میکنه.

گام دوم، اینه که به آپدیت منیجر، بگیم که به جای lts در نسخه های normal برامون دنبال ریلیز جدید بگرده. فقط کافیه این فایل رو با یک ویرایشگر متن باز کنیم (البته ترجیحا ویرایشگرهای خط فرمان؛ چون دسترسی ریشه نیاز داریم) :

/etc/update-manager/release-upgrades

سپس در این فایل، شما احتمالا این خط رو می‌بینید :

Prompt=lts

با تغییر مقدار متغیر prompt به normal ، شما به آپدیت منیجر گفتید که در نسخه های STS به دنبال ریلیز جدید بگرده. بعد از این که عبارت lts رو با normal جایگزین کردید، کافیه فایل رو ذخیره کرده، ببندید و در ترمینال تایپ کنید :

do-release-upgrade

و جایی هم نیاز به پسورد داشته باشید، این دستور ازتون دریافتش خواهد کرد.

این راه حلی بود که خودم دقیقا استفاده کردم برای آپدیت به ۱۹.۰۴. نمیدونم قبلتر کسی در وب فارسی توضیحش داده یا نه، ولی خب امیدوارم که به کارتون بیاد 🙂

Share

ساختن کنترلر دو بعدی برای بازی های RPG در یونیتی

مدتی میشه که یکی از اسباب بازی های جدیدم، یعنی موتور بازی‌سازی یونیتی رو با جدیت بیشتری دارم دنبال میکنم و چیزای جالبی هم ازش یاد گرفتم. همینطور باعث هم شده دوباره کمی کد بزنم و این داستانها.

یکی از سبکهای مورد علاقه من در بازی‌سازی، سبک Role Playing عه که در این سبک، شما در واقع نقش ایفا می‌کنید، نقش هایی که به شما محول شده و یا این که شما هم میتونید در شکل‌گیری نقش دخیل باشید. بازی‌هایی مثل Elder Scrolls از این دست بازی ها هستند. چندی پیش، با یک ابزار آشنا شدم به اسم RPG Maker که به شما اجازه ساخت این دست بازی ها رو بدون کد زدن میده. اما یک مساله مهمی که احتمالا باهاش روبرو خواهید شد، اینه که این ابزار شدیدا محدوده و به سختی میشه شخصی‌سازیش کرد. به همین خاطر، سعی کردم دنبال این برم که یاد بگیرم چطور یک RPG دو بعدی ساده رو بسازم (حتی شده در حد کنترل کرکتر اصلی!).

نتیجه این شد که یک سری ویدئو دیدم و رفرنسهای برنامه نویسی یونیتی رو چند بار مطالعه کردم و تونستم چنین چیزی بسازم :

نوشتن چنین کدی کار سختی نیست اما کمی دقت لازم داره. به همین خاطر، چندین ساعت درگیرش شدم و در نهایت تونستم اونطوری که دلم میخواد، بسازمش. تمام مراحل طراحی کرکتر، طراحی صحنه، کد زدن و … رو خودم انجام دادم تا ببینم چقدر در جوانب مختلفش، توانایی دارم. خوشبختانه نتیجه خیلی هم بد نشد.

برنامه نویسی

برای کنترل کردن کرکترها در بازی، نیاز به کدی داریم که بتونه دیتا رو از کی‌برد، ماوس، صفحه لمسی و … دریافت کنه و حرکتی که مد نظر داریم رو برای ما، انجام بده. این حرکت میتونه صرفا جابجایی باشه، میتونه هم حرکت و انیمیشن با هم باشه. برای این که کد کامل باشه و بازی حرفه‌ای به نظر برسه، بهتره که انیمیشن هم لحاظ کنیم.

کدی که من نوشتم به این شکله :

using System.Collections;
using System.Collections.Generic;
using UnityEngine;

public class PlayerController : Entity {

    private Animator anim; 

	// Use this for initialization
	void Start () {
        anim = GetComponent<Animator>(); 
	}
	
	// Update is called once per frame
	void Update () {
		if(Input.GetKey(KeyCode.W) || Input.GetKey(KeyCode.UpArrow)){
			GetComponent<Rigidbody2D>().transform.position += Vector3.up * speed * Time.deltaTime; 
		}
		if(Input.GetKey(KeyCode.S) || Input.GetKey(KeyCode.DownArrow) )
        {
			GetComponent<Rigidbody2D>().transform.position += Vector3.down * speed *Time.deltaTime; 
		}
		if(Input.GetKey(KeyCode.A) || Input.GetKey(KeyCode.LeftArrow) )
        {
			GetComponent<Rigidbody2D>().transform.position += Vector3.left * speed * Time.deltaTime; 
		}
		if(Input.GetKey(KeyCode.D) || Input.GetKey(KeyCode.RightArrow) )
        {
			GetComponent<Rigidbody2D>().transform.position += Vector3.right * speed * Time.deltaTime; 
		}

        anim.SetFloat("MoveX", Input.GetAxis("Horizontal"));
        anim.SetFloat("MoveY", Input.GetAxis("Vertical")); 
	}
}<span id="mce_marker" data-mce-type="bookmark" data-mce-fragment="1">​</span>

این کد نشون میده که کلاس PlayerController از کلاس دیگری به اسم Entity داره ارث بری میکنه. تنها چیزی که در Entity تعریف شده، یک متغیر برای سرعت کرکتره. البته، سایر ویژگی هایی که نیاز داریم تا در تمام کرکترها (چه Player و چه NPC ) به کار ببریم رو میتونیم در Entity بگنجونیم.

در Update اومدیم بهش گفتیم که اگر ورودی از کلیدهای خاصی بوده، با سرعت مشخصی در جهتهای مشخص، حرکت کنه. متغیر speed هم یک متغیر public بوده که در Entity تعریف کردیم. در انتها هم گفتیم که دو متغیر ممیز شناور برای حرکت در محور X و Y نیاز داریم که با Animator Controller هماهنگ باشن. این میشه کل چیزی که در متد Update داریم.

در متد اول، یعنی Setup هم صرفا به کد گفتیم که انیماتور رو از خود شیء Player بخونه و لود کنه. پس ما نیاز داریم که خودمون یک انیماتور براش بسازیم.

چطور این کد رو آزمایش کنیم؟

آزمایش کردن این کد، هیچ کاری نداره. چون کل انیمیشن و … رو در گیتهاب قرار دادم (لینک) و میتونید از گیتهاب دانلودش کرده و تست کنید. به زودی هم، این ابزار رو به صورت یک prefab برای یونیتی منتشر میکنم که بتونید مستقیما از همین دیزاین و انیمیشن، بدون چسبوندنشون به هم، استفاده کنید.

موفق باشید 🙂

Share

صداگذاری بازی کامپیوتری در یونیتی – بخش دوم

در بخش گذشته؛ با نحوه صداگذاری و ورود به Trigger و همچنین اضافه کردن موسیقی متن به بازی، آشنا شدیم. در این بخش میخوایم کمی پا رو فراتر بذاریم و Dynamic Soundscape رو هم یاد بگیریم. فقط قبل از اون باید کمی مفاهیم آهنگسازی/صداگذاری رو با هم مرور کنیم.

مفهوم Soundscape

فضاهایی که توسط صدا ساخته میشن، یا بهتر بگم؛ صدایی که باعث میشه فضایی خاص به ذهن ما بیاد رو بهش میگن Soundscape. مفهوم پیچیده‌ای نیست ولی میتونه به پیچیده شدن سایر مفاهیم یا حتی هموار تر شدن فهمشون، کمک کنه.

در تصویر بالا، چند Soundscape رو مشاهده میکنیم. یکی برای موج، یکی برای باد، یکی برای پرندگان و … . اما آیا همیشه Soundscape ها، صداهای محیطی (Ambient ) هستند؟ خیر. بعضی وقتا هم قطعات کوتاه و کوچک موسیقی هستند که به ما در درک شرایط کمک میکنن (برای اهل فنش : مثلا یه ویولن ترمولو که یه آرپژ مینور رو بزنه، میتونه کمی ترس یا نگرانی رو القاء کنه). پس، ما نیاز به Soundscaping داریم که بتونیم با صداها؛ حس القاء کنیم.

مفهوم Dynamic Soundscape

خب اینجا کمی مفهوم میتونه پیچیده باشه، اصلا چرا میگیم داینامیک؟ مشخصه، چون قرار نیست همیشه یکسان باشه. پس به چه دردی میخوره؟ فکر کنید در بازی شما صحنه‌ای وجود داره که قراره صدای آب پخش بشه، پس باید با نزدیک شدن به آب، صدای آب کم کم بلند بشه و به گوش برسه، و وقتی کارمون با اون مرحله تموم شد، صدای آب قطع بشه. این رو بهش میگیم Dynamic Soundscape . در یونیتی به سادگی میتونیم این مفهوم رو پیاده کنیم .

مفاهیم مورد نیاز در یونیتی

مفهوم Audio Mixer

میکسر، مفهومش تقریبا همه جا یکیه، پس اگر با Reaper, FL Studio, Studio One و نرم افزارهای آهنگسازی دیگر (هزاران نرم افزار دیگه!) کار کردید، با این مفهوم آشنایید پس این بخش رو می‌تونید ازش عبور کنید . اما به طور کل، ما از میکسر استفاده میکنیم جهت این که صداها رو به کانالهای مختلف بفرستیم. در این کانال ها میتونیم بلندی صدا، تغییراتشون و همچنین افکتهایی که نیاز داریم رو کنترل کنیم.

در یونیتی هم امکان ایجاد و مدیریت تعداد بسیار زیادی میکسر وجود داره، گذشته از اون ما میتونیم یه سری میکسرها رو Master در نظر بگیریم و یه سری دیگه رو زیرمجموعه اونا حساب کنیم. به این شکل، تقریبا میشه گفت که خود یونیتی داره به ما یه استودیوی کامل صداگذاری رو تحویل میده.

شروع پروژه

خب، اول از فولدر Assets با راست کلیک، یک Audio Mixer ایجاد کنیم و اسمش رو بذاریم Master (قراره همه میکسرهای دیگرمون زیرمجموعه این باشن) :

بعد از منوی Window گزینه Audio Mixer رو فعال میکنیم و به این شکل اون رو خواهیم دید :

حالا که یک Master داریم، دو گروه دیگه (از زیرمجموعه Groups )  ایجاد میکنیم به اسم Soundtrack و Sphere . از Soundtrack برای کنترل موسیقی متن (چطوری؟! یاد میگیریم) استفاده میکنیم و از Sphere برای کنترل موسیقی که کنار Sphere ما پخش میشه.

حالا میریم سراغ دوربینمون و Audio Source ای که بهش اضافه کردیم ، یک گزینه Output داریم، اون رو روی Soundtrack قرار میدیم (به همین راحتی، موسیقی/صدا رو در یک کانال از میکسر فرستادیم!)

و به همین ترتیب، موسیقی که روی Sphere قرار دادیم رو هم به کانال Sphere میفرستیم.

استفاده از Snapshot ها

میکسرها قابلیتی دارن به اسم Snapshot که میتونیم وضعیتی رو از اون میکسرها، ثابت نگه داریم. در واقع انگار که عکس گرفته باشیم (از اسم مشخصه). و به کمک همین Snapshot هاست که میشه وضعیت صدا رو کنترل کرد. در ادامه، کد و روش کار رو با هم یاد میگیریم.

نوشتن اسکریپت Dynamic Soundscape

قبل از هرچیزی، اسکریپتی که در بخش قبل نوشتیم رو از Sphere حذف میکنیم و فایل صوتی رو مستقیم به Audio Source میدیم. سپس به Audio Mixer بر میگردیم و این طور تغییرش میدیم :

با اجرای بازی، الان فقط میتونیم صدای موسیقی متن رو بشنویم. پس میریم به قسمت Snapshots و روی + کلیک می‌کنیم و اسمش رو میذاریم Snap1 . سپس، اون Snapshot ستاره دار (به نوعی Master در اسنپ شاتها!) رو به این شکل تغییر میدیم :

و باز یک Snapshot جدید به اسم Snap2 ایجاد میکنیم. حالا در Asset ها یک C# Script تازه ایجاد میکنیم به اسم DynamicSoundscape . و این ها رو درونش مینویسیم :

در خط چهارم من UnityEngine.Audio رو اضافه کردم، این به این معناست که میتونم از Snapshot ها هم استفاده کنم. در خط ۷ و ۸ هم دو تا Snapshot ساختم به اسم fadeIn (برای آرام بلند شدن صدای مورد نظر) و fadeOut (برای آرام کم شدن صدا)، سپس تعریف کردم که وقتی وارد Trigger شدیم و تگمون هم Player بود، وارد fadeIn بشه و وقتی ازش خارج شدیم، وارد fadeOut . حالا این اسکریپت و دو اسنپ شاتی که ساختیم رو به Sphere میدیم :

حالا وقتشه که بازیمون رو اجرا کنیم و نتیجه رو به چشم ببینیم 🙂

نتیجه کارمون به صورت GIF به این شکله (به تغییر کانالهای میکسر دقت کنید 😀 )

مسلما این همه اون چیزی نیست که برای صداگذاری باید بدونید، ولی به نظر من مهم ترین بخشه. امیدوارم در این دو بخش، تونسته باشم به خوبی پوشش بدم مطلب رو. در آینده هم احتمالا باز مطالبی در مورد کار با یونیتی خواهم نوشت، و اینها آخرین مطالب من در یونیتی نیستن. بهرحال، امید به این که مفید بوده باشه و امید به موفقیت شما 🙂

Share

صداگذاری بازی کامپیوتری در یونیتی – بخش اول

بحث صدا و موسیقی در بازی کامپیوتری، بحث عجیب و گهگاه پرچالشیه. چرا که صداها میتونن جو و هدف بازی ما رو تعیین کنند و بهش فضای بالاتری اختصاص بدن. در این مطلب، قصد دارم بخشی از تجربیات خودم در زمینه صداگذاری (و نه آهنگسازی!) در بازی های کامپیوتری رو با شما به اشتراک بذارم. در این مطلب، چیزی که بررسی میکنیم : ۱. قرار دادن موسیقی متن بازی و ۲. پخش صدا در Trigger های خاص خواهد بود. پس در ادامه با من باشید 🙂

قرار دادن موسیقی متن بازی

اول یک پروژه به اسم Audio Test درست میکنیم، سپس وارد Scene اصلی میشیم تا این صفحه یونیتی رو ببینیم :

حالا باید دو کار انجام بدیم، از Asset های پیشفرض، یک First Person Controller برداریم و Main Camera رو هم پاک کنیم. ضمن این که لازمه حتما یک «زمین بازی» بسازیم. بعد از این کارها Scene من این شکلی شد :

وقتی روی FPSController کلیک کنیم و اولین زیرمجموعه‌ش رو در Inspector ببینیم با این صحنه مواجه میشیم :

همونطور که می‌بینید، در این Inspector ما عنصری به اسم Audio Listener داریم. Audio Listener کارش «شنیدن صدا»ست و روی دوربین سوار میشه. کاراکتر اول شخص هم معمولا همراه خودش یک دوربین داره، پس خیالمون از بابت «شنیده شدن» صدا، راحته. حالا روی Add Component کلیک می‌کنیم و یک Audio Source بهش اضافه میکنیم و سپس، موسیقی متن مورد نظر رو به عنوان Audio Clip بهش معرفی می‌کنیم (در اینجا دوئت پیانو و ویولن که چند وقت پیش ساخته بودم رو معرفی کردم) و تیک Loop هم میزنیم :

(البته اینجا تیک Loop رو نزدم) و حالا تبریک! موسیقی متن بازی شما نشست روی بازی. ولی این همه ماجرا نیست. ماجرا در کل خیلی پیچیده تر میشه ولی این اولین چیزیه که ما باید یاد میگرفتیم (مثلا بعدها در مورد این که چطور موسیقی داینامیک استفاده کنیم و … هم بحث خواهد شد).

حالا که این رو یاد گرفتیم، بریم سراغ اضافه کردن یک لایه صدا که در یک Trigger خاص قرار می‌گیره.

ساخت Trigger های صدا

در Scene یک Sphere میسازیم، یک متریال دلخواه بهش میدیم، یک Collider از نوع Trigger براش تعریف می‌کنیم و نتیجه میشه این :

خب، محتوای Inspector باید مثل این باشه (البته الزامی نیست، صرفا خواستیم که محدوده Collider مشخص باشه). الان کاری که باید بکنیم، اینه که یک Audio Source و یک Script به این Sphere اضافه کنیم (زبان اسکریپت رو سی‌شارپ تعیین کنید). حالا کافیه در اسکریپتمون چنین چیزی بنویسیم :

این اسکریپت، میگه که «اگر چیزی وارد Collider من شد و تگ Player داشت، کلیپی که معرفی شده رو یک بار پخش کن». پس به Inspector باید بریم و برای FPSController مون، یک تگ Player تعریف کنیم. سپس، به Script (و نه Audio Source ) باید یک Clip اختصاص بدیم، به این شکل :

و خب کار تموم شد! این فایل صوتی هم با ورود ما به Trigger تعریف شده، پخش خواهد شد!

چه چیزهایی مونده که هنوز باید یاد گرفت؟

موضوعی که اینجا بهش پرداخته شد خیلی خیلی سطحی بود. برای کار صدا در یونیتی، هم باید با Audio Mixer کار کنیم هم Audio Mixer Snapshot . گذشته از اون، باید با اسکریپت؛ اینها رو به هم مرتبط کنیم، به شکلی که یه جا موسیقی آروم قراره پخش بشه و بعد موسیقی یک صحنه خوفناک وارد بشه و … . سعی می‌کنم در قسمت (های) بعد، این موارد رو هم پوشش بدم.

موفق باشید 🙂

Share

امنیت حسابهای اجتماعی

امروز صبح در تلگرام پیامی برای من فوروارد شد که حاوی یک اسکرین شات از توییت خود شرکت توییتر بود. این اسکرین شات :

همونطوری که می‌بینید، توییتر میگه یک باگ پیدا کردن که باعث شده یک سری پسوردها، بدون این که ماسک بشن، لاگ شدن. یعنی چی؟

فرض کنیم ما یک پسورد میسازیم، پسورد ما موقعی که داریم وارد میکنیم یک چیزی مثل MySecurePassword@123456 عه. این پسورد تقریبا تمام فاکتورهای یک پسورد امن رو داره. ولی اگر به صورت Plain Text بخوایم ذخیره‌ش کنیم این که جای خود، یک میلیون کارکتر دیگر هم داشته باشه احتمال لو رفتنش بسیار بالاست. (داخل پرانتز عرض کنم خدمت آقای علیرضا شیرازی، مدیریت محترم بلاگفا که تا چند سال پیش هم همینطوری پسورد ها رو نگهداری میکرد، جای این که در توییتر و … ملت رو بخاطر مواخذه کردنتون بلاک کنید، پاسخ میدادید که چرا اینطور بود! چون همون موقع هم بسیاری از اسکریپت های مدیریت محتوا پسوردها رو ماسک می‌کردن!).
حالا بخوایم MySecurePassword@123456 رو در دیتابیسی ذخیره کنیم باید چه کنیم؟ باید از «هش» و الگوریتم های مربوطه استفاده کنیم. مثلا الگوریتم MD5 (لینک جهت مطالعه). حالا این عبارت نسبتا سخت رو من با کمک ابزارهایی که دم دستم بود به MD5 هش میکنم و نتیجه میشه :

23b7618b2a23e171e6cda057a9736423

و وقتی من پسورد رو وارد کنم، اسکریپتی که برای لاگین نوشتم، یا API ای که وظیفه لاگین کردن من رو برعهده میگیره، اول پسورد رو هش میکنه بعد در دیتابیسش چک میکنه و اگر هش یکی بود، اجازه میده من به سیستم دسترسی داشته باشم. برای مثال این یک سیستم لاگین بسیار ساده بود که خودم نوشته بودم :

کد   
post '/welcome' do
 begin 
  params[:user][:password] == params[:user][:password_again]
  user = User.create(:username => params[:user][:username], :password => Digest::MD5.hexdigest(params[:user][:password]))
  redirect to("/welcome")
 rescue
  redirect to("/signup_error")
 end
end

و این یعنی ذخیره ایمن پسورد در یک دیتابیس (در اینجا از دیتابیس های مونگو استفاده کردم). و حالا اگر اون قسمتی که مربوط به هش کردن پسورد نمیشد رو، در کد قرار میدادم چه میشد؟ وقتی قرار بود Query بزنم مثلا به یوزر mamad و پسوردش 1125 بود، اینطور بر میگردوند :

کد   
{
"username":"mamad", 
"password":"1125"
}

و مثلا اگر شما قرار بود با API ای که من برای عضوگیری سرویس نوشتم کار کنید (مثلا لاگین کردن به وسیله سرویس من در اپلیکیشن، بازی یا سیستم حضور غیاب و … )، پسوردها رو به سادگی میتونستید ببینید. اما چیزی که الان بر میگرده اینه :

کد   
{"username":"mamad","password":"c21002f464c5fc5bee3b98ced83963b8"}

و خب شما نمیتونید به پسورد دسترسی پیدا کنید، مگر این که ابزار یا دیکشنری مربوط به شکستن این الگوریتم رو داشته باشید. البته معمول هم نیست شما JSON مربوط به اطلاعات کاربران رو برگردونید! چون باز هم دیتای کاربر به خطر میفته.

فکر کنم به قدر کافی در مورد پسورد و نحوه ذخیره سازیش توضیح داده باشم، هدف این بود که مباحثی مربوط به هک شدن و نفوذ به تلگرام هم در این پست مطرح کنم که متاسفانه این پست بیش از چیزی که فکر کردم، طولانی شد. پس در مورد تلگرام در پست جداگانه ای خواهم نوشت 🙂

 

Share

مرگ وبلاگ نویسی، گشت و گذاری در سرویس های وبلاگ فارسی

شاید حدود ۱۰ سال پیش، وقتی به تازگی وارد ۱۲ سالگی شده بودم، شروع به ساخت وبلاگ در یکی از قدیمی ترین سرویس های وبلاگدهی فارسی، یعنی بلاگفا کردم. بلاگفایی که تا همین یکی دو سال پیش، به معنای واقعی از پرترافیک ترین وبسایت های فارسی به شمار میرفت.
دقیقا همان روزها، بلاگفا در صفحه اصلیش، دست کم دو تبلیغ نشان میداد، اخبارش و وبلاگ های بروز شده را لیست می‌کرد و گهگاه در شکل خبرهای فوری، امکانات حذف یا اضافه شده به سیستمش رو اطلاع رسانی می‌کرد. به این شکل مثلا فهمیدیم که مدتی blogfa.ir هم در دسترسه، و هر وبلاگی که شما بسازید هم در زیردامنه blogfa.com و هم blogfa.ir قرار میگیره.
البته، آن روزها پرشین بلاگ (قدیمی ترین سیستم بلاگدهی فارسی) و بلاگ اسکای و … هم رونق زیادی داشتند. در واقع، هرکس که میتونست هزینه های یک سرویس بلاگدهی (بخاطر سرور و منابع بالایی که نیاز داره و … ) رو تامین کنه و دانشی از برنامه نویسی وب داشت، یک سیستم بلاگدهی بالا میاورد. اما اونهایی که خیلی مطرح بودند، همین بلاگفا و بلاگ اسکای و پرشین بلاگ بودند.
دوستانی هم بودند که ترجیح میدادند – علیرغم فیلترینگ – از سرویس هایی مثل وردپرس یا بلاگر استفاده کنند، و ما هم با سختی و زحمت هایی که اون زمان برای عبور از سد داشتیم، وبلاگ ها رو میخوندیم و گهگداری هم اینتراکشنی داشتیم.

اما الان چه بلایی سر بلاگ ها اومده؟ امروز بعد از چند سال صفحه اصلی بلاگفا رو باز کردم! دیدم دیگه خبری از اخبار و لیست بلاگهای بروز شده نیست، همه‌ش شده لینک در صفحه اصلی، و صفحه اصلی صرفا شده یه محل برای لاگین کردن وبلاگ نویس ها!
لیست وبلاگ های بروز شده رو باز کردم و یکی دو تا وبلاگ رو خوندم، یکیشون دقیقا همین دهم آبان ویرایش شده بود و یکی هم حدود سه روز پیش. قبلا، این بروزرسانی ها، ساعتی بود. مثلا الان لیست رو میخوندیم، میدیدیم که در ۴ ساعت گذشته دست کم ۱۰ وبلاگ بروزرسانی شدند، اما الان این اختلافها به روز رسیدند!

گرچه، دلیل «مرگ وبلاگ نویسی» مشخصه، دیگه کسی نمیره از بلاگفا سرویس بگیره و بلاگ بنویسه، معمولا یه کانال تلگرامی میزنن و حرفاشون رو اونجا میزنن، دریغ از این که نمیدونن موندگار نیست، حداقل اونقدری که وبلاگ های روی بلاگفا هستند!

Share

آغاز به یادگیری هوش مصنوعی

در پست قبلی وبلاگ، در مورد چیستی هوش مصنوعی توضیح دادم. در این یکی پست، قصدم اینه که به شما بگم برای یادگیری هوش مصنوعی لازمه چه چیزهایی بلد باشیم و چه چیزهایی رو در طول زمان یاد میگیریم. خب، پس بریم سراغ این که برای هوش مصنوعی چه پیش‌نیازی لازمه، بعد کم کم بریم سراغ سیر یادگیری و … .

  • الگوریتم:
    این که بتونید برای یک برنامه، یک الگوریتم بهینه پیدا کنید یا پیشنهاد بدید، مهم ترین عامل در یادگیری و انجام پروژه های هوش مصنوعی به حساب میاد. اگرچه این مورد، همه جا کاربرد داره و کلا برای برنامه نویس و دولپر خوب شدن لازمش داریم؛ ولی اینجا لازمه که به الگوریتم و الفبای موضوع مسلط باشیم. پس، باید یاد بگیریم که چطور با استفاده از الگوریتم ها یک برنامه بسازیم. خب برای یادگیری الگوریتم (اگر بلد نیستید) پیشنهاد من کتاب CLRS هست. هم ترجمه این کتاب در بازار موجوده و هم زبان اصلیش در اینترنت هست.
  • برنامه نویسی :
    برای این که بتونید پروژه هوش مصنوعی انجام بدید باید برنامه نویسی بلد باشید؛ بهرحال بخشی از کامپیوتره و نمیشه ازش در رفت. گرچه ممکنه شما صرفا ایده پردازی یک پروژه هوش مصنوعی رو انجام داده باشید ولی موضوع مهم اینه که شما بتونید همون ایده رو هم چندین بار تست کنید و بعد ارائه‌ش کنید به یک تیم. پس، برنامه نویسی بلد بودن هم از شرایط یادگیری و انجام پروژه در هوش مصنوعی هست. پیشنهاد من هم برای یادگیری زبان، پایتونه که الان تبدیل شده به ابزار شماره یک پروژه های هوش مصنوعی.
  • علوم شناختی :
    علوم شناختی یا Cognitive Science ترکیبیه از روانشناسی، فلسفه ذهن، زیست شناسی مغز و علوم کامپیوتر. البته انقدر ها هم خلاصه نیست و من دارم انقدر خلاصه میگم. برای این که بتونیم پروژه های هوش مصنوعی بزنیم؛ لازم داریم که بلد باشیمش. گرچه طوریه که در حین یادگیری هوش مصنوعی هم، این موضوع رو یاد میگیریم. خیلی از ایده ها و … که در هوش مصنوعی (به ویژه شبکه های عصبی مصنوعی) مطرح شده، حاصل کار دانشمندان شناختی بوده.

شبکه عصبی مصنوعی

شبکه عصبی مصنوعی

 

  • با مغز انسان آشنا بشید!
    این مورد از مهم ترین مواردی هست که باید به عنوان کسی که کار هوش مصنوعی میکنه، بلد باشیم. کاری که ما میخوایم بکنیم این هست که یک سری اعمال انسانی مثل تفکر، تصمیم گیری و یادگیری رو برای ماشین پیاده سازی کنیم و ماشین ما قراره فکر کنه برای ما. پس، بهتره که ساختار مغز رو بشناسیم و باهاش آشنا بشیم. در این زمینه هم کتاب و رفرنس زیاد داریم.
  • از منابع مختلف استفاده کنید!!!
    و در آخر هم، استفاده از منابع متعدد مثل یوتوب، وبسایت های هوش مصنوعی و کتابها توصیه میشه. به این شکل شما میتونید به راحتی و بدون هیچ مشکلی، هوش مصنوعی یاد بگیرید و از انجام پروژه های هوش لذت ببرید.
Share

پروژه گاه‌شمار

خب، من در گروه های تلگرامی این پیام رو میذاشتم :

دوستی مدتی پیش (که خیلی هم ازش نگذشته ) یک چالش رو بعنوان تمرین برنامه نویسی پیشنهاد داد، و اون هم نوشتن یک API بود برای دریافت ساعت و تاریخ.
من هم وارد این چالش شدم و یک API با روبی و سیناترا نوشتم، روی گیتهاب هم قرارش دادم ولی الان دپلویش کردم که اگر شما هم خواستید بتونید ازش استفاده کنید :
https://gahshomar-api.herokuapp.com/

خب، این هم پروژه ای بود که محسن بعنوان تمرین خواست که ما یه API بنویسیم، من هم این رو با Sinatra نوشتم و الان دپلوی شده و در دسترسه! امیدوارم ازش لذت ببرید 🙂

Share

زبان ماشین، رمزگشای دستور العمل

در پست های گذشته بسیار بسیار در مورد زبان ماشین و اسمبلی بحث کردیم، اما این بار میخوایم بررسی کنیم که یک دستور، چطور کار میکنه. برای این کار، ما از ساده ترین دستورات استفاده میکنیم. قبل از اون، باید ببینیم که چه اتفاقی میفته که دستورات ما، شناسایی میشن! پس میایم و دستوراتمون رو بررسی میکنیم.

یک دستور در ماشین چطور خونده میشه؟

این خیلی مهمه که بدونیم یک دستور به چه شکلی خونده میشه. بسیار خوب، دستور زیر رو در نظر بگیرید :

کد   
MOV AX, 0

 

این دستور ماشین کد به این شکل داره :

کد   
B8 0000

 

که البته این ماشین کد، یک ماشین کد هگزادسیمال هست. اون چهار صفری که داریم که مقداری هست که خواستیم توی AX قرار بدیم و باهاش کاری نداریم، ولی B8 ما ، همون دستوریه که لازمه رمزگشایی شه و به صورت دو دویی به این شکل در میاد :

کد   
1011 1000

 

خب ما یک «دیکدر» (که یک مدار متشکل از n ورودی و دو به توان n خروجی هست) داریم، که این اعداد رو به ترتیب روشن و خاموش میکنه، و به این شکله که ما به  دستور میرسیم. در واقع مدارات مربوط به دستور رو خواهیم داشت.

بسیار خوب، حالا که میدونیم چه چیزی باعث میشه که ما بتونیم زبان ماشین رو درک کنیم، بیایم بررسی کنیم که :

زبان ماشین از چند بخش تشکیل شده؟

زبان ماشین، اول به صورت اسمبلی نوشته میشه که به زبون انسان خیلی خیلی نزدیکه. یعنی هرکس کمی انگلیسی بدونه میدونه که کلمه ای مثل ADD یعنی جمع کردن. اما، حالا مشکلی که هست اینه که وقتی «اسمبلی» به «آبجکت کد» یا همون کد هگزادسیمال تبدیل میشه رو هرکسی نمیتونه بخونه. پس راه حل چیه؟

اول باید ببینیم که یک خط آبجکت کد از چیا تشکیل میشه! بیاید این مثال رو در نظر بگیریم باز :

کد   
MOV AX, 0 ;B8 0000

 

خب اینجا من آبجکت کد رو به صورت کامنت در آوردم. دو بخش داریم، یکیش چهارتا صفر، که بهش عملوند یا Operand میگیم و دیگری «کد عملیات» یا Operation Code هست. مثلا برای انتقال به AX همیشه از B8 استفاده میشه. چرا؟ چون اینتل اینطور خواسته 😀 . بعد از این، این کد هگزادسیمال به یک کد باینری تبدیل میشه که CPU میتونه اون رو برای ما اجرا کنه.

از کجا آبجکت کد رو بخونیم؟

همه اسمبلر های موجود میتونن فایلی تولید کنن که آبجکت کد، سمبلهای به کار رفته و … رو شامل شه، و در اسمبلر MASM این فایل با پسوند LST ساخته میشه. شما میتونید با باز کردن این فایل با یک ویرایشگر متنی و خوندنش، ببینید که هر دستوری چه کدی رو داره.

یک برنامه نمونه

خب، من یک برنامه اسمبلی خیلی ساده نوشتم که اجرا کردنش هیچ خروجی ای نداره (:D ) ولی خب آبجکت کد ها تولید شده و اسمبل بدون مشکل صورت گرفته. این برنامه با آبجکت کدهاش به صورت کامنت به این شکله (بررسی دستور MOV در ۱۲ حالت مختلف) :

کد   
.MODEL SMALL
.8086
.STACK 
.DATA
.CODE
MOV AX, 0 ;B8 0000
MOV BX, 0 ;BB 0000
MOV CX, 0 ;B9 0000
MOV DX, 0 ;BA 0000
MOV AH, 0 ;B4 00
MOV BH, 0 ;B7 00
MOV CH, 0 ;B5 00
MOV DH, 0 ;B6 00
MOV AL, 0 ;B0 00
MOV BL, 0 ;B3 00
MOV CL, 0 ;B1 00
MOV DL, 0 ;B2 00
END

برای جلوگیری از ابهام هم مقداری که توی رجیسترها ریخته شده صفر هست، به این شکل کد ماشین بسیار ساده تر شده.

تا پست های بعدی، و اسمبلی بیشتر، موفق و موید و آزاد و شاد باشید! 🙂

Share

گسترش Makefile ها – استفاده از متغیر در Makefile

توی این پست بود که تصمیم گرفتم در مورد نوشتن Makefile توضیح بدم. اما قضیه نوشتن میک فایل، به اون چیزی که اونجا مطرح کردیم محدود نمیشه. میتونیم توی Makefile هامون تعدادی متغیر داشته باشیم. متغیر میتونه کامپایلرمون، ورودی ها و خروجی هاش رو مشخص کنه. حتی سوییچ هایی که برای کامپایل کردن برنامه نیاز داریم میتونیم توی Makefile قرار بدیم. بسیار خوب، خود میک یه دستور echo هم داره که میتونیم برای چاپ پیام ازش استفاده کنیم (به جای استفاده از echo بش). حالا سوال پیش میاد که چطور از این دستور ها و قابلیت ها استفاده میکنیم؟

این خط رو در نظر بگیرید :

کد   
gcc -std=c99 main.c mpc.c -ledit -lm -o main -Wincompatible-pointer-types

الان ما میتونیم هرچی که با L شروع میشه رو توی یک متغیر بریزیم، std رو هم همینطور و همچنین incompatible-pointer-types رو. اینطوری چه سودی بهمون میرسه؟ یک میک فایل تر و تمیز خواهیم داشت. پس به این شکل توی میک فایلمون درش میاریم :

کد   
CC = gcc
STD = -std=c99
LINK = -ledit -lm
FLAGS = -Wincompatible-pointer-types

الان هرچی که لازم بود رو توی متغیرهامون گذاشتیم، ولی نوع استفاده از متغیر هم مهمه. همون کد بالا رو در نظر بگیرید، حالا میایم از متغیرها استفاده میکنیم و به چنین چیزی میرسیم:

کد   
$(CC) $(STD) main.c mpc.c $(LINK) -o main $(FLAGS)

دقت کنید که پرانتز هم برای صدا زدن متغیرها لازمه. الان ما یک میک فایل تر و تمیز داریم. کل میک فایلمون به این شکل در اومده الان :

کد   
CC = gcc
STD = -std=c99
LINK = -ledit -lm
FLAGS = -Wincompatible-pointer-types
all:
	$(CC) $(STD) main.c mpc.c $(LINK) -o main $(FLAGS)
 
clean:
	rm main

خب الان میخوایم یک پیام هم چاپ کنیم و به کاربر خوش آمد بگیم، یا بگیم که صبور باشه و بعد کامپایل شدن پیام کامپایل با موفقیت رو چاپ کنه! کافیه به این فرمت چیزی که میخوایم رو بنویسیم:

کد   
@echo "Compiling proccess may take a long time, please be patient"

و به این شکل پیامتون رو هرجا که دوست داشتید قرار بدید. البته Makefile های خیلی خیلی گسترده تر هم وجود دارند که به معنای واقعی میشه گفت یک کمپانی کامپایل هستند.

امیدوارم که این پست هم مفید واقع شده باشه، چون واقعا رفرنس برای نوشتن Makefile توی اینترنت نیست.

موفق و پیروز باشید 🙂

Share