ترسیم تصویر donut در board ( بازی سازی با جاوا)

1395/10/6 لیلا کشاورز 833

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

اگر خاطرتون باشه،در قسمت قبل ، کار رو تا ساخت یک board  (محیطی که بازی مون در اون به نمایش در میاد) پیش بردیم و در مرحله ی بعد دیدیم که چطور یک تصویر رو در board  مون به نمایش دربیاریم.

برای رسم اشکال مختلف، جاوا توابع وکلاسهای بسیاری شامل ابزار نقاشی، کار با رنگها و تصاویرو... را در اختیار ما قرار داده .
در این قسمت قصد داریم به کمک این متد ها(که به JAVA 2D API  معروفند) ،تصویر یک donut  رو  در board  مون رسم کنیم.

خب، یک پروژه ی جدید ایجاد کنید ، یک پکیج در پروژتون قرار بدید و در اون، کلاسی بنام Board  (از فرم JPanel )
ایجاد کنید.
رسم donut  رو طبق توضیحات جلسه قبل، درون این کلاس  باید پیاده سازی میکنیم.

public void paintComponent(Graphics g) {
        super.paintComponent(g);
        drawDonut(g);
    }

عملیات رسم از متد  paintComponent()  آغاز میشود. برای تنها ورودی این متد، (g) ،
 تابع drowDonat() را که عملا رسم را در آن پیاده سازی میکنیم ، فراخوانی میکنیم:

private void drawDonut(Graphics g) {
        Graphics2D g2d = (Graphics2D) g;
}

کلاس Graphics2D که از کلاس  Graphics مشتق شده است، یک کنترل را در سطح بالا برای رسم ایجاد می کند .

قبل از اینکه به رسم شکلمون بپردازیم، از RenderingHints  ، برای روانسازی خطوط رسممون استفاده میکنیم. برای انجام اینکار ،کد زیر را به تابع drawDonut() اضافه کنید.
 

RenderingHints rh
                = new RenderingHints(RenderingHints.KEY_ANTIALIASING,
                        RenderingHints.VALUE_ANTIALIAS_ON);
        rh.put(RenderingHints.KEY_RENDERING,
                RenderingHints.VALUE_RENDER_QUALITY)
        g2d.setRenderingHints(rh);

حالا نویت به رسم خود donut  میرسه. قبل از هر چیزی ،یک بیضی باید رسم کنیم.(که به کمک کلاس  Ellipse2Dرسمش میکنیم.) مختصات مرکز بیضی و هم چنین اندازه ی طول و عرض بیضی را به عنوان ورودی ، وارد میکنیم:

 Ellipse2D e = new Ellipse2D.Double(0, 0, 80, 130);

با دستور setStroke()  مقدار ضخامت خطوط رسم رو مشخص میکنیم.(ما ضخامت 1 را در نظر گرفتیم. با افزایش این مقدار، خطوط رسم ضخیم تر میشوند.)

g2d.setStroke(new BasicStroke(1));

 با دستور setColor()  هم ،رنگ مورد نظر رو بهش میدیم.

g2d.setColor(Color.blue);

حالا برای  اینکه  مشخص کنیم که بیضی دقیقا کجای پنجره ی خروجی قرار بگیره باید از AffineTransform  استفاده کنیم .
بهتر هست که برای اینکه خروجی مون شکل بهتری داشته باشد، رسم از مرکز پنجره آغاز شده باشد.
باااین حساب به طول و عرض پنجره نیاز داریم ، که با دستورات زیر، آنها را دریافت میکنیم:

Dimension size = getSize();
double w = size.getWidth();
double h = size.getHeight();

خب، مرکز پنجره با تعریف متغییر های فوق، میشود . (w/2, h/2) پس مختصات نقطه ی شروع رسم را به کمک AffineTransform، برابر این مقدار قرار میدیم. (در واقع با اینکار، نقطه ی سمت چپ بیضی در مرکز پنجره قرار میگیرد(.

AffineTransform at
= AffineTransform.getTranslateInstance(w/2, h/2);

برای رسم هم از دستور draw()  استفاده میکنیم:

g2d.draw(at.createTransformedShape(e));

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

package basic_2dgame;
public class skeleton extends javax.swing.JFrame {
    public skeleton() {
        add(new Board());
        setTitle("Donut");
        setDefaultCloseOperation(EXIT_ON_CLOSE);
        setSize(300,340);
        setLocationRelativeTo(null);
    }
    @SuppressWarnings("unchecked")
    public static void main(String args[]) {
        java.awt.EventQueue.invokeLater(new Runnable() {
            public void run() {
                new skeleton().setVisible(true);
            }
        });
    }
}

اگر پروژمون رو اجرا کنیم ،خروجی زیر رو میبینیم:

آموزش بازیسازی با جاوا

- حالا برای اینکه از این بیضی برسیم به شکل donut که هدف اصلیمون ،کافیه که بیضی ای که رسمش کردیم رو 72 مرتبه در یک حلقه دوران بدیم  و رسمش کنیم.
 اینکار رومیشه خیلی راحت به کمک حلقه ی for  انجام داد . یعنی دستورات مربوط به AffineTransform و draw رو به داخل حلقه انتقال میدیم .

for (double deg = 0; deg < 360; deg += 5) {
            AffineTransform at
                    = AffineTransform.getTranslateInstance(w/2, h/2);
            at.rotate(Math.toRadians(deg));
            g2d.draw(at.createTransformedShape(e));

خب،کار تمومه ...
فقط من یکبار دیگه قطعه کدهایی که در کلاس Board  نوشتیم رو بطور کامل اینجا میارم براتون که شکل نهایی کلاس رو ببینید :

package basic_2dgame;

import java.awt.BasicStroke;
import java.awt.Color;
import java.awt.Dimension;
import java.awt.Graphics;
import java.awt.Graphics2D;
import java.awt.RenderingHints;
import java.awt.geom.AffineTransform;
import java.awt.geom.Ellipse2D;

public class Board extends javax.swing.JPanel {
   public void paintComponent(Graphics g) {
        super.paintComponent(g);
        drawDonut(g);
    }
    @SuppressWarnings("unchecked")
private void drawDonut(Graphics g) {
        Graphics2D g2d = (Graphics2D) g;
        RenderingHints rh
                = new RenderingHints(RenderingHints.KEY_ANTIALIASING,
                        RenderingHints.VALUE_ANTIALIAS_ON);
        rh.put(RenderingHints.KEY_RENDERING,
                RenderingHints.VALUE_RENDER_QUALITY)
        g2d.setRenderingHints(rh);

        Dimension size = getSize();
        double w = size.getWidth();
        double h = size.getHeight();

        Ellipse2D e = new Ellipse2D.Double(0, 0, 80, 130);
        g2d.setStroke(new BasicStroke(1));
        g2d.setColor(Color.blue);

        for (double deg = 0; deg < 360; deg += 5) {
            AffineTransform at
                    = AffineTransform.getTranslateInstance(w/2, h/2);
            at.rotate(Math.toRadians(deg));
            g2d.draw(at.createTransformedShape(e));
        }
    }

حالا اگه پروژه رو اجرا کنیم، خروجی زیر رو مشاهده میکنیم:

بازیسازی با جاوا

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