2013年1月12日 星期六

IOS 小畫家基本實作(二)

從前一篇IOS 小畫家基本實作(ㄧ)改進而來。增加三個按鍵,分別是清除畫面、重繪及清除記錄。

實作如下

1. 加入記錄的變數到PaintMaskViewController.h中
#import <UIKit/UIKit.h>

@interface PaintMaskViewController : UIViewController
{
   
    BOOL isFirstPoint;

}


@property(nonatomic, retain) UIImageView* drawImage;

- (void) redraw;

@property (nonatomic) CGPoint  lPoint;
@property (nonatomic) CGPoint  cPoint;

@property (nonatomic) NSMutableArray *linePointsArray;
@property (nonatomic) NSMutableArray *drawLineSet;

@end

2.  在PaintMaskViewController.h中增加相關程式碼
#import "PaintMaskViewController.h"

@interface PaintMaskViewController ()

@end

@implementation PaintMaskViewController

int mouseMoved;
BOOL mouseSwiped;
CGPoint lastPoint;
CGPoint currentPoint;

@synthesize drawImage;

@synthesize linePointsArray;
@synthesize drawLineSet;


- (id)initWithNibName:(NSString *)nibNameOrNil bundle:(NSBundle *)nibBundleOrNil
{
    self = [super initWithNibName:nibNameOrNil bundle:nibBundleOrNil];
    if (self) {
        // Custom initialization
    }
    return self;
}

- (void)viewDidLoad
{
    [super viewDidLoad];
    // Do any additional setup after loading the view.
   
    linePointsArray = [[NSMutableArray alloc] init];
    drawLineSet = [[NSMutableArray alloc] init];
    isFirstPoint = NO;
       
    [self setClearButton];
    [self setRedrawButton];
    [self setClearSetsButton];   


}

- (void)didReceiveMemoryWarning
{
    [super didReceiveMemoryWarning];
    // Dispose of any resources that can be recreated.
}

- (void)touchesBegan:(NSSet *)touches withEvent:(UIEvent *)event {
    if(drawImage == nil) {
              
        self.drawImage = [[UIImageView alloc] initWithImage:nil];
       
        drawImage.frame = self.view.frame;
        [self.view addSubview:drawImage];
       
        [linePointsArray removeAllObjects];
       
    }
   
    isFirstPoint = YES;
   
    mouseSwiped = NO;
    UITouch *touch = [touches anyObject];

    lastPoint = [touch locationInView:self.view];
   
    [linePointsArray addObject:[NSValue valueWithCGPoint:lastPoint]];  // add a CGPoint
   

 
}


- (void)touchesMoved:(NSSet *)touches withEvent:(UIEvent *)event {
    mouseSwiped = YES;
    UITouch *touch = [touches anyObject];
    currentPoint = [touch locationInView:self.view];
   
    [self drawLine:1];   
    lastPoint = currentPoint;
   
    [linePointsArray addObject:[NSValue valueWithCGPoint:lastPoint]];  // add a CGPoint
   

    mouseMoved++;
   
    if (mouseMoved == 10) {
        mouseMoved = 0;
    }
}

- (void)touchesEnded:(NSSet *)touches withEvent:(UIEvent *)event {
    //Double click to clean the canvas
    UITouch *touch = [touches anyObject];
   
    currentPoint = [touch locationInView:self.view];
      
    [drawLineSet addObject:linePointsArray]; // add a array to sets
   
    linePointsArray  = nil;
   
    linePointsArray = [[NSMutableArray alloc] init];

    
}
- (void) drawLine:(int) move
{
    UIGraphicsBeginImageContext(self.view.frame.size);
    [drawImage.image drawInRect:CGRectMake(0, 0, drawImage.frame.size.width, drawImage.frame.size.height)];
   
    CGContextSetLineCap(UIGraphicsGetCurrentContext(), kCGLineCapRound);
    CGContextSetLineWidth(UIGraphicsGetCurrentContext(), 5.0);
   
   
    CGContextSetRGBStrokeColor(UIGraphicsGetCurrentContext(), 0.0, 1.0, 0.0, 1.0);

    CGContextMoveToPoint(UIGraphicsGetCurrentContext(), lastPoint.x, lastPoint.y);
   
    if (move == 1)
        CGContextAddLineToPoint(UIGraphicsGetCurrentContext(), currentPoint.x, currentPoint.y);
    else
       CGContextAddLineToPoint(UIGraphicsGetCurrentContext(), lastPoint.x, lastPoint.y);
   
    CGContextStrokePath(UIGraphicsGetCurrentContext());
   
    drawImage.image = UIGraphicsGetImageFromCurrentImageContext();
    UIGraphicsEndImageContext();
}


- (void)setClearButton  // 動態產生一個的Button
{
    UIButton *clearButton = [UIButton  buttonWithType:UIButtonTypeRoundedRect];
    //動態產生一個RoundedRect 形式的  Button
   
    clearButton.frame = CGRectMake(100,50, 100, 50); // 大小
   // [clearButton setCenter:CGPointMake(150, 50)];//位置放在x=150, y=50的位置
   
   
    [clearButton addTarget:self action:@selector(drawClear) forControlEvents:UIControlEventTouchUpInside];
    //設定Button動作呼叫的function在 onHelloActionButton,方式為按下
   
    //_helloActionButton.= @"Action Button";
    [clearButton setTitle:@"清除畫面" forState:UIControlStateNormal];
    //將動態Button上放置Action Button這兩個字
   
    [self.view addSubview:clearButton];
    //將動態Button放到View上展出
   
}



- (void)setRedrawButton  // 動態產生一個的Button
{
    UIButton *redrawButton = [UIButton  buttonWithType:UIButtonTypeRoundedRect];
    //動態產生一個RoundedRect 形式的  Button
   
    redrawButton.frame = CGRectMake(200, 50, 100, 50); // 大小
    //[redrawButton setCenter:CGPointMake(250, 50)];//位置放在x=150, y=50的位置
   
   
    [redrawButton addTarget:self action:@selector(redraw) forControlEvents:UIControlEventTouchUpInside];
    //設定Button動作呼叫的function在 onHelloActionButton,方式為按下
   
    //_helloActionButton.= @"Action Button";
    [redrawButton setTitle:@"重繪" forState:UIControlStateNormal];
    //將動態Button上放置Action Button這兩個字
   
    [self.view addSubview:redrawButton];
    //將動態Button放到View上展出
   
}


- (void)setClearSetsButton  // 動態產生一個的Button
{
    UIButton *clearSetsButton = [UIButton  buttonWithType:UIButtonTypeRoundedRect];
    //動態產生一個RoundedRect 形式的  Button
   
    clearSetsButton.frame = CGRectMake(300, 50, 100, 50); // 大小
    //[redrawButton setCenter:CGPointMake(250, 50)];//位置放在x=150, y=50的位置
   
   
    [clearSetsButton addTarget:self action:@selector(clearSet) forControlEvents:UIControlEventTouchUpInside];
    //設定Button動作呼叫的function在 onHelloActionButton,方式為按下
   
    //_helloActionButton.= @"Action Button";
    [clearSetsButton setTitle:@"清除記錄" forState:UIControlStateNormal];
    //將動態Button上放置Action Button這兩個字
   
    [self.view addSubview:clearSetsButton];
    //將動態Button放到View上展出
   
}



- (void) clearSet
{
    [drawLineSet removeAllObjects];
   
    drawLineSet = nil;
   
    drawLineSet = [[NSMutableArray alloc] init];
   
}


- (void) redraw
{
   
    UIGraphicsBeginImageContext(self.view.frame.size);
    [drawImage.image drawInRect:CGRectMake(0, 0, drawImage.frame.size.width, drawImage.frame.size.height)];
   
    CGContextSetLineCap(UIGraphicsGetCurrentContext(), kCGLineCapRound);
    CGContextSetLineWidth(UIGraphicsGetCurrentContext(), 5.0);

    CGContextSetRGBStrokeColor(UIGraphicsGetCurrentContext(), 1.0, 0.0, 1.0, 1.0);
   
   
    int count1 = [drawLineSet count];
   
    if (count1 ==0)
        return;
   
    NSMutableArray *temp = [[NSMutableArray alloc] init];
   
    for (int j=0;j<count1;j++){
       
        temp = [ drawLineSet  objectAtIndex:j];
       
        NSValue *val = [temp objectAtIndex:0];
        CGPoint p = [val CGPointValue];
       
        CGContextMoveToPoint(UIGraphicsGetCurrentContext(), p.x, p.y);
   
        int count = [temp count];
       
        for (int i=1; i<count; i++)
        {
            val = [temp objectAtIndex:i];
            p = [val CGPointValue];
           
            CGContextAddLineToPoint(UIGraphicsGetCurrentContext(), p.x, p.y);
        }
       
        CGContextStrokePath(UIGraphicsGetCurrentContext());
    }
   
    drawImage.image = UIGraphicsGetImageFromCurrentImageContext();
    UIGraphicsEndImageContext();
}



- (void) drawClear
{
   
    UIGraphicsBeginImageContext(self.view.frame.size);
    [drawImage.image drawInRect:CGRectMake(0, 0, drawImage.frame.size.width, drawImage.frame.size.height)];
   
    CGContextSetLineCap(UIGraphicsGetCurrentContext(), kCGLineCapRound);
    CGContextSetLineWidth(UIGraphicsGetCurrentContext(), 5.0);
    

    // 清除畫面
     CGContextClearRect(UIGraphicsGetCurrentContext(), CGRectMake(0, 0, 1024, 768));

    // 存回畫面

    drawImage.image = UIGraphicsGetImageFromCurrentImageContext();
    UIGraphicsEndImageContext();
}

@end

 3. 結果顯示,重繪的線使用紫色。


2013年1月11日 星期五

NSValue的使用

當你想使用Cocoa的集合來存儲非對象型數據時,NSValue和NSNumber是非常有用的。 NSNumber是NSValue的子類,所以NSValue更靈活一些。我們先看看NSValue能做什麼: 
一個NSValue對像是用來存儲一個C或者Objective-C數據的簡單容器。它可以保存任意類型的數據,比如int,float,char,當然也可以是指pointers, structures, and object ids。 NSValue類的目標就是允許以上數據類型的數據結構能夠被添加到集合裡,例如那些需要其元素是對象的數據結構,如NSArray或者NSSet 的實例。

另外注意,如果要用struct的指向變數,要使用NSData,有機會再整理相關資料。

下面使用NSMutableArray來作例子 

將CGPoint放入NSMutable Array
NSMutableArray *linePointsArray = [[NSMutableArray alloc] init];
CGPoint lastPoint = CGPointMake(5.5, 6.6)]

[linePointsArray addObject:[NSValue valueWithCGPoint:lastPoint]]; // add a CGPoint


從Array中取出 CGPoint
 NSValue *val = [linePointsArray objectAtIndex:0];
  CGPoint p = [val CGPointValue];



另外int 變數也可以如此用

myArray = [NSMutableArray array];
[myArray addObject:[NSNumber numberWithInteger:1234]];

//..

 int theNumber = [[myArray objectAtIndex:0] integerValue];

2013年1月10日 星期四

iOS App第一次被Apple退件

第一次被Apple退件,前面兩個app很幸運都一次就上架了,但這一次因為趕在新曆年前上架,有一些細節確實有比較差了點,本想進版時再來修訂。看來Apple的審查確實有比較嚴格了點,這一次退件,大概主要出在兩個位置:

1. 因為iPad的畫面較大,而所用到的貼圖較小,因此將圖片撐大些,來使版面看起來較少空隙。下圖是Apple挑出來的畫面,右邊的圖是我撐大後的結果,看起來畫質確實較差了點。


2. 另外因為尚有些內容來不及整理完,因此第一版的部分章節就簡單了些,造成空隙過大。因此就趁這一次退稿,將內容較完整地呈現出來,雖然不可能一百分,至少也要有個八十分的水準,才對得起自己的作品。下圖可以看到空隙過大的缺點,另外也不建議用單一背景圖來充場面,應該使用ScrollView來填充多張圖,這樣的質感才會比較好。


以下使退稿的說明文字,當做是自己的一次記錄。

We found the following issues with the user interface of your app:

- Included low resolution/jagged image/s; see screenshot for example.
- Was not optimized to support the device screen size and/or resolution; see screenshot for example.

These examples identify types of issues discovered in your app but may not represent all such issues. It would be appropriate to thoroughly evaluate your app to address these types of issues.

* * * *

Resources for learning how to improve your app:

- Watch the video The Ingredients of Great Apps to understand the basics of great apps

- Watch the video iPhone and iPad User Interface Design for practical design tips

- Read the iOS Human Interface Guidelines and double check that your app's user interface adheres to these valuable guidelines.

- Read the App Design Basics section of the iOS App Programming Guide.

- Watch the iOS Development Videos to learn about programming and design tips.If you feel we didn't understand the features of your app, or that we missed key functionality, and your app was incorrectly rejected, you may appeal to the App Review Board.

2013年1月9日 星期三

錄音與播放的使用實作

實作一個錄音與播放的功能

1. 開啓一個新的專案


2. 在storyboard上加入兩個Button及一個Label
3. 加上AVFoundation Framework


4. 在mainViewController.h加入所需變數
#import <UIKit/UIKit.h>
#import <AVFoundation/AVFoundation.h>

@interface mainViewController : UIViewController
{
    NSURL *recordedFile;
    AVAudioPlayer *player;
    AVAudioRecorder *recorder;
    BOOL isRecording;
}


@property (weak, nonatomic) IBOutlet UIButton *recordButton;

@property (weak, nonatomic) IBOutlet UIButton *playButton;

@property (weak, nonatomic) IBOutlet UILabel *timeLabel;

@property(nonatomic)NSTimer *songTimer;
@property(nonatomic)NSTimer *playTimer;


@end

5.在mainViewController.m加入相關程式碼
#import "mainViewController.h"

@interface mainViewController ()

@end

@implementation mainViewController

@synthesize recordButton,playButton,timeLabel;

@synthesize songTimer, playTimer;


- (void)viewDidLoad
{
    [super viewDidLoad];
    // Do any additional setup after loading the view, typically from a nib.
   
    isRecording = NO;
    [playButton setEnabled:NO];
    playButton.titleLabel.alpha = 0.5;
    recordedFile = [NSURL fileURLWithPath:[NSTemporaryDirectory() stringByAppendingString:@"RecordedFile"]];
   
    AVAudioSession *session = [AVAudioSession sharedInstance];
   
    NSError *sessionError;
    [session setCategory:AVAudioSessionCategoryPlayAndRecord error:&sessionError];
   
    if(session == nil)
        NSLog(@"Error creating session: %@", [sessionError description]);
    else
        [session setActive:YES error:nil];

   
}

- (void)didReceiveMemoryWarning
{
    [super didReceiveMemoryWarning];
    // Dispose of any resources that can be recreated.
}

- (IBAction)activeRecord:(id)sender {
   
    if (playTimer!= nil){
        [playTimer invalidate];
        playTimer = nil;
    }   
   
    //If the app is note recording, we want to start recording, disable the play button, and make the record button say "STOP"
    if(!isRecording)
    {
        isRecording = YES;
        [recordButton setTitle:@"停止" forState:UIControlStateNormal];
        [playButton setEnabled:NO];
        [playButton.titleLabel setAlpha:0.5];
        recorder = [[AVAudioRecorder alloc] initWithURL:recordedFile settings:nil error:nil];
        [recorder prepareToRecord];
        [recorder record];
        player = nil;
       
        songTimer = [NSTimer scheduledTimerWithTimeInterval:0.1 target:self selector:@selector(timeRecorder) userInfo:nil repeats:YES]; //scheduledTimerWithTimeInterval 不可太小,模擬器速度撐不住。最好使用0.5,模擬器才不會卡卡的

    }
    //If the app is recording, we want to stop recording, enable the play button, and make the record button say "REC"
    else
    {
        isRecording = NO;
        [recordButton setTitle:@"錄音" forState:UIControlStateNormal];
        [playButton setEnabled:YES];
        [playButton.titleLabel setAlpha:1];
       
        [songTimer invalidate];
        songTimer = nil;
       
        [recorder stop];
        recorder = nil;
       
        NSError *playerError;
       
        player = [[AVAudioPlayer alloc] initWithContentsOfURL:recordedFile error:&playerError];
       
        if (player == nil)
        {
            NSLog(@"ERror creating player: %@", [playerError description]);
        }
     
    }

}

- (IBAction)playSound:(id)sender {
   
    if (songTimer != nil)
    {
        [songTimer invalidate];
        songTimer = nil;
    }
   
    //If the track is playing, pause and achange playButton text to "Play"
    if([player isPlaying])
    {
        [player pause];
        [playButton setTitle:@"播放" forState:UIControlStateNormal];
       
        [playTimer invalidate];
        playTimer = nil;
       
    }
    //If the track is not player, play the track and change the play button to "Pause"
    else
    {
        [player play];
        [playButton setTitle:@"暫停" forState:UIControlStateNormal];
       
        playTimer = [NSTimer scheduledTimerWithTimeInterval:0.1 target:self selector:@selector(timeLoader) userInfo:nil repeats:YES]; 

//scheduledTimerWithTimeInterval 不可太小,模擬器速度撐不住。最好使用0.5,模擬器才不會卡卡的
    }

}

- (void)audioPlayerDidFinishPlaying:(AVAudioPlayer *)player successfully:(BOOL)flag
{
    [self.playButton setTitle:@"Play" forState:UIControlStateNormal];
}

- (void) showTime:(NSTimeInterval ) time
{
    int min;
    int sec;
   
    min = (NSInteger ) time/60;
   
    sec = (NSInteger ) time%60;
   
    NSString *showTimeText =  [NSString stringWithFormat:@"%2.2d:%2.2d",min, sec];
   
    timeLabel.text = showTimeText;
   
}

-(void)timeLoader

{
    if (player.currentTime == 0)
        [self showTime:player.duration];
    else
        [self showTime:player.currentTime];
   
    if (player.currentTime > player.duration - 0.1)
    {
        [playButton setTitle:@"播放" forState:UIControlStateNormal];
       
        [playTimer invalidate];
        playTimer = nil;
    }
   
}

-(void)timeRecorder
{
    [self showTime:recorder.currentTime];
}


@end


6. 執行結果,錄音與播放。


2013年1月8日 星期二

避免IOS進入休眠的做法

iOS如果沒有特殊的設定,一段時間後就會自動進入休眠,為了避免自動休眠,只要加入下面程式碼即可。

- (void) viewWillAppear:(BOOL)animated
{
    [[UIApplication sharedApplication] setIdleTimerDisabled: YES]; // 讓iOS不要睡著了
}

- (void) viewWillDisappear: (BOOL) animated
{
    [[UIApplication sharedApplication] setIdleTimerDisabled: NO];  // 縮小時就讓iOS可以休眠
}
 

2013年1月7日 星期一

UIScrollView進階使用(四)

改良前一篇的做法,不僅Segment可以選擇,連圖片(Touch mode)都可以選擇。

1. 在mainViewController.m加入程式碼
- (void)viewDidLoad
{
    [super viewDidLoad];
    // Do any additional setup after loading the view, typically from a nib.
   
  ....   
    [self.view addSubview:scrollerView];
   
    [scrollerView addSubview:seg];
   
    UITapGestureRecognizer *singleTap = [[UITapGestureRecognizer alloc] initWithTarget:self action:@selector(singleTapGestureCaptured:)];
   
    [scrollerView addGestureRecognizer:singleTap];

   
    [seg addTarget:self action:@selector(changeImage:) forControlEvents:UIControlEventValueChanged];
   
    [self.view addSubview:rootImageView];
   
}

- (void)singleTapGestureCaptured:(UITapGestureRecognizer *)gesture
{
    CGPoint touchPoint=[gesture locationInView:scrollerView];

    for (int i=0; i<14;i++)
    {

    if (touchPoint.x < PIC_WIDTH*(i+1) && touchPoint.x >PIC_WIDTH*i && touchPoint.y <PIC_HEIGHT)
    {
        rootImageView.image = [UIImage imageNamed:[NSString stringWithFormat:@"%d.png",i]];
        break;
    }
    }
}


2. 顯示結果


2013年1月6日 星期日

UIScrollView進階使用(三)

使用ScrollView來制作選擇表。


1. 開啓一個專案

2. 選擇橫向顯示


3. 加入必要的變數到mainViewController.h
#import <UIKit/UIKit.h>

@interface mainViewController : UIViewController
{
UIImageView *rootImageView;
UISegmentedControl *seg;
UIScrollView *scrollerView;
}
@end


4. 加入程式碼到mainViewController.m
#import "mainViewController.h"

@interface mainViewController ()

@end

@implementation mainViewController

#define SCROLL_HEIGHT   150
#define SCROLL_SIZE     1024
#define SCROLL_HORIZOTAL_DISPLAY  2248

#define PIC_WIDTH 150
#define PIC_HEIGHT  90

#define SEGMENT_WIDTH   14*150  //*PIC_WEIGHT
#define SEGMENT_HEIGHT  50


- (void)viewDidLoad
{
    [super viewDidLoad];
    // Do any additional setup after loading the view, typically from a nib.
   
    rootImageView = [[UIImageView alloc]initWithFrame:CGRectMake(360, 200, 280, 280)];
   
    NSArray *arr = [NSArray arrayWithObjects:@"圖一",@"圖二",@"圖三",@"圖四",@"圖五",@"圖六",@"圖七",@"圖八",@"圖九",@"圖十",@"圖十一",@"圖十二",@"圖十三",@"圖十四", nil];
   
    seg = [[UISegmentedControl alloc]initWithItems:arr];
   
    seg.segmentedControlStyle = UISegmentedControlStylePlain;
    seg.frame = CGRectMake(0, 100, SEGMENT_WIDTH, SEGMENT_HEIGHT);
    seg.tintColor = [UIColor blackColor];
    seg.userInteractionEnabled = YES;//关闭用户交互
   
    scrollerView = [[UIScrollView alloc]initWithFrame:CGRectMake(0, 600, SCROLL_SIZE, SCROLL_HEIGHT)];
   
    scrollerView.backgroundColor = [UIColor clearColor];
    scrollerView.indicatorStyle = UIScrollViewIndicatorStyleBlack;//滚动条样式
    scrollerView.showsHorizontalScrollIndicator = YES;
    //显示横向滚动条
    scrollerView.showsVerticalScrollIndicator = NO;//关闭纵向滚动条
    scrollerView.bounces = NO;//取消反弹效果
    scrollerView.pagingEnabled = YES;//划一屏
    scrollerView.contentSize = CGSizeMake(SCROLL_HORIZOTAL_DISPLAY, SCROLL_HEIGHT);
   
   
    for(int i=0;i<14;i++)
    {
        UIImageView *bgImageView = [[UIImageView alloc]initWithFrame:CGRectMake(PIC_WIDTH*i, 10, PIC_WIDTH, PIC_HEIGHT)];
       
        UIImage *bgImage = [UIImage imageNamed:[NSString stringWithFormat:@"%d.png",i]];
        bgImageView.image = bgImage;
        [scrollerView addSubview:bgImageView];
               
    }
   
    [self.view addSubview:scrollerView];
   
    [scrollerView addSubview:seg];
   
    [seg addTarget:self action:@selector(changeImage:) forControlEvents:UIControlEventValueChanged];
   
    [self.view addSubview:rootImageView];


}

- (void)didReceiveMemoryWarning
{
    [super didReceiveMemoryWarning];
    // Dispose of any resources that can be recreated.
}

- (void) changeImage:(UISegmentedControl *)segment
{
    rootImageView.image = [UIImage imageNamed:[NSString stringWithFormat:@"%d.png",segment.selectedSegmentIndex]];
}


@end



5. 執行結果




佛學名詞整理(三)欲界

欲界

佛教術語,欲界包含、人、阿修羅畜生餓鬼地獄六道六種不同境界。

若說欲界中的天界「欲界天」,則是相較於更高層次的另兩個天為色界無色界)最低一個;生於此道者有色身(物質身),亦有男女飲食之

欲界六天

可再細分為六層
   
第一重天: 四天王天
第二重天: 忉利天(又稱三十三天,天主為帝釋天)
第三重天: 夜摩天
第四重天: 兜率天
第五重天: 化樂天
第六重天: 他化自在天

第一重天及第二重天又稱為地居天,分別居於須彌山的山腰和山頂。
其它重天又稱為空居天

欲界六天中,四天王天居須彌山腰, 忉利天 居須彌山頂,此二天均未離開大地,因此稱地居天。夜摩天以上諸天,居忉利以上的空間,因此稱爲空居天 。據《翻譯名義集》卷二稱,所謂天,清淨光潔,最勝最尊,所以稱爲天。眾生因修上品十善,所以離開五道,投生於天趣。其中若是未修禪定,不能離於地者,爲 地居天。夜摩天以上四天,因禪定力故,不依於地,居於空中。但因其定力未到,即未能入根本禪定,所以還未能脱離欲界。即如端坐攝身,調和氣息,泯然澄靜, 身如雲影,虛豁清淨,而猶見有身心之相,便名爲欲界定,是爲欲界諸天所修之定。 如能修根本禪,離欲界之粗散,便生於色界。

第一重天:四天王天

根據佛教經典,須彌山腹有一山,名犍陀羅山,山有四山頭,四大天王各住一山各護一天下(四大部洲,即東勝神洲南瞻部洲西牛賀洲北俱蘆洲),故四大天王又稱護世四天王 ,是六欲天之第一。

四大天王分別是:
  • 北方多聞天王梵文:Vaisravana;藏名:Rnam-thos-kyi-bu / Jambhala):又名毗沙門,「多聞」意為頗精通佛法,以福、德聞於四方。住須彌山黃金埵,身為綠色,穿甲冑,右持寶(或作寶幡),左手臥神鼠-銀鼠。用以制服魔眾,護持人民財富。又名施財天,是古印度的財神。他負責守護北俱蘆洲,以 夜叉羅剎為多聞天王的部眾. 是『二十諸天』中的第三天王。[1]
  • 東方持國天王梵文:Dhrita-rastra;藏名:Yul-hkhor-bsrun):「持國」意為慈悲為懷,保護眾生,護持國土,故名持國天王。住須彌山白銀埵,身為白色,穿甲胄,手持琵琶 ,是主樂神,表明他要用音樂來使眾生皈依佛教,他負責守護東勝神洲。以 乾闥婆緊那羅、毗舍闍...為持國天王的部眾. 是『二十諸天』中的第四天王。
  • 南方增長天王梵文:Vidradhaka;藏名:Hphags-skyes-po):「增長」意為能傳令眾生,增長善根,護持佛法,故名增長天王。住須彌山琉璃埵,身為青色,穿甲冑,手握寶。為的是保護佛法 ,不受侵犯,他負責守護南瞻部洲。以 鳩盤茶薜荔多...為增長天王的部眾. 是『二十諸天』中的第五天王。
  • 西方廣目天王梵文:Virapaksa;藏名:Mig-mi-bzan,Spyan-mi-bzan):「廣目」意為能以淨天眼隨時觀察世界,護持人民,古名廣目天王。住須彌山水晶埵,身為紅色,穿甲冑,為群領袖 ,故手纏一赤龍(或作赤索),看到有人敵對佛教,即用繩索捉來,使其皈依佛教。他負責守護西牛賀洲 。以 龍王、富單那...為廣目天王的部眾. 是『二十諸天』中的第六天王。

 

第二重天:忉利天

(巴利文:तावतिंस Tāvatiṃsa,梵文:Trayastriṃśa),又意譯為三十三天,是佛教世界中欲界的第二層天,因有三十三個天國而得名。

忉利天位於須彌山頂端,周長一萬由旬。中央為帝釋天,天主帝釋居善現城的忉利天宮。其東西南北四方各有八個天國,一共有33個。忉利天的人身高一由旬,其壽命一千歲,其一日相當於人間一百年,因此其壽命相當於人間三千六百萬年。

以漢傳佛教來說,一般認為玉皇大帝即三十三天之主帝釋,居於忉利天。地藏菩薩本願經就是佛陀上升到忉利天為母親摩耶夫人說法。



第三重天:夜摩天

夜摩,閻魔羅闍梵文यमराजYamaraja),又稱閻摩(梵文यम,Yama)、琰魔閻魔閻羅王閻羅大王夜摩天王剡魔焰摩,梵名之意譯為善時分、善時、善分、妙善、妙時分、妙唱、唱樂等。

夜摩天,乃是欲界六天之第三天,又作夜磨天、焰摩天、炎摩天、蘇夜摩天、須夜摩天、須炎天、離諍天。

據《正法念處經》卷三十六、《立世阿毘曇論》卷六、《佛地經論》卷五、《慧苑音義》卷上等所載,此天界光明赫奕,無晝夜之分,居於其中,時時刻刻受不可思議之歡樂。 生于此天界之天人,身体轻盈洁净,相亲相爱,享受种种欢乐。

據《彰所知論》卷上載,三十三天常與阿修羅諍鬥,夜摩天卻遠離諍鬥,故稱離諍天。得生此天之眾生,乃於不殺生、不偷盜、不邪淫等樂修多作,又自能持戒,教他持戒,修持自他利益者。

夜摩天位於空居天之最初層,即距閻浮提十六萬由旬,距忉利天八萬由旬之上層虛空中;縱廣八萬由旬,範圍包括勢力地、上行地、林光明地、乘處地、遊行地等三十二地。

夜摩天王,稱為牟修樓陀,身量五由旬,宮殿設於勢力地。又有高達一萬由旬之清淨山、無垢山、大清淨山、內像山等四大山及其他諸山,以諸多天花莊嚴,並有種種河池,百千園林周匝圍繞:其殊勝妙樂,遠非忉利天所能及。

夜 摩天壽量為二千歲,其一晝夜相當人間二百年。亦有男娶女嫁婚姻之事,以互相親近,或相抱,即成陰陽和合;兒女隨念之起而由膝上化生,初生即如閻浮提三、四 歲之孩童。 夜摩天王之信仰,始於吠陀時代以降,此天界因係充滿歡樂之光明世界,夙為印度民族所憧憬,亦為亡者所欲往生之處。其後夜摩天王逐漸演變為人死後之審判官, 而成為鬼趣、地獄之主,即所謂之閻魔王,並相信其天界在天空之上層。然該信仰被引入佛教之後,乃置其位於六欲天之第三天。


第四重天:兜率天

兜率天梵語:तुषित Tuṣita巴利Tusita,藏文Dgah-idan又譯作睹史多天、兜駛多天等,意思是「具有歡喜」,意譯知足天、妙足天、喜足天、喜樂天,此天天眾壽量四千歲。一歲十二月,一月三十天。其一晝夜相當於人間四百年,以此換算,其壽量相當於人間五億七千六百萬年。天眾行欲時,男女執手即成陰陽。初生之兒如人間小孩八歲大,色圓滿,衣服自備,七日成人,身長四由旬,天衣長八由旬,廣四由旬,重一銖半。 (《雜阿含經》第三十一卷第八百六十一節)。

此天有內外兩院,外院是凡夫果報天宮,只管享樂,直到福報用盡,屬於天界;內院是彌勒的淨土,菩薩修功圓滿,盡此一生,便可成佛,又名為「一生補處」。

根據佛教理論,每當佛陀降生人世之前,都要先在兜天上為諸天講說佛法。相傳彌勒菩薩能為眾生解說在佛法修行過程中產生的種種疑難,因而在我國古代,自東晉至唐代,有關彌勒的信仰非常盛行,彌勒淨土也是我國早期淨土思想中的一個重要部分。東晉時我國著名的僧人釋道安就是彌勒淨土信仰者,我國佛教史上另一位著名僧人,偉大的旅行家和翻譯家、唐代僧人玄奘法師,也是彌勒淨土的信仰者。

彌勒菩薩,於佛陀住世時,生於南天竺,中途得佛陀的教化,佛陀授記他以後為補處的菩薩,能成佛。菩薩現住兜率內院,說法化行,要經過五十六億七千萬年,才下生人間,於華木園龍華樹下成正覺,於龍華樹下三會,化度一切人天。

釋尊成佛以前,在兜率天,從天降生人間成佛。彌勒成佛的人間淨土,是希望的,還在未來,而彌勒所住的兜率天,卻是現在的,又同屬於欲界,論地區也不算太遠。一生所繫的菩薩,生在兜率天,當然與一般的凡夫天不同。兜率天的彌勒菩薩住處,有清淨莊嚴的福樂,又有菩薩說法,真是兩全其美,成為佛弟子心目中仰望的地方。西元前101~77年在位的錫蘭王──度他伽摩尼(Dut!t!ha-Gaman!I),在臨終時,發願生兜率天,見彌勒菩薩。西元前二世紀,已有上生兜率見彌勒的信仰,這是可以確定的。 《小品般若波羅蜜經》說︰不離般若的菩薩,是從那裡生到人間來的?有的'人中命終,還生人中';有從他方世界生到此間來的;也有'於兜率天上,聞彌勒菩薩說般若波羅蜜,問其中事,於彼命終,來生此間'。特別說到兜率天,正因為兜率天有彌勒菩薩說法。彌勒在兜率天說法,是發願往生兜率天的主要原因。兜率天在一切天中,受到了特別的重視。大乘經說到成佛時的國土清淨,有的就說與兜率天一樣,這可見兜率天信仰的普遍。推重兜率天,不是兜率天的一般,而是有彌勒菩薩說法的地區。 《佛本行集經》說︰一生所繫的菩薩,在兜率天的高幢宮,為諸天說'一百八法明門';《普曜經》也有此說。後代所稱的彌勒內院,也就是兜率天上,一生所繫菩薩所住的清淨區。兜率天上彌勒淨土的信仰,是部派佛教時代就有了的。在大乘的他方淨土興起後,仍留下上升兜率見彌勒的信仰,所以玄奘說︰'西方道俗,並作彌勒業,為同欲界,其行易成。 '等到十方佛說興起,於是他方佛土,有北拘盧洲式的自然,天國式的清淨莊嚴,兜率天宮式的(佛)菩薩說法,成為一般大乘行者所仰望的淨土。
 
《彌勒上生經宗要》雲:“六天之中是其第四天,下三沉欲情重,上二浮逸心多,此第四天欲輕逸少,非沉非浮,莫盪於塵,故名知足。”《慧苑音義》卷上說明此詞有喜事、聚集、距大海三十二萬由旬,於虛空密雲上,縱廣八萬由旬。
 
要生於兜率內院,必須積集往生之因。共通的因包括出離心、依止三寶的心及五力等;不共的因包括彌勒像、對彌勒像繞行或頂禮供養、持​​彌勒名號、誦念與彌勒有關之經典及修持彌勒儀軌或〈兜率百尊儀軌〉等等
 《佛說觀彌勒菩薩上生兜率天經》(摘錄)
佛滅度後,我諸弟子,若有精勤修諸功德,威儀不缺,掃塔塗地,以眾名香妙花供養,行眾三昧,深入正受讀誦經典。如是等人,應當至心,雖不斷結,如得六通。應當繫念,念佛形像,稱彌敕名。如是等輩,若一念頃受八戒齋,修諸淨業,發弘誓願,命終之後,譬如壯士屈申臂頃,即得往生兜率陀天,于蓮華上結加趺坐。百千天子作天伎樂,持天曼陀羅花、摩訶曼陀羅華以散其上,贊言︰‘善哉!善哉!善男子,汝于閻浮提廣修福業,來生此處,此處名兜率陀天。今此天主名曰彌勒,汝當歸依。’

第五重天:化樂天

化樂天梵文:निर्माणरति Nirmāṇarati),梵名須涅蜜陀。音譯作尼摩羅天、維那羅泥天。又作化自在天、化自樂天、不憍樂天、樂無慢天、無貢高天、樂變化天。這裡的一晝夜為人間的八百年。化樂天(或化樂天神) 的壽命為八千歲,之後繼續在輪回中流轉。[1]

另有舊譯化自樂天,或化樂天。新譯樂變化天,或妙變化天。自以通力自在變作妙樂而娛樂,故名。
  • 智度論九曰:『化自樂者,自化五塵而自娛樂,故言化自樂。』
  • 佛地論五曰:『樂變化天,樂自變化,作諸樂具以自娛樂。』
  • 俱舍頌疏世品一曰:『樂變化天,於五欲境自變化故。』可洪音義一曰:『妙變化天,樂變化天王也。
  • 大智度論云:須涅蜜陀,秦言化樂天,唐言樂變化天。』《大智度论》九曰:‘化自乐天。化自乐者,自化五尘而自娱乐故,言化自乐。’
  • 然玄應師有別釋。玄應音義二十三曰:『樂變化天,五孝切。但此天雖有寶女,於變化者心多愛著,於男亦爾,故以名焉。舊言化樂天,音洛,失之久矣。』即愛樂變化男女之意。
  • 仁王經上曰:「若菩薩住十億佛國中,作化樂天王修千億法門。

  六欲天中的第五層為樂變化天,又稱化自在天,化樂天等。相傳生活在這層天中眾生,化五塵而自樂,因此稱為化樂天。

 化樂天之人,自化五塵而自娛樂,故稱化自樂。以人間八百歲爲一日夜,亦以三十日爲一個月,十二個月爲一年。壽長八千歲,故其寿命相当于人间23亿零400万年。身長八由旬,身具常光,男女亦有婚姻,男女互相熟視或相向而笑即成交媾,其子自男女膝上化生,甫生即大如人間十 二歲之孩童。常以須陀味爲粗段食,諸覆蓋等爲微細食。與夜摩天、兜率天、他化自在天等,俱以長壽、端正、多樂三事勝閻浮提。


第六重天:化自在天

他化自在天(梵文:परिनिर्मित वशवर्तिन् Parinirmita-vaśavartin)

此天位於欲界天之最高 所,在距大海百二十八萬由旬虛空密雲之上,縱廣八萬由旬,與忉利天同。於此天界,有優鉢羅花等之水生花及解脫花等之陸生花。

他化妙境, 自在轉故。 無世間心, 同世行事, 於行事交, 瞭然超越, 命終之後, 倘能超出化無化境, 如是一類, 名他化自在天。 如是六欲天最高層, 形雖出動, 心跡尚交, 自此以還, 名為欲界。 正脈雲 : 淫為上首, 故曰淫之重輕以分下上次第 ,又此乃自須彌腰頂二天, 以至空居四天, 共有六重, 皆有飲食, 淫慾. 睡眠, 具足三欲, 故號欲天, 其男女嫁娶, 亦如人間。

是諸上有情, 具沙門梵行, 增長解脫因, 得生他化天。
上根有情類, 持戒亦最上, 功德超越前, 生他化自在。

此天有三事勝於閻浮提,即:長壽、端正、多樂。天眾之壽量為一萬六千歲 ( 約人類九十二億一千六百歲 ) ,其一晝夜約為人間一千六百年,但亦有中夭者。其身 長十六由旬或一拘盧舍半,衣長三十二由旬,廣十六由旬,然重僅半銖。食自然之食。男女相視成婬,欲求子時,隨念而忽化生於膝上。初生時,如人間十歲之孩 童,色貌圓滿,衣服自備。於諸經中,如大阿彌陀經卷上、海龍王經卷四法供養品、商主天子所問經、說無垢稱經卷一序品等皆述及此天之各種莊嚴景象。又於大乘 諸經中,華嚴經七處八會中之第六他化自在天宮會、般若經四處十六會中之第十會他化自在天宮說般若理趣分等,即是於此天之天宮中所宣說者。


起世經 : 一切欲界天眾, 無有處女胎藏 (世雲子宮 ),漆邊生, 天女則在兩股內生。
男女作愛方式 : 眼相顧視 , 熱惱便息。
居住 : 以空為宮殿而居住。
飲食 : 1.有觸. 意思. 識食。2.六欲諸天,乃有段食 , 所餐飲食流入身分支節等, 尋即消化, 無有便穢 ,隨其福德, 飯色有異 , 上者見白, 中者見黃, 下者見赤。
苦樂差別 : 天趣有情 , 多分受用衰腦墮沒之苦。

此天為欲界之主,與色界之主摩醯首羅天,皆為嬈害正法之魔王,乃四魔中之天魔,有「第六天魔王」之稱。佛成道時,來試障害者,亦此天魔也。或言第六天上别有魔之宮殿,魔王住之,非他化天王也。

1.《俱舍頌疏世間品》一曰:“他化自在天,於他化中得自在故。”
2.《智度論》九曰:‘此天奪他所化而自娛樂故言他化自在。
3.《智度論》五曰:‘魔有四種,(中略)四者在六欲頂,别有宮殿。今因果經乃爲自在天王,如此則當第六天。有此兩異,蓋是譯者用義之不同也。’
4. 佛祖統紀二曰:「諸經云:魔波旬在六欲頂,別有宮殿。今因果經乃為自在天王,如此則當第六天。有此兩異,蓋是譯者用義之不同也。」
5. 長阿含經卷二十 忉利天品載,第六天上別有縱廣六千由旬之天魔宮殿。
6. 《阿含經》第31卷第863節所說,此天人壽命一萬六千歲,其一年有十二個月,一月三十日,一日一夜為人間一千六百年,故其壽命相當於人間九十二億一千六百萬年。

又,密教中,此天位於胎藏現圖曼荼羅外金剛部院的北方,共有三位。關於其形像,居中央者,右手豎掌持箭,左拳豎立,朝身舒張頭指持弓;居外側者,右掌豎立,屈中指及無名指,左手持蓮華作拳置於胸前;居內側者,右掌豎立,屈頭指及中指持合蓮,左掌覆於腰際。三昧耶形為弓箭,表徵此天的慾樂自在。

佛學名詞整理(二)佛教三界

佛教三界


三界(梵文त्रैलोक्य trailokya),佛教用語。所謂三界,即世間之三個層次:欲界色界無色界

1. 欲界:地獄、畜生、餓鬼、人、阿修羅、六欲天(四天王天、忉利天、夜摩天、兜率陀天、化樂天、他化自在天)
2. 色界:四禪天(初禪、二禪、三禪、四禪等四天)
3. 無色界:四空天(空無邊處、識無邊處、無所有處、非想非非想處四天)

其中天道中的三大天:欲界六天、色界天、無色界天。而後面二大天,就是全部的色界及無色界。

欲明諸天的住處,須先略知佛教的世界說:一日月繞一須彌山,外圍四大部洲、八中部洲,須彌山下入香水海中,水面以上分上下兩段,下段分為四層,第一層名堅手天,第二層名持鬘天,第三層名恆憍(亦譯常放逸)天,為四天王所統帥之夜*神所居,屬於鬼類,非天道所攝,一說第三層之上還有日月星宿天,為日月星宿諸神所居;第四層為四天王天,與日月在一水平面上。須彌山頂為忉利天,此天與四天王天皆地居,忉利天以上為空居(天宮在虛空中),依次為夜摩、兜率、化樂、他化自在四天。六欲天之上覆一初禪天,與六欲天之下的人等五道眾生所居世界,為一“小世界”,乃宇宙中最小的世界單位。一千小世界之上覆一二禪天,為一“小千世界”;一千個小千世界之上覆一三禪天,為一“中千世界”;一千個中千世界之上覆一四禪天,為一“大千世界“,為宇宙世界海中基本的獨立世界單位。一大千世界為三個千數相乘,故稱“三千大千世界”,總計約有百億日月,亦即百億個小世界。小乘說一三千大千世界為“一佛土”(“一佛剎”),即一佛所教化的範圍、所居淨土。大乘則說大千世界之上還有“世界種”,為梯形,分二十層,每層皆有無量微塵數大千世界,無量微塵數世界種組成一“世界海”,為一佛淨土,在宇宙中有無量無數的世界海。