Contacts
صفحه اصلی پورتال | صفحه اصلی تالار | ثبت نام | اعضاء | گروه ها | جستجو | پرسش و پاسخ | فروشگاه الکترونیکی | خرید پستی بازی های کامپیوتری





صفحه اول انجمنها -> ساخت بازی با فریم ورک XNA -> کارگاه کوچک سیستم ذره ای دوبعدی [Particle Systems ]
 

ارسال يك موضوع جديد   پاسخ به يك موضوع ديدن موضوع قبلي :: ديدن موضوع بعدي
برو به صفحه 1, 2  بعدي

کارگاه کوچک سیستم ذره ای دوبعدی [P
نويسنده
پيغام
littledemon
در حال رشد
در حال رشد


تاريخ عضويت: جمعه 31 فروردين 1386
تعداد ارسالها: 86
محل سكونت: زیر بام کلبه ای در غرب این ملک غریب


4 شنبه 25 خرداد 1390 - 18:36
پاسخ بصورت نقل قول
با سلام . Surprised
تصمیم گرفتم تو یه کارگاه کوچیک شروع کنیم به کار بر روی سیستم های ذره ای دوبعدی.
از تعریف سیستم ذره ای شروع کنیم و هفته به هفته یا اگه شد زودتر توی کار با سیستم های ذره ای بریم جلو تا یه مرجع کوچولو برای تازه کارایی مثل خودم باشه .
مقالات جدیدی که قرار میدم رو هفته بعدش توی لیست ، pdf اش رو حاضر میکنم تا برای دوستانی که تازه میان دریافتش آسون باشه .

از دوستان هم انتظار کمک دارم ، چرا که مطالب برگرفته از ذهن خودمه و دوست دارم اساتید اشتباهاتم رو بگن تا درستشون کنم و بقیه رو دچار مشکل نکنم !
نوشتن از من ، غلط گیری و خوندن از شما Arrow


************وضعیت آماده سازی مقالات به صورت مصور**********


قسمت اول :    
قسمت دوم :    
قسمت سوم :  
قسمت چهارم :
فواره آب :        



_________________
به امید موقعیتی که لایقش باشیم !
www.MojtabaMaher.ir


0 بار اين نامه ويرايش شده است كه آخرين بار توسط شنبه 8 مرداد 1390 - 09:04 در 3 بوده است.
ارسال  بازگشت به بالا
ديدن مشخصات كاربر ارسال پيغام خصوصي ديدن وب سايت كاربر
 

نويسنده
پيغام
littledemon
در حال رشد
در حال رشد


تاريخ عضويت: جمعه 31 فروردين 1386
تعداد ارسالها: 86
محل سكونت: زیر بام کلبه ای در غرب این ملک غریب


4 شنبه 25 خرداد 1390 - 18:44
پاسخ بصورت نقل قول
به نام خدا که هر چه دارم از اوست
سری مقالات سیستم های ذره ای دو بعدی در XNA
قسمت اول : مقدمه ای بر سیستم ذره ای

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

شاید شما هم در طبیعت هنگام مشاهده بارش باران ،رخ دادن یک انفجار ، آتش و . . . به این فکر افتاده باشید که چگونه من میتوانم چنین چیزی را شبیه سازی کنم ؟
سیستم ذره ای یا Particle System به یکسری از دستورالعمل های یکپارچه گفته میشود که به ترتیب وظیفه تولید ، کنترل و از بین بردن ذراتی را دارد که تعداد ، نوع ، عمر، موقعیت و اندازه مشخصی دارند. برای این که سیستم ذره ای شکل بگیرد این اشیاء باید از حالت شی بیرون بیایند ، چرا که ما میخواهیم دیگر شی نداشته باشیم. حال سوال این است که چرا ما باید شی را از حالت خود بیرون بیاوریم و سیستم ذره ای را بوجود بیاوریم ؟
در جواب باید گفت ابتدا یک سیستم مانند آتش را در نظر بگیرید ، برای درک بهتر آتش را خرد کنید یعنی آتش تشکیل شده از ذرات بسیار ریزی که هم رنگ دارند و هم مکان (خصوصیات دیگر مورد بحث ما نیست) زمانی که ما میخواهیم یک سیستم ذره ای مثل انفجار را بوجود بیاوریم مسلما باید از تعداد زیادی ذره آتش استفاده کنیم این ذرات از مرکز وقوع انفجار تولید میشود و به اطراف پرتاب میشود و بعد از گذشت زمان مشخصی مثلا 5 ثانیه ذرات آتش به دلای معلوم با ذرات هوا ترکیب میشوند ، پس ما ابتدا حالتی مانند دود مشاهده میکنیم و بعد از آن دیگر ذرات آتش را نمی بینیم چرا که هر ذره تغییر رنگ میدهد و ما این تغییر رنگ را به شکل آتش و دود و در آخر محو شدن می بینیم . ما تا همین جای کار را فعلا نیاز داریم .


اگر متن بالا را چند بار با دقت بخوانیم میتوانیم موارد زیر را از آن استخراج کنیم :
- هر ذره آتش دارای رنگ است.
- هر ذره آتش دارای شکل است.
- هر ذره آتش دارای مکان است.
- هر ذره آتش دارای عمر است.(پس از چند ثانیه تمام ذرات ناپدید میشوند ، اصطلاحا میمیرند )
خوب پس خصوصیات اصلی ذرات را مشخص کردیم و به درک پایه ای از سیستم ذره ای پیدا کردیم.
البته باید توجه داشته باشیم که با در نظر گرفتن نوع سیستم ذره ای مورد نیازمان این خصوصیات را مشخص کنیم . مثلا در تعریف یک سیستم ذره ای برای بارش برف پارامترهایی که در نظر گرفتیم فرق میکند .با جمع بندی مطالب بالا میتوان به این نتیجه رسید که انواع سیستم ذره ای از نظر زمان کاری به شرح زیر است:
* سیستم های بر پایه شلیک
نحوه عمل این سیستم ها مانند شلیک اسلحه است،به این گونه که در زمان خاصی ، تعدادی ذره تولید شده و از بین میروند ، ممکن است این عمل ممکن است تنها یکبار انجام شود یا با فاصله زمانی مشخصی تکرار شود . یا حتی برای تولید ذرات ممکن است نیاز به تحریک چیزی مانند چاشنی داشته باشیم .برای مثال دود حاصل از شلیک یک توپ را در نظر بگیرید که به صورت مداوم در حال شلیک است ،بعد از هرچند دقیقه یک گلوله بارگذاری میشود و شلیکی انجام میشود .
* سیستم های بر پایه حلقه
نحوه عمل این سیستم ها به صورت یک حلقه مداوم است.تا زمانی که حلقه فعال است به صورت مداوم ذراتی تولید می شوند و در زمان معین از بین می روند و ذرات جدیدی جای آنها را می گیرند. مانند یک سیستم فواره آب یا آبشار که دائما در حال فعالیت هستند ، پس این حلقه میتواند بینهایت باشد یا با نهایت .

قسمت دوم: پیاده سازی ذره

طرحی که در ذهن خود آوردیم نیاز به یک پیاه سازی اولیه دارد، تا بتوان عیب هایش را رفع کرد و آن را از دید کاربر مورد بررسی قرار داد .بدین منظور اولین قدم ، پیاده سازی کلاسی به نام Particle برای تعریف ذره است تا بعدا بتوانیم با استفاده از یک موتور این ذرات را تولید کنیم.
ابتدا یک کلاس عمومی به نام Particle ایجاد کنید . سپس حوزه فعالیت کلاس را public (عمومی) تعریف کنید تا در کلاس های دیگر بتوان به راحتی از این کلاس استفاده کرد.
كد:
public class Particle

توجه داشته باشید که فضاهای نام مربوط به چارچوب Xna را برای کلاس تعریف کنید تا بتوانید از توابع آماده و بدنه اصلی xna استفاده کنید .
كد:
using Microsoft.Xna.Framework;
using Microsoft.Xna.Framework.Graphics;

حال نوبت تعریف خاصیت های کلاس رسید ، برای این کار ما تمام خصوصیات یک ذره را به صورت زیر به سیستم معرفی می کنیم .
كد:
public Texture2D Texture { get; set; }             
public Vector2 Position { get; set; }
public Vector2 Velocity { get; set; }
public float Angle { get; set; }
public float AngularVelocity { get; set; }
public Color Color { get; set; }
public float Size { get; set; }
public int TTL { get; set; }         

Texture : تصویری که کاربر به عنوان ذره می بیند . این ذره میتواند تصویر قطره آب باشد یا یک جرقه یا هر چیز دیگری که شما میخواهید.
Position:موقعیت مکانی ذره که برای حرک ذره مورد نیاز است .
Velocity :سرعت حرکت ذره ، که میتواند در حالات مختلف متفاوت باشد .مثلا در انفجار ، سرعت پاشیدن ذرات بسیار سریع است ولی در یک فواره سرعت پرتاب ذرات به هوا معمولی است .
Angle : زاویه چرخش ذره که در مواردی (آتش بازی و . . .)نیاز به تغییر آن دارید.
AngularVelocity :سرعت چرخش ذره. شاید چندان کاربردی به نظر نرسد ولی در بعضی از جلوه ها نیاز دارید تا برای زیباتر شدن نتیجه ،سرعت چرخش ذرات را زیاد کنید.
Color :رنگ ذره که یکی از خصوصیات اصلی و پر کار برد است.
Size :اندازه ذره که در بعضی جلوه ها نیاز دارید آن را تغییر دهید .(دود، انفجار و . . .)
TTL :تقریبا میتوان گفت کلیدی ترین خصوصیت هر ذره عمر آن است .همانطور که قبلا اشاره کردیم بسته به نوع سیستمی که انتخاب میکنید عمر ذرات باید متفاوت باشد .این خصوصیت مخفف کلمات
Time To Live می باشد (اصطلاحا : مدت زندگی) .

زمانی که یک ذره تولید میشود باید خصوصیات اصلی آن مقدار دهی شود اگر نه با صحنه ای فوق العاده دور از انتظار مواجه خواهیم شد . برای مثال یک فواره را در نظر بگیرید،ذرات آب از لوله فواره بیرون می آیند (لحظه تولید ذره) و به بالا پرتاب میشوندو بر اثر گرانش زمین به سمت پائین کشیده میشوند و سرانجام وارد آن حوض آب میشوند(لحظه مرگ ذره). اگر زمان تولید ذرات موقعیت مکانی آن ها مشخص نباشد .چه چیزی پیش می آید ؟ هر ذره به جای این که از لوله فواره بیرون بیاید از گوشه صفحه سر در بیاورد . این منظره جالبی نیست ! پس خصوصیات هر ذره را موقع تولید مشخص میکنیم و این کار با مقدار دهی خصوصیات در متد سازنده کلاس particle صورت میگیرد:
كد:
public Particle(Texture2D texture, Vector2 position, Vector2 velocity,
            float angle, float angularVelocity, Color color, float size, int ttl)
        {
            Texture = texture;
            Position = position;
            Velocity = velocity;
            Angle = angle;
            AngularVelocity = angularVelocity;
            Color = color;
            Size = size;
            TTL = ttl;
        }

بنابراین هر زمان که ذره ای ساخته شود بر اساس مقادیر ورودی، تمام خصوصیات آن مقدار میگیرند که مقدار دهی این خصوصیات وظیفه موتور تولید کننده ذرات است و بعدا درمورد آن بحث میکنیم.
حال نوبت متد های اصلی می رسد ، یعنی Update و Draw :
كد:
    public void Update()
        {
            TTL--;
            Position += Velocity;
            Angle += AngularVelocity;
        }


در متد Update ما موقتا کدهایی قراردادیم که بعدا با تنوع سیستم های ذره ای ممکن است مجبور ب تغییر آن ها بشویم. هر لحظه باید عمر ذره کم شود ، به سمت مشخصی و با سرعتی خاص حرکت کند و چرخشی داشته باشد که سرعت آن را نیز معین کرده ایم .
كد:

        public void Draw(SpriteBatch spriteBatch)
        {
            Rectangle sourceRectangle = new Rectangle(0, 0, Texture.Width, Texture.Height);
            Vector2 origin = new Vector2(Texture.Width / 2, Texture.Height / 2);

            spriteBatch.Draw(Texture, Position, sourceRectangle, Color,
                Angle, origin, Size, SpriteEffects.None, 0f);
        }


در متد Draw هم همانطور که پیداست ابتدا در sourceRectangle وضعیت تصویر ذره را مشخص کرده ایم . سپس با استفاده از origin نقطه ای که گردش باید دور آن انجام شود ، مشخص شده و در آخر هم که توسطspriteBatch.Draw ذره را رسم کردیم.
کد نهایی شما در کلاس Particle باید شبیه زیر باشد:

كد:
using System;
using Microsoft.Xna.Framework;
using Microsoft.Xna.Framework.Graphics;


namespace ParticleSystems{
    public class Particle
    {

        public Texture2D Texture { get; set; }         
        public Vector2 Position { get; set; }         
        public Vector2 Velocity { get; set; }           
        public float Angle { get; set; }           
        public float AngularVelocity { get; set; }     
        public Color Color { get; set; }               
        public float Size { get; set; }               
        public int TTL { get; set; }                   
        public Particle(Texture2D texture, Vector2 position, Vector2 velocity,
            float angle, float angularVelocity, Color color, float size, int ttl)
        {
            Texture = texture;
            Position = position;
            Velocity = velocity;
            Angle = angle;
            AngularVelocity = angularVelocity;
            Color = color;
            Size = size;
            TTL = ttl;
        }


        public void Update()
        {
            TTL--;
            Position += Velocity;
            Angle += AngularVelocity;
        }

        public void Draw(SpriteBatch spriteBatch)
        {
            Rectangle sourceRectangle = new Rectangle(0, 0, Texture.Width, Texture.Height);
            Vector2 origin = new Vector2(Texture.Width / 2, Texture.Height / 2);

            spriteBatch.Draw(Texture, Position, sourceRectangle, Color,
                Angle, origin, Size, SpriteEffects.None, 0f);
        }



    }
}

که البته در قسمت namespace ParticleSystems شما باید نام پروژه خود را قرار دهید .در اینجا نام پروژه ما ParticleSystems بوده است.


قسمت سوم : پیاده سازی موتور مولد
ما الان یک ذره را شبیه سازی کردیم اما آیا این برای ما میتواند در حد یک سیستم ذره ای کامل مانند باران یا آتش کار کند ؟مثل این است که ما یک قطره آب داشته باشیم و انتظارمان این باشد که بتوانیم باران از آن ایجاد کنیم .پس ما نیاز به یک موتور مولد ذره داریم ، موتوری که به صورت مداوم بتواند این ذرات را تولید کند. پس کلاس جدیدی به نام ParticleEngine ایجاد میکنیم .البته یادتان باشد که فضاهای نام زیر را قبل از نام کلاس تعریف کنید.

كد:
using System;
using System.Collections.Generic;
using Microsoft.Xna.Framework;
using Microsoft.Xna.Framework.Graphics;

کلاس را از نوع public تعریف میکنیم :
كد:

    public class ParticleEngine
    {

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

كد:
private Random random;
        public Vector2 EmitterLocation { get; set; }
        private List<Particle> particles;
        private List<Texture2D> textures;

random : استفاده این متغیر تصادفی یکی از نیاز های اصلی است چرا که ما برای هر خاصیت تصادفی مانند رنگ ، موقعیت ،سرعت و . . . به این نوع داده ها نیاز داریم.
EmitterLocation : موقعیت نقطه ای که قرار است ذرات از انجا تولید شوند .موقعیت این نقطه میتواند مطلق یا نسبی باشد به این معنا که ممکن است مثلا سیستم ذره ا شما وظیفه تولید آتش موشک جت را بر عهده داشته باشد . پس موقعیت سیستم نمی تواند یک جای ثابت باشد و مسلما باید به انتهای محفظه سوخت موشک متصل باشد که به این مورد موقعیت نسبی گوئیم یعنی نسبت به یک شی دیگر موقعیت خود را تنظیم میکند . اما مثلا گدازه هایی که از دهانه یک اتش فشان بیرون می آید دارای موقعیت مطلق است که تنها به یک نقطه ثابت اشاره میکند و آن هم دهانه آتشفشان است.

Particles : لیستی از ذراتی که باید توسط موتور تولید شوند در اینجا ذخیره میشود.

Textures : لیستی از تصاویری که باید برای ذرات استفاده گردد در اینجا ذخیره میگردد.

متد سازنده موتور مول ما هم باید چیزی شبیه زیر باشد ، البته قبلا طرز کار متد سازنده اشاره کردیم.
كد:

        public ParticleEngine(List<Texture2D> textures, Vector2 location)
        {
            EmitterLocation = location;
            this.textures = textures;
            this.particles = new List<Particle>();
            random = new Random();
        }

تقریبا تمامی خطوط واضح هستند و نیازی به توضیح نیست. البته شاید در مورد آرگومان ورودی اول یعنی textures ابهامی وجود داشته باشد که توضیحی مختصر ارائه میکنیم. زمان ساخته شدن شی موتور مولد ، لیستی از چند تصویر ذره باید به شی معرفی کنیم ، مثلا 4 تصویر مختلف از یک قطره آب را فرض کنید (بیشتر برای تنوع استفاده میشود).زمانی که لیست این 4 ذره به شی موتور مول تحویل داده شد در هربار تولید ذره ، یک تصویر تصادفی از بین 4 تصویر انتخاب میکند و در نتیجه شما تعداد از ذرات با شکل متنوع را مشاهده میکنید . و اما متد update که باید به صورت زیر پیاده سازی شود .

كد:
public void Update()
        {
            int total = 5;

            for (int i = 0; i < total; i++)
            {
                particles.Add(GenerateNewParticle());
            }

            for (int particle = 0; particle < particles.Count; particle++)
            {
                particles[particle].Update();
                if (particles[particle].TTL <= 0)
                {
                    particles.RemoveAt(particle);
                    particle--;
                }
            }
        }

به صورت کلی 2 حلقه داریم . در حلقه اول ذرات توسط تابع GenerateNewParticle تولید میشوند ، یعنی در هربار فراخوانی update حلقه اجرا شده و 5 ذره تولید میکند. حال اگر به فرض مثال متد update در هر ثانیه 30 بار صدا زده شود در هر ثانیه ما 5*30 ذره یعنی 150 ذره داریم !
تابع دوم به ازائ تمام ذرات موجود در لیست یک بار اجرا میشود و وظیفه آن صدا زدن متد update هر ذره است . در قسمت قبل اشاره کردیم که متد update یک ذره چه کاری انجام میدهد.اما فعلا جهت یادآوری باید گفت که هر بار که متد update یک ذره اجرا شود در واقع موقعیت مکانی آن تغییر میکند و مهمتر از آن از عمر ذره کم می شود . پس شرط درون حلقه چک میکند که آیا ذره فعلی عمرش تمام شده یا نه ؟ اگر عمر ذره کمتر یا برابر صفر باشد ذره از لیست حذف میشود تا دیگر پردازشی روی آن صورت نگیرد .
و اما تابع GenerateNewParticle که وظیفه ساخت یک ذره را دارد .
كد:
private Particle GenerateNewParticle()
        {
            Texture2D texture = textures[random.Next(textures.Count)];
            Vector2 position = EmitterLocation;
            Vector2 velocity = new Vector2(
                                    1f * (float)(random.NextDouble() * 2 - 1),
                                    1f * (float)(random.NextDouble() * 2 - 1));
            float angle = 0;
            float angularVelocity = 0.1f * (float)(random.NextDouble() * 2 - 1);
            Color color = new Color(255f, (float)random.NextDouble(), 0f);
            float size = (float)random.NextDouble();
            int ttl = 20 + random.Next(40);

            return new Particle(texture, position, velocity, angle, angularVelocity, color, size, ttl);
        }

این تابع ابتدا یک تصویر تصادفی از لیست تصاویر ذرات انتخاب میکند ، سپس موقعیت مکانی ذره را در جایی تنظیم میکند که موتور مولد قرار دارد پس هر ذره از جایی تولید میشود که موتور مستقر است . بعد از آن سرعت و جهت حرکت ذره را به صورت تصادفی انتخاب میکند تا هر ذره به یک سمت رها شود . در اینجا زاویه چرخش ذرات برابر صفر بوده و سرعت تغییر زاویه هم یک مقدار تصادفی تنظیم شده و در ادامه رنگ ذره هم به صورت تصادفی انتخاب میشود ، البته براساس استانداردRGB که نگاه کنیم میبینیم که مقدار B برابر صفر است به این معنا که رنگ تصادفی ما باید فاقد رنگ آبی باشد . بعد از آن اندازه ذره به صورت تصادفی انتخاب میشود و عمر ذره هم مقدار ثابت 20 به علاوه یک مقدار تصادفی بین 1 تا 40 هست و در آخر هم که ذره ای با تمام مشخصات بالا تولید میشود و به عنوان خروجی تابع باز گردانده میشود.
و اما متد draw که متد نهایی و اصلی جهت رسم ذرات است .
كد:
public void Draw(SpriteBatch spriteBatch)
        {
            spriteBatch.Begin();
            for (int index = 0; index < particles.Count; index++)
            {
                particles[index].Draw(spriteBatch);
            }
            spriteBatch.End();
        }

کد نهایی شما باید شبیه زیر باشد :

كد:

using System;
using System.Collections.Generic;
using Microsoft.Xna.Framework;
using Microsoft.Xna.Framework.Graphics;

namespace ParticleSystems{
    public class ParticleEngine
    {

        private Random random;
        public Vector2 EmitterLocation { get; set; }
        private List<Particle> particles;
        private List<Texture2D> textures;

        public ParticleEngine(List<Texture2D> textures, Vector2 location)
        {
            EmitterLocation = location;
            this.textures = textures;
            this.particles = new List<Particle>();
            random = new Random();
        }

        public void Update()
        {
            int total = 5;

            for (int i = 0; i < total; i++)
            {
                particles.Add(GenerateNewParticle());
            }

            for (int particle = 0; particle < particles.Count; particle++)
            {
                particles[particle].Update();
                if (particles[particle].TTL <= 0)
                {
                    particles.RemoveAt(particle);
                    particle--;
                }
            }
        }

        private Particle GenerateNewParticle()
        {
            Texture2D texture = textures[random.Next(textures.Count)];
            Vector2 position = EmitterLocation;
            Vector2 velocity = new Vector2(
                                    1f * (float)(random.NextDouble() * 2 - 1),
                                    1f * (float)(random.NextDouble() * 2 - 1));
            float angle = 0;
            float angularVelocity = 0.1f * (float)(random.NextDouble() * 2 - 1);
            Color color = new Color(255f, (float)random.NextDouble(), 0f);
            float size = (float)random.NextDouble();
            int ttl = 20 + random.Next(40);

            return new Particle(texture, position, velocity, angle, angularVelocity, color, size, ttl);
        }

        public void Draw(SpriteBatch spriteBatch)
        {
            spriteBatch.Begin();
            for (int index = 0; index < particles.Count; index++)
            {
                particles[index].Draw(spriteBatch);
            }
            spriteBatch.End();
        }

    }
}



به تعداد ذرات موجود در لیست یک حلقه اجرا میشود و هر ذره جداگانه رسم میشود . تا اینجای کار تمام مواد اولیه و وسایل را آماده کردیم . حال نوبت استفاده عملی از این وسایل است .


قسمت چهارم : استفاده کاربردی از سیستم ذره ای
میخواهیم ببینیم تا الان چه کردیم . یک مثال کاربردی میتواند حاصل کار را تا به اینجا مشخص کند .
میخوام دو سیستم ذره ای را روی محور سینوسی در جهت مخالف یکدیگر حرکت دهیم .پس اهداف اصلی ما دو سیستم هستند که نقطه انتشار دهنده ذره آنها بر روی منحنی سینوسی حرکت میکند . ما نیاز به دو نقطه انتشار دهنده داریم ، دوموتور که ذرات را به صورت خودکار تولید کنند و ذرات به صورت خودکار بعد از گذشت زمانی از بین بروند . در نهایت این دو موتور بر روی یک منحنی حرکت کنند .اگر حرکت موتور ها را از کار حذف کنیم ، میبینیم که آنچه تا بحال انجام دادیم همین است که الان نیاز داریم .پس ما فقط نیاز به ایجد دو موتور و فعال کردن آنها داریم و در نتیجه حرکت دادن آنها بر روی منحنی مورد نظر .
با ایجاد موتور ها شروع میکنیم ، البته توجه داشته باشید که کدها در فایل Game1.cs قرار میگیرد .
در کلاس Game1.cs متغیر های زیر را تعریف کنید .
كد:
ParticleEngine particleEngine1, particleEngine2;
        bool Flag=true ;
        float sin=0f;

ما دوسیستم ذره ای به نام های particleEngine1 و 2 تعریف کردیم ، این دو موتور همان نقاط انتشار دهنده ما هستند . در ادامه Flag را تعریف کردیم که یک متغیر پرچم است که برای تغییر جهت حرکت موتور ها به کار میرود ، یعنی زمانی که پرچم بالا باشد جهت حرکت مثبت است و در غیر اینصورت جهت حرکت منفی است . زمان استفاده از این پرچم سعی میکنیم بیشتر بر روی آن تمرکز کنیم . و در نهایت متغیری به نام sin داریم که نگهدارنده سینوس موقعیت موتور است . که بعدا به صورت کامل توضیح خواهیم داد . در متد LoadContent کدهای زیر را اضافه میکنیم :
كد:

            List<Texture2D> textures = new List<Texture2D>();
            textures.Add(Content.Load<Texture2D>("circle"));
            textures.Add(Content.Load<Texture2D>("star"));
            textures.Add(Content.Load<Texture2D>("4ed"));
            particleEngine1 = new ParticleEngine(textures, new Vector2(400, 240));
            particleEngine2 = new ParticleEngine(textures, new Vector2(400, 240));

textures در اینجا لیستی از تصاویر است ، تصاویری که باید در موتور تولید شوند . همانطور که میبینید در ادامه تعریف لیست ، 3 عنصر به آن اضافه کردیم ، circle ،star و 4ed که تصاویر را خودتان ميتوانيد در ابعاد 10*10 انتخاب يا رسم كنيد . در خطوط بعد دو موتور را مقدار دهی کردیم . اگه یادتان باشد هر موتور برای ساخته شدن 2 آرگومان ورودی دریافت میکرد . یکی لیست تصاویر ذراتی که باید در موتور تولید شوند و دیگری موقعیت نقطه انتشار دهنده موتور ، ما در این خطوط این دو آرگومان را مقدار دهی کرده ایم.
در متد Update کد زیر را اضافه میکنیم :
كد:

            if (Flag)
            {
                sin += .05f;
                if (sin >= 14)
                    Flag = false;
            }
            else
            {
                if (sin <= -2)
                    Flag = true;
                sin -= .04f;

            }

همانطور که مشاهده میکنید ، در صورتی که مقدارflag برابر true باشد ،مقدار متغیرsin اضافه میشود و زمانی که از مقدار خاصی تجاوز کرد مقدارflag برابرfalse میشود. این به آن خاطر است که مسیر حرکت موتور مثبت است تا زمانی که به گوشه های تصویر برسد و وقتی این اتفاق افتاد ف مسیر حرکت منفی میشود تا موتور به داخل صفحه باز گردد. در ادامه کدهای قبلی ، کدهای زیر را نیز اضافه میکنیم :
كد:

            float sin1=(-1)*sin;
            particleEngine1.EmitterLocation = new Vector2(sin*70,200+(100*( (float)Math.Sin(sin))));
            particleEngine1.Update();
            particleEngine2.EmitterLocation = new Vector2(800+sin1 * 70, 200 + (100 * ((float)Math.Sin(sin))));
            particleEngine2.Update();

در خط اول یک متغیر به نام sin1 داریم که مقدار آن برابر مقدار منفی شده متغیر sin است ، چرا که یکی از موتور ها به سمت جلو و دیگری به سمت عقب حرکت میکند پس ما یک مقدار منفی و یک مقدار مثبت میخواهیم که این گونه آنها را ایجاد کردیم . در خط بعد موقعیت موتور اول را مشخص کرده ایم. مقادیری که در اینجا میبینید ثابت نیستند و بسته به موقعیت نقاط و صفحه استفاده شده اند .با کمی تغییر میتوانید بفهمید که چه اتفاقی افتاده چون ما برای حرکت یک نقطه روی محور سینوس باید نقطه را در جهت محور x ها به طور ثابت جلو ببریم و از y نقطه سینوس بگیریم تا منحنی ایجاد شود .این کار را برای موتور دوم نیز تکرار میکنیم .
در آخر نیز کدهای زیر را در متد draw قرار میدهیم . که برای رسم موتور ها استفاده میشود .
كد:
particleEngine1.Draw(spriteBatch);
            particleEngine2.Draw(spriteBatch);


كد نهايي شما بايد شبيه زير باشد :
u
كد:
sing System;
using System.Collections.Generic;
using System.Linq;
using Microsoft.Xna.Framework;
using Microsoft.Xna.Framework.Audio;
using Microsoft.Xna.Framework.Content;
using Microsoft.Xna.Framework.GamerServices;
using Microsoft.Xna.Framework.Graphics;
using Microsoft.Xna.Framework.Input;
using Microsoft.Xna.Framework.Media;

namespace ParticleSystems
{
    public class Game1 : Microsoft.Xna.Framework.Game
    {
        GraphicsDeviceManager graphics;
        SpriteBatch spriteBatch;
        ParticleEngine particleEngine1, particleEngine2;
        bool Flag=true ;
        float sin=0f;
        public Game1()
        {
            graphics = new GraphicsDeviceManager(this);
            Content.RootDirectory = "Content";
        }

       
        protected override void Initialize()
        {

            base.Initialize();
        }

        protected override void LoadContent()
        {
            spriteBatch = new SpriteBatch(GraphicsDevice);
            List<Texture2D> textures = new List<Texture2D>();
            textures.Add(Content.Load<Texture2D>("circle"));
            textures.Add(Content.Load<Texture2D>("star"));
            textures.Add(Content.Load<Texture2D>("4ed"));
            particleEngine1 = new ParticleEngine(textures, new Vector2(400, 240));
            particleEngine2 = new ParticleEngine(textures, new Vector2(400, 240));
        }

        protected override void UnloadContent()
        {
        }

        protected override void Update(GameTime gameTime)
        {
            if (Flag)
            {
                sin += .05f;
                if (sin >= 14)
                    Flag = false;
            }
            else
            {
                if (sin <= -2)
                    Flag = true;
                sin -= .04f;

            }
            float sin1=(-1)*sin;
            particleEngine1.EmitterLocation = new Vector2(sin*70,200+(100*( (float)Math.Sin(sin))));
            particleEngine1.Update();
            particleEngine2.EmitterLocation = new Vector2(800+sin1 * 70, 200 + (100 * ((float)Math.Sin(sin))));
            particleEngine2.Update();

            base.Update(gameTime);
        }

        protected override void Draw(GameTime gameTime)
        {
            GraphicsDevice.Clear(Color.Black );
            particleEngine1.Draw(spriteBatch);
            particleEngine2.Draw(spriteBatch);
            base.Draw(gameTime);
        }
    }
}


_________________
به امید موقعیتی که لایقش باشیم !
www.MojtabaMaher.ir


0 بار اين نامه ويرايش شده است كه آخرين بار توسط 3 شنبه 7 تير 1390 - 18:56 در 8 بوده است.
ارسال  بازگشت به بالا
ديدن مشخصات كاربر ارسال پيغام خصوصي ديدن وب سايت كاربر
 

نويسنده
پيغام
vahidpoor
پیر بازی سازی
پیر بازی سازی


تاريخ عضويت: 4 شنبه 31 تير 1388
تعداد ارسالها: 531
محل سكونت: مشهد


4 شنبه 25 خرداد 1390 - 19:12
پاسخ بصورت نقل قول
اضافه میکنم برای ایکس ان ای موتورهایی برای سیستم ذره ای دو بعدی و سه بعدی وجود دارد
http://mpe.codeplex.com/wikipage?title=Screenshots&referringTitle=Home
این دو بعدی

_________________
همیشه زمانی برای شروع است
ارسال  بازگشت به بالا
ديدن مشخصات كاربر ارسال پيغام خصوصي ارسال ايميل ديدن وب سايت كاربر
 

نويسنده
پيغام
dorche
کاربر جدید
کاربر جدید


تاريخ عضويت: جمعه 31 ارديبهشت 1389
تعداد ارسالها: 4


5 شنبه 26 خرداد 1390 - 19:35
پاسخ بصورت نقل قول
سلام

منم علاقه زیادی به این موضوع دارم و مایل به همکاری هستم

فقط اگه میشه منابعی که مطالعه کردید و مطالعه می کنید را نام ببرید

ممنون
ارسال  بازگشت به بالا
ديدن مشخصات كاربر ارسال پيغام خصوصي
 

نويسنده
پيغام
SILSIN
در حال رشد
در حال رشد


تاريخ عضويت: شنبه 19 مرداد 1387
تعداد ارسالها: 46
محل سكونت: مازندران


5 شنبه 26 خرداد 1390 - 20:49
پاسخ بصورت نقل قول
خوبه.
نگران غلط گیری نباش خودم غلط هات رو می گیرم Very Happy

_________________
اولین انجمن تخصصی انجین بازی سازی UDK در ایران

WWW.UDK.IR
ارسال  بازگشت به بالا
ديدن مشخصات كاربر ارسال پيغام خصوصي ارسال ايميل ديدن وب سايت كاربر
 

نويسنده
پيغام
vahidpoor
پیر بازی سازی
پیر بازی سازی


تاريخ عضويت: 4 شنبه 31 تير 1388
تعداد ارسالها: 531
محل سكونت: مشهد


جمعه 27 خرداد 1390 - 00:20
پاسخ بصورت نقل قول
البته قصد ایراد گیری ندارم اما خوب
دو سیستم که توضیح در مورد زمان شروعشون هست که در حقیقت یک مدل بر اساس رخداد دیگری هم به صورت یک حلقه با شرطی مشخص هست

ادامه بدید لطفا

_________________
همیشه زمانی برای شروع است
ارسال  بازگشت به بالا
ديدن مشخصات كاربر ارسال پيغام خصوصي ارسال ايميل ديدن وب سايت كاربر
 

نويسنده
پيغام
ashkan_203
مدیر انجمن
مدیر انجمن


تاريخ عضويت: 5 شنبه 9 آذر 1385
تعداد ارسالها: 794
محل سكونت: همه جای ایران سرای من است


جمعه 27 خرداد 1390 - 11:52
پاسخ بصورت نقل قول
منم من باب این پست دادم که دارم دنبال می کنم Evil or Very Mad
منتظر ادامه هستیم

_________________

آی گیمز
ارسال  بازگشت به بالا
ديدن مشخصات كاربر ارسال پيغام خصوصي ارسال ايميل ديدن وب سايت كاربر نام كاربري در پيغامگير Yahoo
 

نويسنده
پيغام
littledemon
در حال رشد
در حال رشد


تاريخ عضويت: جمعه 31 فروردين 1386
تعداد ارسالها: 86
محل سكونت: زیر بام کلبه ای در غرب این ملک غریب


جمعه 27 خرداد 1390 - 14:43
پاسخ بصورت نقل قول
خیلی ممنونم از همه
به خاطر دو امتحانی که تو راه دارم ، انشالله قسمت بعدی رو بامداد دوشنبه اضافه می کنم .

در جواب دوست عزیزم جناب vahidpoor, باید بگم من هم همینو میخواستم. بالاخره من یه چیزی که ساخته ذهنمه میگم و شما بزرگا باید بیاید منت بزارید و درستش کنید تا مام یادبگیریم Surprised

_________________
به امید موقعیتی که لایقش باشیم !
www.MojtabaMaher.ir
ارسال  بازگشت به بالا
ديدن مشخصات كاربر ارسال پيغام خصوصي ديدن وب سايت كاربر
 

نويسنده
پيغام
littledemon
در حال رشد
در حال رشد


تاريخ عضويت: جمعه 31 فروردين 1386
تعداد ارسالها: 86
محل سكونت: زیر بام کلبه ای در غرب این ملک غریب


2 شنبه 30 خرداد 1390 - 09:26
پاسخ بصورت نقل قول
عجب بامدادی !!! خورشید وسط آسمونه !! Shocked
ما قرار شد بامداد بزاریم قسمت بعد رو که دیر شد یکم .امتحاناته دیگه Wink
دوستان قسمت سوم هم تا فردا شب اضافه میکنم تا بشه قسمت دوم رو راحت تر هضم کرد PDT_002

در ضمن : به دلیل این که ممکنه خیلی ها علاقه به پیاده سازی سیستم های ذره ای داشته باشند ولی روزهای اولشون هست با برنامه نویسی در xna سر و کله میزنند ، بنده اومدم و به صورت سطح پائین توضیح دادم مطالب رو . پس اساتید چشم پوشی کنند از این مسله Very Happy

___________ویرایش شد !
راستی یادم نره بگم که بنده برای شروع از کدهای سایت Rbwhitaker استفاده کردم که بعدا خودمون ارتقا بدیم سطح رو... چون دیدم شروع خوبی داشت بنده هم از کدها استفاده کردم Surprised

_________________
به امید موقعیتی که لایقش باشیم !
www.MojtabaMaher.ir


اين نامه توسط littledemon در 3 شنبه 31 خرداد 1390 - 07:52 ويرايش شده است.
ارسال  بازگشت به بالا
ديدن مشخصات كاربر ارسال پيغام خصوصي ديدن وب سايت كاربر
 

نويسنده
پيغام
vahidpoor
پیر بازی سازی
پیر بازی سازی


تاريخ عضويت: 4 شنبه 31 تير 1388
تعداد ارسالها: 531
محل سكونت: مشهد


2 شنبه 30 خرداد 1390 - 10:33
پاسخ بصورت نقل قول
اضافه می کنم این سیستم پارتیکتل دو بعدی و همچنین پاییه ای است البته روشهای دیگری هم وجود دارد

_________________
همیشه زمانی برای شروع است
ارسال  بازگشت به بالا
ديدن مشخصات كاربر ارسال پيغام خصوصي ارسال ايميل ديدن وب سايت كاربر
 

نمايش نامه هاي ارسال شده قبلي:   
ارسال يك موضوع جديد   پاسخ به يك موضوع    صفحه 1 از 2 تمام ساعات و تاريخها بر حسب 3.5+ ساعت گرينويچ مي باشد
برو به صفحه 1, 2  بعدي


 
پرش به:  


شما نمي توانيد در اين انجمن نامه ارسال كنيد.
شما نمي توانيد به موضوعات اين انجمن پاسخ دهيد
شما نمي توانيد نامه هاي ارسالي خود را در اين انجمن ويرايش كنيد
شما نمي توانيد نامه هاي ارسالي خود را در اين انجمن حذف كنيد
شما نمي توانيد در نظر سنجي هاي اين انجمن شركت كنيد


unity3d

بازگردانی به فارسی : علی کسایی @ توسعه مجازی کادوس 2004-2011
Powered by phpBB © 2001, 2011 phpBB Group
| Home | عضويت | ليست اعضا | گروه هاي كاربران | جستجو | راهنماي اين انجمن | Log In |