diff --git "a/21451198\345\215\242\350\266\205/project4/Note/AddNoteViewController.h" "b/21451198\345\215\242\350\266\205/project4/Note/AddNoteViewController.h" new file mode 100644 index 00000000..e14d3d60 --- /dev/null +++ "b/21451198\345\215\242\350\266\205/project4/Note/AddNoteViewController.h" @@ -0,0 +1,17 @@ +// +// AddNoteViewController.h +// Note +// +// Created by jiaoshoujie on 14-11-21. +// Copyright (c) 2014年 ___FULLUSERNAME___. All rights reserved. +// + +#import "ViewController.h" + +@interface AddNoteViewController : ViewController +@property (weak, nonatomic) IBOutlet UITextView *textView; + +@property (nonatomic,strong) NSString *databaseFilePath; +@property (weak, nonatomic) IBOutlet UIBarButtonItem *rightButon; + +@end diff --git "a/21451198\345\215\242\350\266\205/project4/Note/AddNoteViewController.m" "b/21451198\345\215\242\350\266\205/project4/Note/AddNoteViewController.m" new file mode 100644 index 00000000..ec955264 --- /dev/null +++ "b/21451198\345\215\242\350\266\205/project4/Note/AddNoteViewController.m" @@ -0,0 +1,133 @@ +// +// AddNoteViewController.m +// Note +// +// Created by jiaoshoujie on 14-11-21. +// Copyright (c) 2014年 ___FULLUSERNAME___. All rights reserved. +// + +#import "AddNoteViewController.h" +#import "sqlite3.h" +#define kDatabaseName @"database.sqlite3" + +@interface AddNoteViewController () + +@end + +@implementation AddNoteViewController + +@synthesize databaseFilePath; +@synthesize rightButon; + +- (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. + //获取数据库文件路径 + NSArray *paths = NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES); + NSString *documentsDirectory = [paths objectAtIndex:0]; + self.databaseFilePath = [documentsDirectory stringByAppendingPathComponent:kDatabaseName]; +} + +//关闭键盘 +- (IBAction)backgroundTap:(id)sender { + [_textView resignFirstResponder]; +} + +-(void)viewDidAppear:(BOOL)animated{ + +} + +- (void)didReceiveMemoryWarning +{ + [super didReceiveMemoryWarning]; + // Dispose of any resources that can be recreated. +} + +- (IBAction)addNoteAction:(id)sender { + //UIAlertView *alter = [[UIAlertView alloc] initWithTitle:@"提示" message:@"你点击了导航栏右按钮" delegate:self cancelButtonTitle:@"确定" otherButtonTitles:nil, nil]; + //[alter show]; + NSString *title = [[NSString alloc] initWithCString:"完成" encoding:NSUTF8StringEncoding]; + NSLog(@"title:%@,rightButton:%@",title,rightButon.title); + NSLog(@"textView:%@",_textView.text); + if ([title isEqualToString:rightButon.title]&&![[[NSString alloc]initWithCString:"" encoding:NSUTF8StringEncoding]isEqualToString:_textView.text] ) { + [self insertIntoDatabase]; + [rightButon setTitle:@"添加"]; + _textView.text = nil; + }else{ + [rightButon setTitle:@"完成"]; + } +} + +-(void)insertIntoDatabase{ + //打开数据库 + sqlite3 *database; + if (sqlite3_open([self.databaseFilePath UTF8String], &database)!=SQLITE_OK) { + sqlite3_close(database); + NSAssert(0, @"打开数据库失败!"); + } + int last = [self lastTagofNotes]; + //使用约束变量插入数据 + char *update = "INSERT OR REPLACE INTO NOTES (TAG, DETAILS, THEDATETIME) VALUES (?,?,?);"; + sqlite3_stmt *stmt; + if (sqlite3_prepare_v2(database, update, -1, &stmt, nil) == SQLITE_OK) { + sqlite3_bind_int(stmt, 1, last+1); + sqlite3_bind_text(stmt, 2, [_textView.text UTF8String], -1, NULL); + NSDate* date = [NSDate date]; + NSDateFormatter* formatter = [[NSDateFormatter alloc] init]; + [formatter setDateFormat:@"yyyy-MM-dd HH:MM:SS"]; + NSString* str = [formatter stringFromDate:date]; + NSLog(@"现在时间是:%@",str); + sqlite3_bind_text(stmt, 3, [str UTF8String], -1, NULL); + } + char *errorMsg = NULL; + if (sqlite3_step(stmt) != SQLITE_DONE) { + NSAssert(0, @"更新数据库表FIELDS出错:%s",errorMsg); + } + sqlite3_finalize(stmt); + //关闭数据库 + sqlite3_close(database); +} + +-(int)lastTagofNotes{ + //打开数据库 + sqlite3 *database; + if (sqlite3_open([self.databaseFilePath UTF8String], &database)!=SQLITE_OK) { + sqlite3_close(database); + NSAssert(0, @"打开数据库失败!"); + } + int lastTag = 0; + char *update = "SELECT MAX(TAG) FROM NOTES"; + sqlite3_stmt *stmt; + if (sqlite3_prepare_v2(database, update, -1, &stmt, nil) == SQLITE_OK){ + while (sqlite3_step(stmt)==SQLITE_ROW){ + lastTag = sqlite3_column_int(stmt, 0); + } + sqlite3_finalize(stmt); + } + sqlite3_close(database); + + return lastTag; +} + +/* +#pragma mark - Navigation + +// In a storyboard-based application, you will often want to do a little preparation before navigation +- (void)prepareForSegue:(UIStoryboardSegue *)segue sender:(id)sender +{ + // Get the new view controller using [segue destinationViewController]. + // Pass the selected object to the new view controller. +} +*/ + +@end diff --git "a/21451198\345\215\242\350\266\205/project4/Note/AppDelegate.h" "b/21451198\345\215\242\350\266\205/project4/Note/AppDelegate.h" new file mode 100644 index 00000000..2e919afd --- /dev/null +++ "b/21451198\345\215\242\350\266\205/project4/Note/AppDelegate.h" @@ -0,0 +1,14 @@ +// +// AppDelegate.h +// Note +// +// Created by jiaoshoujie on 14-11-21. +// Copyright (c) 2014年 ___FULLUSERNAME___. All rights reserved. +// +#import + +@interface AppDelegate : UIResponder + +@property (strong, nonatomic) UIWindow *window; + +@end diff --git "a/21451198\345\215\242\350\266\205/project4/Note/AppDelegate.m" "b/21451198\345\215\242\350\266\205/project4/Note/AppDelegate.m" new file mode 100644 index 00000000..98e7a851 --- /dev/null +++ "b/21451198\345\215\242\350\266\205/project4/Note/AppDelegate.m" @@ -0,0 +1,46 @@ +// +// AppDelegate.m +// Note +// +// Created by jiaoshoujie on 14-11-21. +// Copyright (c) 2014年 ___FULLUSERNAME___. All rights reserved. +// + +#import "AppDelegate.h" + +@implementation AppDelegate + +- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions +{ + // Override point for customization after application launch. + return YES; +} + +- (void)applicationWillResignActive:(UIApplication *)application +{ + // Sent when the application is about to move from active to inactive state. This can occur for certain types of temporary interruptions (such as an incoming phone call or SMS message) or when the user quits the application and it begins the transition to the background state. + // Use this method to pause ongoing tasks, disable timers, and throttle down OpenGL ES frame rates. Games should use this method to pause the game. +} + +- (void)applicationDidEnterBackground:(UIApplication *)application +{ + // Use this method to release shared resources, save user data, invalidate timers, and store enough application state information to restore your application to its current state in case it is terminated later. + // If your application supports background execution, this method is called instead of applicationWillTerminate: when the user quits. +} + +- (void)applicationWillEnterForeground:(UIApplication *)application +{ + // Called as part of the transition from the background to the inactive state; here you can undo many of the changes made on entering the background. +} + +- (void)applicationDidBecomeActive:(UIApplication *)application +{ + // Restart any tasks that were paused (or not yet started) while the application was inactive. If the application was previously in the background, optionally refresh the user interface. +} + +- (void)applicationWillTerminate:(UIApplication *)application +{ + // Called when the application is about to terminate. Save data if appropriate. See also applicationDidEnterBackground:. +} + +@end diff --git "a/21451198\345\215\242\350\266\205/project4/Note/Base.lproj/Main.storyboard" "b/21451198\345\215\242\350\266\205/project4/Note/Base.lproj/Main.storyboard" new file mode 100644 index 00000000..d56481c8 --- /dev/null +++ "b/21451198\345\215\242\350\266\205/project4/Note/Base.lproj/Main.storyboard" @@ -0,0 +1,168 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git "a/21451198\345\215\242\350\266\205/project4/Note/Note-Info.plist" "b/21451198\345\215\242\350\266\205/project4/Note/Note-Info.plist" new file mode 100644 index 00000000..ffba6bfc --- /dev/null +++ "b/21451198\345\215\242\350\266\205/project4/Note/Note-Info.plist" @@ -0,0 +1,40 @@ + + + + + CFBundleDevelopmentRegion + en + CFBundleDisplayName + ${PRODUCT_NAME} + CFBundleExecutable + ${EXECUTABLE_NAME} + CFBundleIdentifier + com.funmi.test.${PRODUCT_NAME:rfc1034identifier} + CFBundleInfoDictionaryVersion + 6.0 + CFBundleName + ${PRODUCT_NAME} + CFBundlePackageType + APPL + CFBundleShortVersionString + 1.0 + CFBundleSignature + ???? + CFBundleVersion + 1.0 + LSRequiresIPhoneOS + + UIMainStoryboardFile + Main + UIRequiredDeviceCapabilities + + armv7 + + UISupportedInterfaceOrientations + + UIInterfaceOrientationPortrait + UIInterfaceOrientationLandscapeLeft + UIInterfaceOrientationLandscapeRight + + + diff --git "a/21451198\345\215\242\350\266\205/project4/Note/Note-Prefix.pch" "b/21451198\345\215\242\350\266\205/project4/Note/Note-Prefix.pch" new file mode 100644 index 00000000..82a2bb45 --- /dev/null +++ "b/21451198\345\215\242\350\266\205/project4/Note/Note-Prefix.pch" @@ -0,0 +1,16 @@ +// +// Prefix header +// +// The contents of this file are implicitly included at the beginning of every source file. +// + +#import + +#ifndef __IPHONE_5_0 +#warning "This project uses features only available in iOS SDK 5.0 and later." +#endif + +#ifdef __OBJC__ + #import + #import +#endif diff --git "a/21451198\345\215\242\350\266\205/project4/Note/Note.h" "b/21451198\345\215\242\350\266\205/project4/Note/Note.h" new file mode 100644 index 00000000..0587a34d --- /dev/null +++ "b/21451198\345\215\242\350\266\205/project4/Note/Note.h" @@ -0,0 +1,17 @@ +// +// Note.h +// Note +// +// Created by jiaoshoujie on 14-11-21. +// Copyright (c) 2014年 ___FULLUSERNAME___. All rights reserved. +// + +#import + +@interface Note : NSObject + +@property (nonatomic, assign) int tag; +@property (nonatomic ,strong) NSString *dateTime; +@property (nonatomic, strong) NSString *detail; + +@end diff --git "a/21451198\345\215\242\350\266\205/project4/Note/Note.m" "b/21451198\345\215\242\350\266\205/project4/Note/Note.m" new file mode 100644 index 00000000..efba8ae5 --- /dev/null +++ "b/21451198\345\215\242\350\266\205/project4/Note/Note.m" @@ -0,0 +1,17 @@ +// +// Note.m +// Note +// +// Created by jiaoshoujie on 14-11-21. +// Copyright (c) 2014年 ___FULLUSERNAME___. All rights reserved. +// + +#import "Note.h" + +@implementation Note + +@synthesize dateTime; +@synthesize detail; +@synthesize tag; + +@end diff --git "a/21451198\345\215\242\350\266\205/project4/Note/NoteListTableViewController.h" "b/21451198\345\215\242\350\266\205/project4/Note/NoteListTableViewController.h" new file mode 100644 index 00000000..c9ca3fb7 --- /dev/null +++ "b/21451198\345\215\242\350\266\205/project4/Note/NoteListTableViewController.h" @@ -0,0 +1,18 @@ +// +// NoteListTableViewController.h +// Note +// +// Created by jiaoshoujie on 14-11-21. +// Copyright (c) 2014年 ___FULLUSERNAME___. All rights reserved. +// + +#import + +@interface NoteListTableViewController : UITableViewController{ + NSMutableArray *notes; +} + +@property (nonatomic,strong) NSString *databaseFilePath; +@property (strong, nonatomic) IBOutlet UITableView *notesTableView; + +@end diff --git "a/21451198\345\215\242\350\266\205/project4/Note/NoteListTableViewController.m" "b/21451198\345\215\242\350\266\205/project4/Note/NoteListTableViewController.m" new file mode 100644 index 00000000..922e3851 --- /dev/null +++ "b/21451198\345\215\242\350\266\205/project4/Note/NoteListTableViewController.m" @@ -0,0 +1,267 @@ +// +// NoteListTableViewController.m +// Note +// +// Created by jiaoshoujie on 14-11-21. +// Copyright (c) 2014年 ___FULLUSERNAME___. All rights reserved. +// + +#import "NoteListTableViewController.h" +#import "sqlite3.h" +#import "Note.h" +#import "ShowNoteViewController.h" + +#define kDatabaseName @"database.sqlite3" + +@interface NoteListTableViewController () + +@end + +@implementation NoteListTableViewController + +@synthesize databaseFilePath; + +- (id)initWithStyle:(UITableViewStyle)style +{ + self = [super initWithStyle:style]; + if (self) { + // Custom initialization + } + return self; +} + +- (void)viewDidLoad +{ + [super viewDidLoad]; + + [self showNotes]; + NSLog(@"count:%d",[self countofNotes]); + + // Uncomment the following line to preserve selection between presentations. + // self.clearsSelectionOnViewWillAppear = NO; + + // Uncomment the following line to display an Edit button in the navigation bar for this view controller. + // self.navigationItem.rightBarButtonItem = self.editButtonItem; +} + +-(void)viewWillAppear:(BOOL)animated{ + [self showNotes]; +} + +-(int)countofNotes{ + //打开数据库 + sqlite3 *database; + if (sqlite3_open([self.databaseFilePath UTF8String], &database)!=SQLITE_OK) { + sqlite3_close(database); + NSAssert(0, @"打开数据库失败!"); + } + int count = 0; + char *update = "SELECT COUNT(*) FROM NOTES"; + sqlite3_stmt *stmt; + if (sqlite3_prepare_v2(database, update, -1, &stmt, nil) == SQLITE_OK){ + while (sqlite3_step(stmt)==SQLITE_ROW){ + count = sqlite3_column_int(stmt, 0); + } + sqlite3_finalize(stmt); + } + sqlite3_close(database); + + return count; +} + +-(void)showNotes{ + //获取数据库文件路径 + NSArray *paths = NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES); + NSString *documentsDirectory = [paths objectAtIndex:0]; + self.databaseFilePath = [documentsDirectory stringByAppendingPathComponent:kDatabaseName]; + + //打开或创建数据库 + sqlite3 *database; + if (sqlite3_open([self.databaseFilePath UTF8String], &database) != SQLITE_OK) { + sqlite3_close(database); + NSAssert(0, @"打开数据库失败"); + } + //创建数据库表 + NSString *createSQL = @"CREATE TABLE IF NOT EXISTS NOTES (TAG INTEGER PRIMARY KEY,DETAILS TEXT,THEDATETIME TETX);"; + char *errorMsg; + if (sqlite3_exec(database, [createSQL UTF8String], NULL, NULL, &errorMsg) != SQLITE_OK) { + sqlite3_close(database); + NSAssert(0, @"创建数据库变错误:%s", errorMsg); + } + + notes = [NSMutableArray arrayWithCapacity:20]; + + //执行查询 + NSString *query = @"SELECT TAG, DETAILS, THEDATETIME FROM NOTES ORDER BY TAG DESC"; + sqlite3_stmt *statement; + if (sqlite3_prepare(database, [query UTF8String], -1, &statement, nil) == SQLITE_OK) { + //依次读取数据库表格NOTES中每行的内容,并显示在对应的TextField + while (sqlite3_step(statement) == SQLITE_ROW) { + //获取数据 + int tag = sqlite3_column_int(statement, 0); + char *details = (char *)sqlite3_column_text(statement, 1); + char *thedatetime = (char *)sqlite3_column_text(statement, 2); + Note *note = [[Note alloc]init]; + note.tag = tag; + note.detail = [[NSString alloc]initWithCString:details encoding:NSUTF8StringEncoding]; + note.dateTime = [[NSString alloc]initWithCString:thedatetime encoding:NSUTF8StringEncoding]; + NSLog(@"tag:%d,detail:%@,datetime:%@",tag,note.detail,note.dateTime); + [notes addObject:note]; + //根据tag获得TextField + //UITextField *textField = (UITextField *)[self.view viewWithTag:tag]; + // 设置文本 + //textField.text = [[NSString alloc] initWithUTF8String:rowData]; + } + sqlite3_finalize(statement); + } + //关闭数据库 + sqlite3_close(database); + //刷新一下tableView + [_notesTableView reloadData]; +} + +- (Note *)selectNotebyTag:(int)tag{ + //打开数据库 + sqlite3 *database; + if (sqlite3_open([self.databaseFilePath UTF8String], &database)!=SQLITE_OK) { + sqlite3_close(database); + NSAssert(0, @"打开数据库失败!"); + } + Note *note = [[Note alloc] init]; + char *sql = "SELECT TAG,DETAILS,THEDATETIME FORM NOTES WHERE TAG = ?;"; + sqlite3_stmt *stmt; + if (sqlite3_prepare_v2(database, sql, -1, &stmt, NULL) == SQLITE_OK) { + + while (sqlite3_step(stmt) == SQLITE_ROW) { + sqlite3_bind_int(stmt, 1, tag); + int tag = sqlite3_column_int(stmt, 0); + char *details = (char*)sqlite3_column_text(stmt, 1); + char *dateTime = (char*)sqlite3_column_text(stmt, 2); + note.tag = tag; + note.detail = [[NSString alloc]initWithCString:details encoding:NSUTF8StringEncoding]; + note.dateTime = [[NSString alloc]initWithCString:dateTime encoding:NSUTF8StringEncoding]; + } + } + sqlite3_close(database); + return note; +} + +- (void)deleteNoteByTag:(int)tag{ + //打开数据库 + sqlite3 *database; + if (sqlite3_open([self.databaseFilePath UTF8String], &database)!=SQLITE_OK) { + sqlite3_close(database); + NSAssert(0, @"打开数据库失败!"); + } + sqlite3_stmt *stmt; + char *sql = "DELETE FROM NOTES where tag = ?"; + if (sqlite3_prepare_v2(database, sql, -1, &stmt, NULL) == SQLITE_OK) { + sqlite3_bind_int(stmt, 1, tag); + if (sqlite3_step(stmt) == SQLITE_ERROR) { + NSLog(@"Error: failed to delete the database with message."); + //关闭数据库 + sqlite3_close(database); + } + } + sqlite3_close(database); + [_notesTableView reloadData]; +} + +//通过Segue传递TableView中的数据 +- (void)prepareForSegue:(UIStoryboardSegue *)segue sender:(id)sender{ + if ([segue.identifier isEqualToString:@"showNoteDetailsSegue"]) { + NSIndexPath *indexPath = [self.notesTableView indexPathForSelectedRow]; + ShowNoteViewController *showNoteViewController = segue.destinationViewController; + showNoteViewController.note = [notes objectAtIndex:indexPath.row]; + } +} + +- (void)didReceiveMemoryWarning +{ + [super didReceiveMemoryWarning]; + // Dispose of any resources that can be recreated. +} + +#pragma mark - Table view data source + +- (NSInteger)numberOfSectionsInTableView:(UITableView *)tableView +{ +//#warning Potentially incomplete method implementation. + // Return the number of sections. + return 1; +} + +- (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section +{ +//#warning Incomplete method implementation. + // Return the number of rows in the section. + return [notes count]; +} + + +- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath +{ +// UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:@"NoteCell" forIndexPath:indexPath]; + UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:@"NoteCell"]; + Note *note = [notes objectAtIndex:indexPath.row]; + cell.textLabel.text = [[NSString alloc]initWithString:note.detail]; + cell.detailTextLabel.text = note.dateTime; + // Configure the cell... + return cell; +} + + +/* +// Override to support conditional editing of the table view. +- (BOOL)tableView:(UITableView *)tableView canEditRowAtIndexPath:(NSIndexPath *)indexPath +{ + // Return NO if you do not want the specified item to be editable. + return YES; +} +*/ + + +// Override to support editing the table view. +- (void)tableView:(UITableView *)tableView commitEditingStyle:(UITableViewCellEditingStyle)editingStyle forRowAtIndexPath:(NSIndexPath *)indexPath +{ + if (editingStyle == UITableViewCellEditingStyleDelete) { + // Delete the row from the data source + //[tableView deleteRowsAtIndexPaths:@[indexPath] withRowAnimation:UITableViewRowAnimationFade]; + Note *note = [notes objectAtIndex:indexPath.row]; + [self deleteNoteByTag:note.tag]; + [notes removeObjectAtIndex:indexPath.row]; + [tableView deleteRowsAtIndexPaths:[NSArray arrayWithObject:indexPath] withRowAnimation:UITableViewRowAnimationFade]; + } else if (editingStyle == UITableViewCellEditingStyleInsert) { + // Create a new instance of the appropriate class, insert it into the array, and add a new row to the table view + } +} + + +/* +// Override to support rearranging the table view. +- (void)tableView:(UITableView *)tableView moveRowAtIndexPath:(NSIndexPath *)fromIndexPath toIndexPath:(NSIndexPath *)toIndexPath +{ +} +*/ + +/* +// Override to support conditional rearranging of the table view. +- (BOOL)tableView:(UITableView *)tableView canMoveRowAtIndexPath:(NSIndexPath *)indexPath +{ + // Return NO if you do not want the item to be re-orderable. + return YES; +} +*/ + +/* +#pragma mark - Navigation + +// In a storyboard-based application, you will often want to do a little preparation before navigation +- (void)prepareForSegue:(UIStoryboardSegue *)segue sender:(id)sender +{ + // Get the new view controller using [segue destinationViewController]. + // Pass the selected object to the new view controller. +} +*/ + +@end diff --git "a/21451198\345\215\242\350\266\205/project4/Note/ShowNoteViewController.h" "b/21451198\345\215\242\350\266\205/project4/Note/ShowNoteViewController.h" new file mode 100644 index 00000000..373c0b85 --- /dev/null +++ "b/21451198\345\215\242\350\266\205/project4/Note/ShowNoteViewController.h" @@ -0,0 +1,21 @@ +// +// ShowNoteViewController.h +// Note +// +// Created by jiaoshoujie on 14-11-21. +// Copyright (c) 2014年 ___FULLUSERNAME___. All rights reserved. +// + +#import "ViewController.h" +#import "Note.h" + +@interface ShowNoteViewController : ViewController{ + +} +@property (nonatomic,strong) NSString *databaseFilePath; +@property (nonatomic, strong) Note *note; +@property (weak, nonatomic) IBOutlet UITextView *noteTextView; +@property (weak, nonatomic) IBOutlet UINavigationItem *noteNavItem; +@property (weak, nonatomic) IBOutlet UILabel *noteDateLabel; + +@end diff --git "a/21451198\345\215\242\350\266\205/project4/Note/ShowNoteViewController.m" "b/21451198\345\215\242\350\266\205/project4/Note/ShowNoteViewController.m" new file mode 100644 index 00000000..c2f281fc --- /dev/null +++ "b/21451198\345\215\242\350\266\205/project4/Note/ShowNoteViewController.m" @@ -0,0 +1,102 @@ +// +// ShowNoteViewController.m +// Note +// +// Created by jiaoshoujie on 14-11-21. +// Copyright (c) 2014年 ___FULLUSERNAME___. All rights reserved. +// + +#import "ShowNoteViewController.h" +#import "sqlite3.h" + +#define kDatabaseName @"database.sqlite3" + +@interface ShowNoteViewController () + +@end + +@implementation ShowNoteViewController + +- (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. + //获取数据库文件路径 + NSArray *paths = NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES); + NSString *documentsDirectory = [paths objectAtIndex:0]; + self.databaseFilePath = [documentsDirectory stringByAppendingPathComponent:kDatabaseName]; + [self showNoteDetails]; +} + +- (void)didReceiveMemoryWarning +{ + [super didReceiveMemoryWarning]; + // Dispose of any resources that can be recreated. +} + +- (void)showNoteDetails{ + self.noteTextView.text = self.note.detail; + self.noteNavItem.title = self.note.detail; + self.noteDateLabel.text = self.note.dateTime; +} + + +- (IBAction)updateNotesAction:(id)sender { + [self updateNote]; +} + +//关闭键盘 +- (IBAction)backgroundTap:(id)sender { + [_noteTextView resignFirstResponder]; +} + +- (void)updateNote{ + //打开数据库 + sqlite3 *database; + if (sqlite3_open([self.databaseFilePath UTF8String], &database)!=SQLITE_OK) { + sqlite3_close(database); + NSAssert(0, @"打开数据库失败!"); + } + //使用约束变量插入数据 + char *update = "INSERT OR REPLACE INTO NOTES (TAG, DETAILS, THEDATETIME) VALUES (?,?,?);"; + sqlite3_stmt *stmt; + if (sqlite3_prepare_v2(database, update, -1, &stmt, nil) == SQLITE_OK) { + sqlite3_bind_int(stmt, 1, self.note.tag); + sqlite3_bind_text(stmt, 2, [_noteTextView.text UTF8String], -1, NULL); + NSDate* date = [NSDate date]; + NSDateFormatter* formatter = [[NSDateFormatter alloc] init]; + [formatter setDateFormat:@"yyyy-MM-dd HH:MM:SS"]; + NSString* str = [formatter stringFromDate:date]; + NSLog(@"现在时间是:%@",str); + sqlite3_bind_text(stmt, 3, [str UTF8String], -1, NULL); + } + char *errorMsg = NULL; + if (sqlite3_step(stmt) != SQLITE_DONE) { + NSAssert(0, @"更新数据库表FIELDS出错:%s",errorMsg); + } + sqlite3_finalize(stmt); + //关闭数据库 + sqlite3_close(database); +} + +/* +#pragma mark - Navigation + +// In a storyboard-based application, you will often want to do a little preparation before navigation +- (void)prepareForSegue:(UIStoryboardSegue *)segue sender:(id)sender +{ + // Get the new view controller using [segue destinationViewController]. + // Pass the selected object to the new view controller. +} +*/ + +@end diff --git "a/21451198\345\215\242\350\266\205/project4/Note/ViewController.h" "b/21451198\345\215\242\350\266\205/project4/Note/ViewController.h" new file mode 100644 index 00000000..70220fd6 --- /dev/null +++ "b/21451198\345\215\242\350\266\205/project4/Note/ViewController.h" @@ -0,0 +1,12 @@ +// +// ViewController.h +// Note +// +// Created by jiaoshoujie on 14-11-21. +// Copyright (c) 2014年 ___FULLUSERNAME___. All rights reserved. +// +#import + +@interface ViewController : UIViewController + +@end diff --git "a/21451198\345\215\242\350\266\205/project4/Note/ViewController.m" "b/21451198\345\215\242\350\266\205/project4/Note/ViewController.m" new file mode 100644 index 00000000..2a89d37a --- /dev/null +++ "b/21451198\345\215\242\350\266\205/project4/Note/ViewController.m" @@ -0,0 +1,29 @@ +// +// ViewController.m +// Note +// +// Created by jiaoshoujie on 14-11-21. +// Copyright (c) 2014年 ___FULLUSERNAME___. All rights reserved. +// + +#import "ViewController.h" + +@interface ViewController () + +@end + +@implementation ViewController + +- (void)viewDidLoad +{ + [super viewDidLoad]; + // Do any additional setup after loading the view, typically from a nib. +} + +- (void)didReceiveMemoryWarning +{ + [super didReceiveMemoryWarning]; + // Dispose of any resources that can be recreated. +} + +@end diff --git "a/21451198\345\215\242\350\266\205/project4/Note/main.m" "b/21451198\345\215\242\350\266\205/project4/Note/main.m" new file mode 100644 index 00000000..389f71aa --- /dev/null +++ "b/21451198\345\215\242\350\266\205/project4/Note/main.m" @@ -0,0 +1,18 @@ +// +// main.m +// Note +// +// Created by jiaoshoujie on 14-11-21. +// Copyright (c) 2014ๅนด ___FULLUSERNAME___. All rights reserved. +// + +#import + +#import "AppDelegate.h" + +int main(int argc, char * argv[]) +{ + @autoreleasepool { + return UIApplicationMain(argc, argv, nil, NSStringFromClass([AppDelegate class])); + } +} diff --git "a/21451198\345\215\242\350\266\205/project5/MyPlane/AppDelegate.h" "b/21451198\345\215\242\350\266\205/project5/MyPlane/AppDelegate.h" new file mode 100644 index 00000000..e07136bf --- /dev/null +++ "b/21451198\345\215\242\350\266\205/project5/MyPlane/AppDelegate.h" @@ -0,0 +1,28 @@ +// +// AppDelegate.h +// MyPlane +// +// Created by jiaoshoujie on 14-12-12. +// Copyright jiaoshoujie 2014年. All rights reserved. +// + +#import +#import "cocos2d.h" + +// Added only for iOS 6 support +@interface MyNavigationController : UINavigationController +@end + +@interface AppController : NSObject +{ + UIWindow *window_; + MyNavigationController *navController_; + + CCDirectorIOS *director_; // weak ref +} + +@property (nonatomic, retain) UIWindow *window; +@property (readonly) MyNavigationController *navController; +@property (readonly) CCDirectorIOS *director; + +@end diff --git "a/21451198\345\215\242\350\266\205/project5/MyPlane/AppDelegate.m" "b/21451198\345\215\242\350\266\205/project5/MyPlane/AppDelegate.m" new file mode 100644 index 00000000..311e02ed --- /dev/null +++ "b/21451198\345\215\242\350\266\205/project5/MyPlane/AppDelegate.m" @@ -0,0 +1,216 @@ +// +// AppDelegate.m +// MyPlane +// +// Created by jiaoshoujie on 14-12-12. +// Copyright jiaoshoujie 2014年. All rights reserved. +// + +#import "cocos2d.h" + +#import "AppDelegate.h" +#import "IntroLayer.h" + +@implementation MyNavigationController + +// The available orientations should be defined in the Info.plist file. +// And in iOS 6+ only, you can override it in the Root View controller in the "supportedInterfaceOrientations" method. +// Only valid for iOS 6+. NOT VALID for iOS 4 / 5. + + +#if __IPHONE_OS_VERSION_MAX_ALLOWED >= __IPHONE_6_0 + +- (NSUInteger)application:(UIApplication *)application supportedInterfaceOrientationsForWindow:(UIWindow *)window +{ + return UIInterfaceOrientationMaskAll; +} + +#endif + +#if __IPHONE_OS_VERSION_MAX_ALLOWED < __IPHONE_6_0 + +-(NSUInteger)supportedInterfaceOrientations { + + // iPhone only + if( [[UIDevice currentDevice] userInterfaceIdiom] == UIUserInterfaceIdiomPhone ) + return UIInterfaceOrientationMaskLandscape; + + // iPad only + return UIInterfaceOrientationPortraitUpsideDown; +} + + + +#endif + +// Supported orientations. Customize it for your own needs +// Only valid on iOS 4 / 5. NOT VALID for iOS 6. +- (BOOL)shouldAutorotateToInterfaceOrientation:(UIInterfaceOrientation)interfaceOrientation +{ + // iPhone only + if( [[UIDevice currentDevice] userInterfaceIdiom] == UIUserInterfaceIdiomPhone ) + return UIInterfaceOrientationIsPortrait(interfaceOrientation); + + // iPad only + // iPhone only + return UIInterfaceOrientationIsPortrait(interfaceOrientation); +} + +// This is needed for iOS4 and iOS5 in order to ensure +// that the 1st scene has the correct dimensions +// This is not needed on iOS6 and could be added to the application:didFinish... +-(void) directorDidReshapeProjection:(CCDirector*)director +{ + if(director.runningScene == nil) { + // Add the first scene to the stack. The director will draw it immediately into the framebuffer. (Animation is started automatically when the view is displayed.) + // and add the scene to the stack. The director will run it when it automatically when the view is displayed. + [director runWithScene: [IntroLayer scene]]; + } +} +@end + + +@implementation AppController + +@synthesize window=window_, navController=navController_, director=director_; + +- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions +{ + // Create the main window + window_ = [[UIWindow alloc] initWithFrame:[[UIScreen mainScreen] bounds]]; + + + // CCGLView creation + // viewWithFrame: size of the OpenGL view. For full screen use [_window bounds] + // - Possible values: any CGRect + // pixelFormat: Format of the render buffer. Use RGBA8 for better color precision (eg: gradients). But it takes more memory and it is slower + // - Possible values: kEAGLColorFormatRGBA8, kEAGLColorFormatRGB565 + // depthFormat: Use stencil if you plan to use CCClippingNode. Use Depth if you plan to use 3D effects, like CCCamera or CCNode#vertexZ + // - Possible values: 0, GL_DEPTH_COMPONENT24_OES, GL_DEPTH24_STENCIL8_OES + // sharegroup: OpenGL sharegroup. Useful if you want to share the same OpenGL context between different threads + // - Possible values: nil, or any valid EAGLSharegroup group + // multiSampling: Whether or not to enable multisampling + // - Possible values: YES, NO + // numberOfSamples: Only valid if multisampling is enabled + // - Possible values: 0 to glGetIntegerv(GL_MAX_SAMPLES_APPLE) + CCGLView *glView = [CCGLView viewWithFrame:[window_ bounds] + pixelFormat:kEAGLColorFormatRGB565 + depthFormat:0 + preserveBackbuffer:NO + sharegroup:nil + multiSampling:NO + numberOfSamples:0]; + + director_ = (CCDirectorIOS*) [CCDirector sharedDirector]; + + director_.wantsFullScreenLayout = YES; + + // Display FSP and SPF + [director_ setDisplayStats:YES]; + + // set FPS at 60 + [director_ setAnimationInterval:1.0/60]; + + // attach the openglView to the director + [director_ setView:glView]; + + // 2D projection + [director_ setProjection:kCCDirectorProjection2D]; + // [director setProjection:kCCDirectorProjection3D]; + + // Enables High Res mode (Retina Display) on iPhone 4 and maintains low res on all other devices + if( ! [director_ enableRetinaDisplay:YES] ) { + [[CCSpriteFrameCache sharedSpriteFrameCache]addSpriteFramesWithFile:@"gameArts.plist"]; + CCLOG(@"Retina Display Not supported"); + }else { + [[CCSpriteFrameCache sharedSpriteFrameCache]addSpriteFramesWithFile:@"gameArts-hd.plist"]; + } + + + // Default texture format for PNG/BMP/TIFF/JPEG/GIF images + // It can be RGBA8888, RGBA4444, RGB5_A1, RGB565 + // You can change this setting at any time. + [CCTexture2D setDefaultAlphaPixelFormat:kCCTexture2DPixelFormat_RGBA8888]; + + // If the 1st suffix is not found and if fallback is enabled then fallback suffixes are going to searched. If none is found, it will try with the name without suffix. + // On iPad HD : "-ipadhd", "-ipad", "-hd" + // On iPad : "-ipad", "-hd" + // On iPhone HD: "-hd" + CCFileUtils *sharedFileUtils = [CCFileUtils sharedFileUtils]; + [sharedFileUtils setEnableFallbackSuffixes:NO]; // Default: NO. No fallback suffixes are going to be used + [sharedFileUtils setiPhoneRetinaDisplaySuffix:@"-hd"]; // Default on iPhone RetinaDisplay is "-hd" + [sharedFileUtils setiPadSuffix:@"-ipad"]; // Default on iPad is "ipad" + [sharedFileUtils setiPadRetinaDisplaySuffix:@"-ipadhd"]; // Default on iPad RetinaDisplay is "-ipadhd" + + // Assume that PVR images have premultiplied alpha + [CCTexture2D PVRImagesHavePremultipliedAlpha:YES]; + + // Create a Navigation Controller with the Director + navController_ = [[MyNavigationController alloc] initWithRootViewController:director_]; + navController_.navigationBarHidden = YES; + + // for rotation and other messages + [director_ setDelegate:navController_]; + + // set the Navigation Controller as the root view controller + [window_ setRootViewController:navController_]; + + // make main window visible + [window_ makeKeyAndVisible]; + + return YES; +} + +// getting a call, pause the game +-(void) applicationWillResignActive:(UIApplication *)application +{ + if( [navController_ visibleViewController] == director_ ) + [director_ pause]; +} + +// call got rejected +-(void) applicationDidBecomeActive:(UIApplication *)application +{ + [[CCDirector sharedDirector] setNextDeltaTimeZero:YES]; + if( [navController_ visibleViewController] == director_ ) + [director_ resume]; +} + +-(void) applicationDidEnterBackground:(UIApplication*)application +{ + if( [navController_ visibleViewController] == director_ ) + [director_ stopAnimation]; +} + +-(void) applicationWillEnterForeground:(UIApplication*)application +{ + if( [navController_ visibleViewController] == director_ ) + [director_ startAnimation]; +} + +// application will be killed +- (void)applicationWillTerminate:(UIApplication *)application +{ + CC_DIRECTOR_END(); +} + +// purge memory +- (void)applicationDidReceiveMemoryWarning:(UIApplication *)application +{ + [[CCDirector sharedDirector] purgeCachedData]; +} + +// next delta time will be zero +-(void) applicationSignificantTimeChange:(UIApplication *)application +{ + [[CCDirector sharedDirector] setNextDeltaTimeZero:YES]; +} + +- (void) dealloc +{ + [window_ release]; + [navController_ release]; + + [super dealloc]; +} +@end diff --git "a/21451198\345\215\242\350\266\205/project5/MyPlane/CCFoePlane.h" "b/21451198\345\215\242\350\266\205/project5/MyPlane/CCFoePlane.h" new file mode 100644 index 00000000..099ac188 --- /dev/null +++ "b/21451198\345\215\242\350\266\205/project5/MyPlane/CCFoePlane.h" @@ -0,0 +1,16 @@ +// +// CCFoePlane.h +// MyPlane +// +// Created by jiaoshoujie on 14-12-12. +// Copyright (c) 2014年 jiaoshoujie. All rights reserved. +// + +#import "CCSprite.h" + +@interface CCFoePlane : CCSprite +@property (readwrite) int planeType; +@property (readwrite) int hp; +@property (readwrite) int speed; + +@end diff --git "a/21451198\345\215\242\350\266\205/project5/MyPlane/CCFoePlane.m" "b/21451198\345\215\242\350\266\205/project5/MyPlane/CCFoePlane.m" new file mode 100644 index 00000000..25b44e17 --- /dev/null +++ "b/21451198\345\215\242\350\266\205/project5/MyPlane/CCFoePlane.m" @@ -0,0 +1,13 @@ +// +// CCFoePlane.m +// MyPlane +// +// Created by jiaoshoujie on 14-12-12. +// Copyright (c) 2014年 jiaoshoujie. All rights reserved. +// + +#import "CCFoePlane.h" + +@implementation CCFoePlane + +@end diff --git "a/21451198\345\215\242\350\266\205/project5/MyPlane/CCProps.h" "b/21451198\345\215\242\350\266\205/project5/MyPlane/CCProps.h" new file mode 100644 index 00000000..60a331cc --- /dev/null +++ "b/21451198\345\215\242\350\266\205/project5/MyPlane/CCProps.h" @@ -0,0 +1,23 @@ +// +// CCProps.h +// MyPlane +// +// Created by jiaoshoujie on 14-12-12. +// Copyright (c) 2014年 jiaoshoujie. All rights reserved. +// + +#import +#import "cocos2d.h" + +typedef enum { + propsTypeBomb = 4, + propsTypeBullet = 5 +}propsType; + +@interface CCProps : CCNode + +@property (assign) CCSprite *prop; +@property (assign) propsType type; +- (void) initWithType:(propsType)type; +- (void) propAnimation; +@end diff --git "a/21451198\345\215\242\350\266\205/project5/MyPlane/CCProps.m" "b/21451198\345\215\242\350\266\205/project5/MyPlane/CCProps.m" new file mode 100644 index 00000000..32db209f --- /dev/null +++ "b/21451198\345\215\242\350\266\205/project5/MyPlane/CCProps.m" @@ -0,0 +1,29 @@ +// +// CCProps.m +// MyPlane +// +// Created by jiaoshoujie on 14-12-12. +// Copyright (c) 2014年 jiaoshoujie. All rights reserved. +// + +#import "CCProps.h" + +@implementation CCProps + +- (void) initWithType:(propsType)type { + _type = type; + NSString *propKey = [NSString stringWithFormat:@"enemy%d_fly_1.png",type]; + _prop = [CCSprite spriteWithSpriteFrameName:propKey]; + [_prop setPosition:ccp((arc4random()%268)+23, 732)]; +} + +- (void) propAnimation { + id act1 = [CCMoveTo actionWithDuration:1 position:ccp(_prop.position.x, 400)]; + id act2 = [CCMoveTo actionWithDuration:0.2 position:ccp(_prop.position.x, 402)]; + id act3 = [CCMoveTo actionWithDuration:1 position:ccp(_prop.position.x, 732)]; + id act4 = [CCMoveTo actionWithDuration:2 position:ccp(_prop.position.x, -55)]; + + [_prop runAction:[CCSequence actions:act1, act2, act3, act4, nil]]; +} + +@end \ No newline at end of file diff --git "a/21451198\345\215\242\350\266\205/project5/MyPlane/HelloWorldLayer.h" "b/21451198\345\215\242\350\266\205/project5/MyPlane/HelloWorldLayer.h" new file mode 100644 index 00000000..bf4af360 --- /dev/null +++ "b/21451198\345\215\242\350\266\205/project5/MyPlane/HelloWorldLayer.h" @@ -0,0 +1,70 @@ +// +// HelloWorldLayer.h +// MyPlane +// +// Created by jiaoshoujie on 14-12-12. +// Copyright jiaoshoujie 2014年. All rights reserved. +// + + +#import + +// When you import this file, you import all the cocos2d classes +#import "cocos2d.h" +#import "CCFoePlane.h" +#import "CCProps.h" + +#define WINDOWHEIGHT [[UIScreen mainScreen] bounds].size.height + +// HelloWorldLayer +@interface HelloWorldLayer : CCLayer +{ + // 背景 + CCSprite *BG1; + CCSprite *BG2; + + // 分数 + CCLabelTTF *scoreLabel; + int score; + + int adjustmentBG; + + // 玩家飞机 + CCSprite *player; + // 子弹 + CCSprite *bullet; + // 子弹数量 + int bulletSum; + // 子弹样式 + BOOL isBigBullet; + BOOL isChangeBullet; + // 子弹速度 + int bulletSpeed; + // 特殊子弹时间 + int bulletTiming; + + // 敌方飞机 + CCArray *foePlanes; + + // 添加飞机时机 + int bigPlan; + int smallPlan; + int mediumPlan; + + // 道具 + CCProps *prop; + // 添加道具时机 + int props; + // 是否存在 + BOOL isVisible; + + CCLabelTTF *gameOverLabel; + CCMenu *restart; + BOOL isGameOver; + +} + +// returns a CCScene that contains the HelloWorldLayer as the only child ++(CCScene *) scene; + +@end diff --git "a/21451198\345\215\242\350\266\205/project5/MyPlane/HelloWorldLayer.m" "b/21451198\345\215\242\350\266\205/project5/MyPlane/HelloWorldLayer.m" new file mode 100644 index 00000000..2d3d7119 --- /dev/null +++ "b/21451198\345\215\242\350\266\205/project5/MyPlane/HelloWorldLayer.m" @@ -0,0 +1,587 @@ +// +// HelloWorldLayer.m +// MyPlane +// +// Created by jiaoshoujie on 14-12-12. +// Copyright jiaoshoujie 2014年. All rights reserved. +// + + +// Import the interfaces +#import "HelloWorldLayer.h" + +// Needed to obtain the Navigation Controller +#import "AppDelegate.h" + +#pragma mark - HelloWorldLayer + +// HelloWorldLayer implementation +@implementation HelloWorldLayer + +// Helper class method that creates a Scene with the HelloWorldLayer as the only child. ++(CCScene *) scene +{ + // 'scene' is an autorelease object. + CCScene *scene = [CCScene node]; + + // 'layer' is an autorelease object. + HelloWorldLayer *layer = [HelloWorldLayer node]; + + // add layer as a child to scene + [scene addChild: layer]; + + // return the scene + return scene; +} + +// on "init" you need to initialize your instance +-(id) init +{ + // always call "super" init + // Apple recommends to re-assign "self" with the "super's" return value + if( (self=[super init]) ) { + + [self initData]; + [self loadBackground]; + [self loadPlayer]; + [self madeBullet]; + [self resetBullet]; + + [self scheduleUpdate]; + + // touch事件代理 + [[[CCDirector sharedDirector] touchDispatcher] addTargetedDelegate:self priority:0 swallowsTouches:YES]; + + } + return self; +} + +- (void) update:(ccTime)delta { + if (!isGameOver) { + [self backgrouneScroll]; + [self firingBullets]; + [self addFoePlane]; + [self moveFoePlane]; + [self collisionDetection]; + [self makeProps]; + [self bulletTiming]; + } +} + +- (void) initData { + adjustmentBG = 568; + bulletSum = 0; + isBigBullet = NO; + isChangeBullet = NO; + bulletTiming = 900; + bulletSpeed = 25; + bigPlan = 0; + smallPlan = 0; + mediumPlan = 0; + props = 0; + score = 0; + isVisible = NO; + isGameOver = NO; + foePlanes = [CCArray array]; + [foePlanes retain]; +} + +/* ----资源加载------- + - (void) loadResources { + [[CCSpriteFrameCache sharedSpriteFrameCache]addSpriteFramesWithFile:@"gameArts.plist"]; + } + */ + +// 载入背景 +- (void) loadBackground { + BG1 = [CCSprite spriteWithSpriteFrameName:@"background_2.png"]; + [BG1 setAnchorPoint:ccp(0.5, 0)]; + [BG1 setPosition:ccp(160, adjustmentBG)]; + [self addChild:BG1 z:0]; + + BG2 = [CCSprite spriteWithSpriteFrameName:@"background_2.png"]; + [BG2 setAnchorPoint:ccp(0.5, 0)]; + [BG2 setPosition:ccp(160, 568-adjustmentBG)]; + [self addChild:BG2 z:0]; + + scoreLabel=[CCLabelTTF labelWithString:@"0000" fontName:@"MarkerFelt-Thin" fontSize:18]; + [scoreLabel setColor:ccc3(0, 0, 0)]; + scoreLabel.anchorPoint=ccp(0,1); + scoreLabel.position=ccp(10,WINDOWHEIGHT-10); + [self addChild:scoreLabel z:4]; + +} + +// 背景滚动 +- (void) backgrouneScroll { + adjustmentBG--; + + if (adjustmentBG<=0) { + adjustmentBG = 568; + } + + [BG1 setPosition:ccp(160, adjustmentBG)]; + [BG2 setPosition:ccp(160, adjustmentBG-568)]; + +} +// 玩家飞机加载 +- (void) loadPlayer { + + NSMutableArray *playerActionArray = [NSMutableArray array]; + for (int i = 1 ; i<=2; i++) { + NSString* key = [NSString stringWithFormat:@"hero_fly_%d.png", i]; + //从内存池中取出Frame + CCSpriteFrame* frame = [[CCSpriteFrameCache sharedSpriteFrameCache] spriteFrameByName:key]; + //添加到序列中 + [playerActionArray addObject:frame]; + } + + //将数组转化为动画序列,换帧间隔0.1秒 + CCAnimation* animPlayer = [CCAnimation animationWithSpriteFrames:playerActionArray delay:0.1f]; + //生成动画播放的行为对象 + id actPlayer = [CCAnimate actionWithAnimation:animPlayer]; + //清空缓存数组 + [playerActionArray removeAllObjects]; + + player=[CCSprite spriteWithSpriteFrameName:@"hero_fly_1.png"]; + player.position=ccp(160,50); + [self addChild:player z:3]; + [player runAction:[CCRepeatForever actionWithAction:actPlayer]]; + +} + +// 发射子弹 +- (void) firingBullets { + + bullet.position=ccp(bullet.position.x,bullet.position.y+bulletSpeed); + + if (bullet.position.y>WINDOWHEIGHT-20) { + [self resetBullet]; + } + +} + +// 子弹还原 +- (void) resetBullet { + + if ((isBigBullet&&isChangeBullet)||(!isBigBullet&&isChangeBullet)) { + [bullet removeFromParent]; + [self madeBullet]; + isChangeBullet = NO; + } + + bulletSpeed = (460-(player.position.y + 50))/15; + if (bulletSpeed<5)bulletSpeed=5; + bullet.position=ccp(player.position.x,player.position.y+50); +} + +// 制造子弹 +- (void) madeBullet { + + bullet=[CCSprite spriteWithSpriteFrameName:(!isBigBullet)?@"bullet1.png":@"bullet2.png"]; + bullet.anchorPoint=ccp(0.5,0.5); + [self addChild:bullet]; + +} + +// --------------飞机移动----------------------- + +- (BOOL)ccTouchBegan:(UITouch *)touch withEvent:(UIEvent *)event { + return YES; + +} + +- (CGPoint)boundLayerPos:(CGPoint)newPos { + CGPoint retval = newPos; + retval.x = player.position.x+newPos.x; + retval.y = player.position.y+newPos.y; + + if (retval.x>=286) { + retval.x = 286; + }else if (retval.x<=33) { + retval.x = 33; + } + + if (retval.y >=WINDOWHEIGHT-50) { + retval.y = WINDOWHEIGHT-50; + }else if (retval.y <= 43) { + retval.y = 43; + } + + return retval; +} + +- (void)panForTranslation:(CGPoint)translation { + if (!isGameOver) { + player.position = [self boundLayerPos:translation]; + } +} + +- (void)ccTouchMoved:(UITouch *)touch withEvent:(UIEvent *)event { + + CGPoint touchLocation = [self convertTouchToNodeSpace:touch]; + + CGPoint oldTouchLocation = [touch previousLocationInView:touch.view]; + oldTouchLocation = [[CCDirector sharedDirector] convertToGL:oldTouchLocation]; + oldTouchLocation = [self convertToNodeSpace:oldTouchLocation]; + + CGPoint translation = ccpSub(touchLocation, oldTouchLocation); + [self panForTranslation:translation]; + +} + +- (void)ccTouchEnded:(UITouch *)touch withEvent:(UIEvent *)event +{ + +} + +// ------------------------------------------- + +// 移动敌机 +- (void) moveFoePlane { + for (CCFoePlane *foePlane in foePlanes) { + [foePlane setPosition:ccp(foePlane.position.x, foePlane.position.y-foePlane.speed)]; + if (foePlane.position.y<(-75)) { + [foePlanes removeObject:foePlane]; + [foePlane removeFromParent]; + } + } +} + +// 添加飞机 +- (void) addFoePlane { + bigPlan++; + smallPlan++; + mediumPlan++; + + if (bigPlan>500) { + CCFoePlane *foePlane = [self makeBigFoePlane]; + [self addChild:foePlane z:3]; + [foePlanes addObject:foePlane]; + bigPlan = 0; + } + + if (mediumPlan>400) { + CCFoePlane *foePlane = [self makeMediumFoePlane]; + [self addChild:foePlane z:3]; + [foePlanes addObject:foePlane]; + mediumPlan = 0; + } + + if (smallPlan>45) { + CCFoePlane *foePlane = [self makeSmallFoePlane]; + [self addChild:foePlane z:3]; + [foePlanes addObject:foePlane]; + smallPlan = 0; + } + +} + +// 造大飞机 +- (CCFoePlane *) makeBigFoePlane { + + NSMutableArray *bigFoePlaneActionArray = [NSMutableArray array]; + for (int i = 1 ; i<=2; i++) { + NSString* key = [NSString stringWithFormat:@"enemy2_fly_%i.png", i]; + //从内存池中取出Frame + CCSpriteFrame* frame = [[CCSpriteFrameCache sharedSpriteFrameCache] spriteFrameByName:key]; + //添加到序列中 + [bigFoePlaneActionArray addObject:frame]; + } + + //将数组转化为动画序列,换帧间隔0.1秒 + CCAnimation* animPlayer = [CCAnimation animationWithSpriteFrames:bigFoePlaneActionArray delay:0.1f]; + //生成动画播放的行为对象 + id actPlayer = [CCAnimate actionWithAnimation:animPlayer]; + //清空缓存数组 + [bigFoePlaneActionArray removeAllObjects]; + + CCFoePlane *bigFoePlane = [CCFoePlane spriteWithSpriteFrameName:@"enemy2_fly_1.png"]; + [bigFoePlane setPosition:ccp((arc4random()%210)+55, 732)]; + [bigFoePlane setPlaneType:2]; + [bigFoePlane setHp:30]; + [bigFoePlane runAction:[CCRepeatForever actionWithAction:actPlayer]]; + [bigFoePlane setSpeed:(arc4random()%2)+2]; + + return bigFoePlane; +} + +// 造中飞机 +- (CCFoePlane *) makeMediumFoePlane { + CCFoePlane *mediumFoePlane = [CCFoePlane spriteWithSpriteFrameName:@"enemy3_fly_1.png"]; + [mediumFoePlane setPosition:ccp((arc4random()%268)+23, 732)]; + [mediumFoePlane setPlaneType:3]; + [mediumFoePlane setHp:15]; + [mediumFoePlane setSpeed:(arc4random()%3)+2]; + return mediumFoePlane; +} + +// 造小飞机 +- (CCFoePlane *) makeSmallFoePlane { + CCFoePlane *smallFoePlane = [CCFoePlane spriteWithSpriteFrameName:@"enemy1_fly_1.png"]; + [smallFoePlane setPosition:ccp((arc4random()%240)+17, 732)]; + [smallFoePlane setPlaneType:1]; + [smallFoePlane setHp:1]; + [smallFoePlane setSpeed:(arc4random()%4)+2]; + return smallFoePlane; +} + +// 制作道具 +- (void) makeProps { + props++; + if (props>1520) { + prop = [CCProps node]; + [prop initWithType:(arc4random()%2)+4]; + [self addChild:prop.prop]; + [prop propAnimation]; + [prop retain]; + props = 0; + isVisible = YES; + } + +} + +// 子弹持续时间 +- (void) bulletTiming { + if (isBigBullet) { + if (bulletTiming>0) { + bulletTiming--; + }else { + isBigBullet = NO; + isChangeBullet = YES; + bulletTiming = 900; + } + } +} + +// 碰撞检测 +- (void) collisionDetection { + + // 子弹跟敌机 + CGRect bulletRec = bullet.boundingBox; + for (CCFoePlane *foePlane in foePlanes) { + if (CGRectIntersectsRect(bulletRec, foePlane.boundingBox)) { + + [self resetBullet]; + [self fowPlaneHitAnimation:foePlane]; + foePlane.hp = foePlane.hp-(isBigBullet?2:1); + if (foePlane.hp<=0) { + [self fowPlaneBlowupAnimation:foePlane]; + [foePlanes removeObject:foePlane]; + } + + } + } + + // 飞机跟打飞机 + CGRect playerRec = player.boundingBox; + playerRec.origin.x += 25; + playerRec.size.width -= 50; + playerRec.origin.y -= 10; + playerRec.size.height -= 10; + for (CCFoePlane *foePlane in foePlanes) { + if (CGRectIntersectsRect(playerRec, foePlane.boundingBox)) { + [self gameOver]; + [self playerBlowupAnimation]; + [self fowPlaneBlowupAnimation:foePlane]; + [foePlanes removeObject:foePlane]; + } + } + + // 飞机跟道具 + + if (isVisible) { + CGRect playerRec1 = player.boundingBox; + CGRect propRec = prop.prop.boundingBox; + if (CGRectIntersectsRect(playerRec1, propRec)) { + + [prop.prop stopAllActions]; + [prop.prop removeFromParent]; + isVisible = NO; + + if (prop.type == propsTypeBullet) { + isBigBullet = YES; + isChangeBullet = YES; + }else if (prop.type == propsTypeBomb) { + for (CCFoePlane *foePlane in foePlanes) { + [self fowPlaneBlowupAnimation:foePlane]; + } + [foePlanes removeAllObjects]; + } + } + } + + +} + +// 添加打击效果 +- (void) fowPlaneHitAnimation:(CCFoePlane *)foePlane { + if (foePlane.planeType == 3) { + if (foePlane.hp==13) { + NSMutableArray *playerActionArray = [NSMutableArray array]; + for (int i = 1 ; i<=2; i++) { + NSString* key = [NSString stringWithFormat:@"enemy3_hit_%d.png",i]; + //从内存池中取出Frame + CCSpriteFrame* frame = [[CCSpriteFrameCache sharedSpriteFrameCache] spriteFrameByName:key]; + //添加到序列中 + [playerActionArray addObject:frame]; + } + + //将数组转化为动画序列,换帧间隔0.1秒 + CCAnimation* animPlayer = [CCAnimation animationWithSpriteFrames:playerActionArray delay:0.1f]; + //生成动画播放的行为对象 + id actPlayer = [CCAnimate actionWithAnimation:animPlayer]; + //清空缓存数组 + [playerActionArray removeAllObjects]; + [foePlane stopAllActions]; + [foePlane runAction:[CCRepeatForever actionWithAction:actPlayer]]; + } + }else if (foePlane.planeType == 2) { + if (foePlane.hp==20) { + NSMutableArray *playerActionArray = [NSMutableArray array]; + for (int i = 1 ; i<=1; i++) { + NSString* key = [NSString stringWithFormat:@"enemy2_hit_%d.png",i]; + //从内存池中取出Frame + CCSpriteFrame* frame = [[CCSpriteFrameCache sharedSpriteFrameCache] spriteFrameByName:key]; + //添加到序列中 + [playerActionArray addObject:frame]; + } + + //将数组转化为动画序列,换帧间隔0.1秒 + CCAnimation* animPlayer = [CCAnimation animationWithSpriteFrames:playerActionArray delay:0.1f]; + //生成动画播放的行为对象 + id actPlayer = [CCAnimate actionWithAnimation:animPlayer]; + //清空缓存数组 + [playerActionArray removeAllObjects]; + [foePlane stopAllActions]; + [foePlane runAction:[CCRepeatForever actionWithAction:actPlayer]]; + } + } +} + +// 爆炸动画 +- (void) fowPlaneBlowupAnimation:(CCFoePlane *)foePlane { + int forSum; + if (foePlane.planeType == 3) { + forSum = 4; + score+=6000; + }else if (foePlane.planeType == 2) { + score+=30000; + forSum = 7; + }else if (foePlane.planeType == 1) { + forSum = 4; + score+=1000; + } + + [scoreLabel setString:[NSString stringWithFormat:@"%d",score]]; + + [foePlane stopAllActions]; + NSMutableArray *foePlaneActionArray = [NSMutableArray array]; + + for (int i = 1; i<=forSum ; i++ ) { + NSString* key = [NSString stringWithFormat:@"enemy%d_blowup_%i.png",foePlane.planeType , i]; + //从内存池中取出Frame + CCSpriteFrame* frame = [[CCSpriteFrameCache sharedSpriteFrameCache] spriteFrameByName:key]; + //添加到序列中 + [foePlaneActionArray addObject:frame]; + } + + //将数组转化为动画序列,换帧间隔0.1秒 + CCAnimation* animPlayer = [CCAnimation animationWithSpriteFrames:foePlaneActionArray delay:0.1f]; + //生成动画播放的行为对象 + id actFowPlane = [CCAnimate actionWithAnimation:animPlayer]; + id end = [CCCallFuncN actionWithTarget:self selector:@selector(blowupEnd:)]; + //清空缓存数组 + [foePlaneActionArray removeAllObjects]; + + [foePlane runAction:[CCSequence actions:actFowPlane, end, nil]]; +} + +// 飞机爆炸 +- (void) playerBlowupAnimation { + NSMutableArray *foePlaneActionArray = [NSMutableArray array]; + + for (int i = 1; i<=4 ; i++ ) { + NSString* key = [NSString stringWithFormat:@"hero_blowup_%i.png", i]; + //从内存池中取出Frame + CCSpriteFrame* frame = [[CCSpriteFrameCache sharedSpriteFrameCache] spriteFrameByName:key]; + //添加到序列中 + [foePlaneActionArray addObject:frame]; + } + + //将数组转化为动画序列,换帧间隔0.1秒 + CCAnimation* animPlayer = [CCAnimation animationWithSpriteFrames:foePlaneActionArray delay:0.1f]; + //生成动画播放的行为对象 + id actFowPlane = [CCAnimate actionWithAnimation:animPlayer]; + //清空缓存数组 + [foePlaneActionArray removeAllObjects]; + + [player runAction:[CCSequence actions:actFowPlane, nil]]; +} + +- (void) playerBlowupEnd:(id)sender { + +} + +- (void) blowupEnd : (id) sender { + + CCFoePlane *foePlane = (CCFoePlane *) sender; + [foePlane removeFromParent]; +} + +- (void) gameOver { + + isGameOver = YES; + CCNode *node; + CCARRAY_FOREACH([self children], node){ + [node stopAllActions]; + } + + gameOverLabel = [CCLabelTTF labelWithString:@"GameOver" fontName:@"MarkerFelt-Thin" fontSize:35]; + [gameOverLabel setPosition:ccp(160, 300)]; + [self addChild:gameOverLabel z:4]; + + CCMenuItemFont *gameOverItem = [CCMenuItemFont itemWithString:@"restart" target:self selector:@selector(restart)]; + [gameOverItem setFontName:@"MarkerFelt-Thin"]; + [gameOverItem setFontSize:30]; + restart = [CCMenu menuWithItems:gameOverItem, nil]; + [restart setPosition:ccp(160, 200)]; + [self addChild:restart z:4]; +} + +- (void) restart { + [self removeAllChildren]; + [foePlanes removeAllObjects]; + [self initData]; + [self loadBackground]; + [self loadPlayer]; + [self madeBullet]; + [self resetBullet]; + +} + +// on "dealloc" you need to release all your retained objects +- (void) dealloc +{ + // in case you have something to dealloc, do it in this method + // in this particular example nothing needs to be released. + // cocos2d will automatically release all the children (Label) + + // don't forget to call "super dealloc" + [super dealloc]; +} + +#pragma mark GameKit delegate + +-(void) achievementViewControllerDidFinish:(GKAchievementViewController *)viewController +{ + AppController *app = (AppController*) [[UIApplication sharedApplication] delegate]; + [[app navController] dismissModalViewControllerAnimated:YES]; +} + +-(void) leaderboardViewControllerDidFinish:(GKLeaderboardViewController *)viewController +{ + AppController *app = (AppController*) [[UIApplication sharedApplication] delegate]; + [[app navController] dismissModalViewControllerAnimated:YES]; +} +@end diff --git "a/21451198\345\215\242\350\266\205/project5/MyPlane/IntroLayer.h" "b/21451198\345\215\242\350\266\205/project5/MyPlane/IntroLayer.h" new file mode 100644 index 00000000..24756eba --- /dev/null +++ "b/21451198\345\215\242\350\266\205/project5/MyPlane/IntroLayer.h" @@ -0,0 +1,21 @@ +// +// IntroLayer.h +// MyPlane +// +// Created by jiaoshoujie on 14-12-12. +// Copyright jiaoshoujie 2014年. All rights reserved. +// + + +// When you import this file, you import all the cocos2d classes +#import "cocos2d.h" + +// HelloWorldLayer +@interface IntroLayer : CCLayer +{ +} + +// returns a CCScene that contains the HelloWorldLayer as the only child ++(CCScene *) scene; + +@end diff --git "a/21451198\345\215\242\350\266\205/project5/MyPlane/IntroLayer.m" "b/21451198\345\215\242\350\266\205/project5/MyPlane/IntroLayer.m" new file mode 100644 index 00000000..fdcca19d --- /dev/null +++ "b/21451198\345\215\242\350\266\205/project5/MyPlane/IntroLayer.m" @@ -0,0 +1,66 @@ +// +// IntroLayer.m +// MyPlane +// +// Created by jiaoshoujie on 14-12-12. +// Copyright jiaoshoujie 2014年. All rights reserved. +// + + +// Import the interfaces +#import "IntroLayer.h" +#import "HelloWorldLayer.h" + + +#pragma mark - IntroLayer + +// HelloWorldLayer implementation +@implementation IntroLayer + +// Helper class method that creates a Scene with the HelloWorldLayer as the only child. ++(CCScene *) scene +{ + // 'scene' is an autorelease object. + CCScene *scene = [CCScene node]; + + // 'layer' is an autorelease object. + IntroLayer *layer = [IntroLayer node]; + + // add layer as a child to scene + [scene addChild: layer]; + + // return the scene + return scene; +} + +// +-(id) init +{ + if( (self=[super init])) { + + // ask director for the window size + CGSize size = [[CCDirector sharedDirector] winSize]; + + CCSprite *background; + + if( UI_USER_INTERFACE_IDIOM() == UIUserInterfaceIdiomPhone ) { + background = [CCSprite spriteWithFile:@"Default.png"]; + background.rotation = 90; + } else { + background = [CCSprite spriteWithFile:@"Default-Landscape~ipad.png"]; + } + background.position = ccp(size.width/2, size.height/2); + + // add the label as a child to this Layer + [self addChild: background]; + } + + return self; +} + +-(void) onEnter +{ + [super onEnter]; + [[CCDirector sharedDirector] replaceScene:[CCTransitionFade transitionWithDuration:1.0 scene:[HelloWorldLayer scene] ]]; +} +@end diff --git "a/21451198\345\215\242\350\266\205/project5/MyPlane/Prefix.pch" "b/21451198\345\215\242\350\266\205/project5/MyPlane/Prefix.pch" new file mode 100644 index 00000000..f2861ffe --- /dev/null +++ "b/21451198\345\215\242\350\266\205/project5/MyPlane/Prefix.pch" @@ -0,0 +1,14 @@ +// +// Prefix header for all source files of the 'Test' target in the 'Test' project +// + +#import + +#ifndef __IPHONE_3_0 +#warning "This project uses features only available in iPhone SDK 3.0 and later." +#endif + +#ifdef __OBJC__ +#import +#import +#endif diff --git "a/21451198\345\215\242\350\266\205/project5/MyPlane/Resources/Default-568h@2x.png" "b/21451198\345\215\242\350\266\205/project5/MyPlane/Resources/Default-568h@2x.png" new file mode 100644 index 00000000..24728b3a Binary files /dev/null and "b/21451198\345\215\242\350\266\205/project5/MyPlane/Resources/Default-568h@2x.png" differ diff --git "a/21451198\345\215\242\350\266\205/project5/MyPlane/Resources/Default-Landscape~ipad.png" "b/21451198\345\215\242\350\266\205/project5/MyPlane/Resources/Default-Landscape~ipad.png" new file mode 100644 index 00000000..82aa50e9 Binary files /dev/null and "b/21451198\345\215\242\350\266\205/project5/MyPlane/Resources/Default-Landscape~ipad.png" differ diff --git "a/21451198\345\215\242\350\266\205/project5/MyPlane/Resources/Default.png" "b/21451198\345\215\242\350\266\205/project5/MyPlane/Resources/Default.png" new file mode 100644 index 00000000..b3de9682 Binary files /dev/null and "b/21451198\345\215\242\350\266\205/project5/MyPlane/Resources/Default.png" differ diff --git "a/21451198\345\215\242\350\266\205/project5/MyPlane/Resources/Default@2x.png" "b/21451198\345\215\242\350\266\205/project5/MyPlane/Resources/Default@2x.png" new file mode 100644 index 00000000..075ae87f Binary files /dev/null and "b/21451198\345\215\242\350\266\205/project5/MyPlane/Resources/Default@2x.png" differ diff --git "a/21451198\345\215\242\350\266\205/project5/MyPlane/Resources/Icon-72.png" "b/21451198\345\215\242\350\266\205/project5/MyPlane/Resources/Icon-72.png" new file mode 100644 index 00000000..5b1ce47a Binary files /dev/null and "b/21451198\345\215\242\350\266\205/project5/MyPlane/Resources/Icon-72.png" differ diff --git "a/21451198\345\215\242\350\266\205/project5/MyPlane/Resources/Icon-Small-50.png" "b/21451198\345\215\242\350\266\205/project5/MyPlane/Resources/Icon-Small-50.png" new file mode 100644 index 00000000..bf1f0c52 Binary files /dev/null and "b/21451198\345\215\242\350\266\205/project5/MyPlane/Resources/Icon-Small-50.png" differ diff --git "a/21451198\345\215\242\350\266\205/project5/MyPlane/Resources/Icon-Small.png" "b/21451198\345\215\242\350\266\205/project5/MyPlane/Resources/Icon-Small.png" new file mode 100644 index 00000000..1f116695 Binary files /dev/null and "b/21451198\345\215\242\350\266\205/project5/MyPlane/Resources/Icon-Small.png" differ diff --git "a/21451198\345\215\242\350\266\205/project5/MyPlane/Resources/Icon-Small@2x.png" "b/21451198\345\215\242\350\266\205/project5/MyPlane/Resources/Icon-Small@2x.png" new file mode 100644 index 00000000..8d8ece43 Binary files /dev/null and "b/21451198\345\215\242\350\266\205/project5/MyPlane/Resources/Icon-Small@2x.png" differ diff --git "a/21451198\345\215\242\350\266\205/project5/MyPlane/Resources/Icon.png" "b/21451198\345\215\242\350\266\205/project5/MyPlane/Resources/Icon.png" new file mode 100644 index 00000000..def89832 Binary files /dev/null and "b/21451198\345\215\242\350\266\205/project5/MyPlane/Resources/Icon.png" differ diff --git "a/21451198\345\215\242\350\266\205/project5/MyPlane/Resources/Icon@2x.png" "b/21451198\345\215\242\350\266\205/project5/MyPlane/Resources/Icon@2x.png" new file mode 100644 index 00000000..05be6c60 Binary files /dev/null and "b/21451198\345\215\242\350\266\205/project5/MyPlane/Resources/Icon@2x.png" differ diff --git "a/21451198\345\215\242\350\266\205/project5/MyPlane/Resources/Info.plist" "b/21451198\345\215\242\350\266\205/project5/MyPlane/Resources/Info.plist" new file mode 100644 index 00000000..13338d3a --- /dev/null +++ "b/21451198\345\215\242\350\266\205/project5/MyPlane/Resources/Info.plist" @@ -0,0 +1,57 @@ + + + + + CFBundleDevelopmentRegion + English + CFBundleDisplayName + ${PRODUCT_NAME} + CFBundleExecutable + ${EXECUTABLE_NAME} + CFBundleIconFile + + CFBundleIconFiles + + Icon.png + Icon@2x.png + Icon-72.png + Icon-Small-50.png + Icon-Small.png + Icon-Small@2x.png + + CFBundleIdentifier + com.yourcompany.${PRODUCT_NAME:rfc1034identifier} + CFBundleInfoDictionaryVersion + 6.0 + CFBundleName + ${PRODUCT_NAME} + CFBundlePackageType + APPL + CFBundleSignature + ???? + CFBundleVersion + 1.0 + LSRequiresIPhoneOS + + UIPrerenderedIcon + + UIRequiredDeviceCapabilities + + accelerometer + + opengles-2 + + + UIStatusBarHidden + + UISupportedInterfaceOrientations + + UIInterfaceOrientationPortrait + + UISupportedInterfaceOrientations~ipad + + UIInterfaceOrientationLandscapeLeft + UIInterfaceOrientationLandscapeRight + + + diff --git "a/21451198\345\215\242\350\266\205/project5/MyPlane/Resources/iTunesArtwork" "b/21451198\345\215\242\350\266\205/project5/MyPlane/Resources/iTunesArtwork" new file mode 100644 index 00000000..b1cc056b Binary files /dev/null and "b/21451198\345\215\242\350\266\205/project5/MyPlane/Resources/iTunesArtwork" differ diff --git "a/21451198\345\215\242\350\266\205/project5/MyPlane/gameArts-hd.plist" "b/21451198\345\215\242\350\266\205/project5/MyPlane/gameArts-hd.plist" new file mode 100644 index 00000000..539ebddb Binary files /dev/null and "b/21451198\345\215\242\350\266\205/project5/MyPlane/gameArts-hd.plist" differ diff --git "a/21451198\345\215\242\350\266\205/project5/MyPlane/gameArts-hd.png" "b/21451198\345\215\242\350\266\205/project5/MyPlane/gameArts-hd.png" new file mode 100644 index 00000000..e941c250 Binary files /dev/null and "b/21451198\345\215\242\350\266\205/project5/MyPlane/gameArts-hd.png" differ diff --git "a/21451198\345\215\242\350\266\205/project5/MyPlane/gameArts.plist" "b/21451198\345\215\242\350\266\205/project5/MyPlane/gameArts.plist" new file mode 100644 index 00000000..be87ee7f Binary files /dev/null and "b/21451198\345\215\242\350\266\205/project5/MyPlane/gameArts.plist" differ diff --git "a/21451198\345\215\242\350\266\205/project5/MyPlane/gameArts.png" "b/21451198\345\215\242\350\266\205/project5/MyPlane/gameArts.png" new file mode 100644 index 00000000..41b66a57 Binary files /dev/null and "b/21451198\345\215\242\350\266\205/project5/MyPlane/gameArts.png" differ diff --git "a/21451198\345\215\242\350\266\205/project5/MyPlane/libs/CocosDenshion/CDAudioManager.h" "b/21451198\345\215\242\350\266\205/project5/MyPlane/libs/CocosDenshion/CDAudioManager.h" new file mode 100644 index 00000000..bb282f76 --- /dev/null +++ "b/21451198\345\215\242\350\266\205/project5/MyPlane/libs/CocosDenshion/CDAudioManager.h" @@ -0,0 +1,243 @@ +/* + Copyright (c) 2010 Steve Oldmeadow + + Permission is hereby granted, free of charge, to any person obtaining a copy + of this software and associated documentation files (the "Software"), to deal + in the Software without restriction, including without limitation the rights + to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + copies of the Software, and to permit persons to whom the Software is + furnished to do so, subject to the following conditions: + + The above copyright notice and this permission notice shall be included in + all copies or substantial portions of the Software. + + THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + THE SOFTWARE. + + $Id$ + */ + +#import "CocosDenshion.h" +#if __IPHONE_OS_VERSION_MIN_REQUIRED >= 30000 + #import +#else + #import "CDXMacOSXSupport.h" +#endif + +/** Different modes of the engine */ +typedef enum { + kAMM_FxOnly, //!Other apps will be able to play audio + kAMM_FxPlusMusic, //!Only this app will play audio + kAMM_FxPlusMusicIfNoOtherAudio, //!If another app is playing audio at start up then allow it to continue and don't play music + kAMM_MediaPlayback, //!This app takes over audio e.g music player app + kAMM_PlayAndRecord //!App takes over audio and has input and output +} tAudioManagerMode; + +/** Possible states of the engine */ +typedef enum { + kAMStateUninitialised, //!Audio manager has not been initialised - do not use + kAMStateInitialising, //!Audio manager is in the process of initialising - do not use + kAMStateInitialised //!Audio manager is initialised - safe to use +} tAudioManagerState; + +typedef enum { + kAMRBDoNothing, //Audio manager will not do anything on resign or becoming active + kAMRBStopPlay, //Background music is stopped on resign and resumed on become active + kAMRBStop //Background music is stopped on resign but not resumed - maybe because you want to do this from within your game +} tAudioManagerResignBehavior; + +/** Notifications */ +extern NSString * const kCDN_AudioManagerInitialised; + +@interface CDAsynchInitialiser : NSOperation {} +@end + +/** CDAudioManager supports two long audio source channels called left and right*/ +typedef enum { + kASC_Left = 0, + kASC_Right = 1 +} tAudioSourceChannel; + +typedef enum { + kLAS_Init, + kLAS_Loaded, + kLAS_Playing, + kLAS_Paused, + kLAS_Stopped, +} tLongAudioSourceState; + +@class CDLongAudioSource; +@protocol CDLongAudioSourceDelegate +@optional +/** The audio source completed playing */ +- (void) cdAudioSourceDidFinishPlaying:(CDLongAudioSource *) audioSource; +/** The file used to load the audio source has changed */ +- (void) cdAudioSourceFileDidChange:(CDLongAudioSource *) audioSource; +@end + +/** + CDLongAudioSource represents an audio source that has a long duration which makes + it costly to load into memory for playback as an effect using CDSoundEngine. Examples + include background music and narration tracks. The audio file may or may not be compressed. + Bear in mind that current iDevices can only use hardware to decode a single compressed + audio file at a time and playing multiple compressed files will result in a performance drop + as software decompression will take place. + @since v0.99 + */ +@interface CDLongAudioSource : NSObject { + AVAudioPlayer *audioSourcePlayer; + NSString *audioSourceFilePath; + NSInteger numberOfLoops; + float volume; + id delegate; + BOOL mute; + BOOL enabled_; + BOOL backgroundMusic; +@public + BOOL systemPaused;//Used for auto resign handling + NSTimeInterval systemPauseLocation;//Used for auto resign handling +@protected + tLongAudioSourceState state; +} +@property (readonly) AVAudioPlayer *audioSourcePlayer; +@property (readonly) NSString *audioSourceFilePath; +@property (readwrite, nonatomic) NSInteger numberOfLoops; +@property (readwrite, nonatomic) float volume; +@property (assign) id delegate; +/* This long audio source functions as background music */ +@property (readwrite, nonatomic) BOOL backgroundMusic; + +/** Loads the file into the audio source */ +-(void) load:(NSString*) filePath; +/** Plays the audio source */ +-(void) play; +/** Stops playing the audio soruce */ +-(void) stop; +/** Pauses the audio source */ +-(void) pause; +/** Rewinds the audio source */ +-(void) rewind; +/** Resumes playing the audio source if it was paused */ +-(void) resume; +/** Returns whether or not the audio source is playing */ +-(BOOL) isPlaying; + +@end + +/** + CDAudioManager manages audio requirements for a game. It provides access to a CDSoundEngine object + for playing sound effects. It provides access to two CDLongAudioSource object (left and right channel) + for playing long duration audio such as background music and narration tracks. Additionally it manages + the audio session to take care of things like audio session interruption and interacting with the audio + of other apps that are running on the device. + + Requirements: + - Firmware: OS 2.2 or greater + - Files: CDAudioManager.*, CocosDenshion.* + - Frameworks: OpenAL, AudioToolbox, AVFoundation + @since v0.8 + */ +@interface CDAudioManager : NSObject { + CDSoundEngine *soundEngine; + CDLongAudioSource *backgroundMusic; + NSMutableArray *audioSourceChannels; + NSString* _audioSessionCategory; + BOOL _audioWasPlayingAtStartup; + tAudioManagerMode _mode; + SEL backgroundMusicCompletionSelector; + id backgroundMusicCompletionListener; + BOOL willPlayBackgroundMusic; + BOOL _mute; + BOOL _resigned; + BOOL _interrupted; + BOOL _audioSessionActive; + BOOL enabled_; + + //For handling resign/become active + BOOL _isObservingAppEvents; + tAudioManagerResignBehavior _resignBehavior; +} + +@property (readonly) CDSoundEngine *soundEngine; +@property (readonly) CDLongAudioSource *backgroundMusic; +@property (readonly) BOOL willPlayBackgroundMusic; + +/** Returns the shared singleton */ ++ (CDAudioManager *) sharedManager; ++ (tAudioManagerState) sharedManagerState; +/** Configures the shared singleton with a mode*/ ++ (void) configure: (tAudioManagerMode) mode; +/** Initializes the engine asynchronously with a mode */ ++ (void) initAsynchronously: (tAudioManagerMode) mode; +/** Initializes the engine synchronously with a mode, channel definition and a total number of channels */ +- (id) init: (tAudioManagerMode) mode; +-(void) audioSessionInterrupted; +-(void) audioSessionResumed; +-(void) setResignBehavior:(tAudioManagerResignBehavior) resignBehavior autoHandle:(BOOL) autoHandle; +/** Returns true is audio is muted at a hardware level e.g user has ringer switch set to off */ +-(BOOL) isDeviceMuted; +/** Returns true if another app is playing audio such as the iPod music player */ +-(BOOL) isOtherAudioPlaying; +/** Sets the way the audio manager interacts with the operating system such as whether it shares output with other apps or obeys the mute switch */ +-(void) setMode:(tAudioManagerMode) mode; +/** Shuts down the shared audio manager instance so that it can be reinitialised */ ++(void) end; + +/** Call if you want to use built in resign behavior but need to do some additional audio processing on resign active. */ +- (void) applicationWillResignActive; +/** Call if you want to use built in resign behavior but need to do some additional audio processing on become active. */ +- (void) applicationDidBecomeActive; + +//New AVAudioPlayer API +/** Loads the data from the specified file path to the channel's audio source */ +-(CDLongAudioSource*) audioSourceLoad:(NSString*) filePath channel:(tAudioSourceChannel) channel; +/** Retrieves the audio source for the specified channel */ +-(CDLongAudioSource*) audioSourceForChannel:(tAudioSourceChannel) channel; + +//Legacy AVAudioPlayer API +/** Plays music in background. The music can be looped or not + It is recommended to use .aac files as background music since they are decoded by the device (hardware). + */ +-(void) playBackgroundMusic:(NSString*) filePath loop:(BOOL) loop; +/** Preloads a background music */ +-(void) preloadBackgroundMusic:(NSString*) filePath; +/** Stops playing the background music */ +-(void) stopBackgroundMusic; +/** Pauses the background music */ +-(void) pauseBackgroundMusic; +/** Rewinds the background music */ +-(void) rewindBackgroundMusic; +/** Resumes playing the background music */ +-(void) resumeBackgroundMusic; +/** Returns whether or not the background music is playing */ +-(BOOL) isBackgroundMusicPlaying; + +-(void) setBackgroundMusicCompletionListener:(id) listener selector:(SEL) selector; + +@end + +/** Fader for long audio source objects */ +@interface CDLongAudioSourceFader : CDPropertyModifier{} +@end + +static const int kCDNoBuffer = -1; + +/** Allows buffers to be associated with file names */ +@interface CDBufferManager:NSObject{ + NSMutableDictionary* loadedBuffers; + NSMutableArray *freedBuffers; + CDSoundEngine *soundEngine; + int nextBufferId; +} + +-(id) initWithEngine:(CDSoundEngine *) theSoundEngine; +-(int) bufferForFile:(NSString*) filePath create:(BOOL) create; +-(void) releaseBufferForFile:(NSString *) filePath; + +@end + diff --git "a/21451198\345\215\242\350\266\205/project5/MyPlane/libs/CocosDenshion/CDAudioManager.m" "b/21451198\345\215\242\350\266\205/project5/MyPlane/libs/CocosDenshion/CDAudioManager.m" new file mode 100644 index 00000000..fe5ec6c4 --- /dev/null +++ "b/21451198\345\215\242\350\266\205/project5/MyPlane/libs/CocosDenshion/CDAudioManager.m" @@ -0,0 +1,888 @@ +/* + Copyright (c) 2010 Steve Oldmeadow + + Permission is hereby granted, free of charge, to any person obtaining a copy + of this software and associated documentation files (the "Software"), to deal + in the Software without restriction, including without limitation the rights + to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + copies of the Software, and to permit persons to whom the Software is + furnished to do so, subject to the following conditions: + + The above copyright notice and this permission notice shall be included in + all copies or substantial portions of the Software. + + THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + THE SOFTWARE. + + $Id$ + */ + + +#import "CDAudioManager.h" + +NSString * const kCDN_AudioManagerInitialised = @"kCDN_AudioManagerInitialised"; + +//NSOperation object used to asynchronously initialise +@implementation CDAsynchInitialiser + +-(void) main { + [super main]; + [CDAudioManager sharedManager]; +} + +@end + +@implementation CDLongAudioSource + +@synthesize audioSourcePlayer, audioSourceFilePath, delegate, backgroundMusic; + +-(id) init { + if ((self = [super init])) { + state = kLAS_Init; + volume = 1.0f; + mute = NO; + enabled_ = YES; + } + return self; +} + +-(void) dealloc { + CDLOGINFO(@"Denshion::CDLongAudioSource - deallocating %@", self); + [audioSourcePlayer release]; + [audioSourceFilePath release]; + [super dealloc]; +} + +-(void) load:(NSString*) filePath { + //We have alread loaded a file previously, check if we are being asked to load the same file + if (state == kLAS_Init || ![filePath isEqualToString:audioSourceFilePath]) { + CDLOGINFO(@"Denshion::CDLongAudioSource - Loading new audio source %@",filePath); + //New file + if (state != kLAS_Init) { + [audioSourceFilePath release];//Release old file path + [audioSourcePlayer release];//Release old AVAudioPlayer, they can't be reused + } + audioSourceFilePath = [filePath copy]; + NSError *error = nil; + NSString *path = [CDUtilities fullPathFromRelativePath:audioSourceFilePath]; + audioSourcePlayer = [(AVAudioPlayer*)[AVAudioPlayer alloc] initWithContentsOfURL:[NSURL fileURLWithPath:path] error:&error]; + if (error == nil) { + [audioSourcePlayer prepareToPlay]; + audioSourcePlayer.delegate = self; + if (delegate && [delegate respondsToSelector:@selector(cdAudioSourceFileDidChange:)]) { + //Tell our delegate the file has changed + [delegate cdAudioSourceFileDidChange:self]; + } + } else { + CDLOG(@"Denshion::CDLongAudioSource - Error initialising audio player: %@",error); + } + } else { + //Same file - just return it to a consistent state + [self pause]; + [self rewind]; + } + audioSourcePlayer.volume = mute ? 0.0f : volume; + audioSourcePlayer.numberOfLoops = numberOfLoops; + state = kLAS_Loaded; +} + +-(void) play { + if (enabled_) { + self->systemPaused = NO; + [audioSourcePlayer play]; + } else { + CDLOGINFO(@"Denshion::CDLongAudioSource long audio source didn't play because it is disabled"); + } +} + +-(void) stop { + [audioSourcePlayer stop]; +} + +-(void) pause { + [audioSourcePlayer pause]; +} + +-(void) rewind { + [audioSourcePlayer setCurrentTime:0]; +} + +-(void) resume { + [audioSourcePlayer play]; +} + +-(BOOL) isPlaying { + if (state != kLAS_Init) { + return [audioSourcePlayer isPlaying]; + } else { + return NO; + } +} + +-(void) setVolume:(float) newVolume +{ + volume = newVolume; + if (state != kLAS_Init && !mute) { + audioSourcePlayer.volume = newVolume; + } +} + +-(float) volume +{ + return volume; +} + +#pragma mark Audio Interrupt Protocol +-(BOOL) mute +{ + return mute; +} + +-(void) setMute:(BOOL) muteValue +{ + if (mute != muteValue) { + if (mute) { + //Turn sound back on + audioSourcePlayer.volume = volume; + } else { + audioSourcePlayer.volume = 0.0f; + } + mute = muteValue; + } +} + +-(BOOL) enabled +{ + return enabled_; +} + +-(void) setEnabled:(BOOL)enabledValue +{ + if (enabledValue != enabled_) { + enabled_ = enabledValue; + if (!enabled_) { + //"Stop" the sounds + [self pause]; + [self rewind]; + } + } +} + +-(NSInteger) numberOfLoops { + return numberOfLoops; +} + +-(void) setNumberOfLoops:(NSInteger) loopCount +{ + audioSourcePlayer.numberOfLoops = loopCount; + numberOfLoops = loopCount; +} + +- (void)audioPlayerDidFinishPlaying:(AVAudioPlayer *)player successfully:(BOOL)flag { + CDLOGINFO(@"Denshion::CDLongAudioSource - audio player finished"); +#if TARGET_IPHONE_SIMULATOR + CDLOGINFO(@"Denshion::CDLongAudioSource - workaround for OpenAL clobbered audio issue"); + //This is a workaround for an issue in all simulators (tested to 3.1.2). Problem is + //that OpenAL audio playback is clobbered when an AVAudioPlayer stops. Workaround + //is to keep the player playing on an endless loop with 0 volume and then when + //it is played again reset the volume and set loop count appropriately. + //NB: this workaround is not foolproof but it is good enough for most situations. + player.numberOfLoops = -1; + player.volume = 0; + [player play]; +#endif + if (delegate && [delegate respondsToSelector:@selector(cdAudioSourceDidFinishPlaying:)]) { + [delegate cdAudioSourceDidFinishPlaying:self]; + } +} + +-(void)audioPlayerBeginInterruption:(AVAudioPlayer *)player { + CDLOGINFO(@"Denshion::CDLongAudioSource - audio player interrupted"); +} + +-(void)audioPlayerEndInterruption:(AVAudioPlayer *)player { + CDLOGINFO(@"Denshion::CDLongAudioSource - audio player resumed"); + if (self.backgroundMusic) { + //Check if background music can play as rules may have changed during + //the interruption. This is to address a specific issue in 4.x when + //fast task switching + if([CDAudioManager sharedManager].willPlayBackgroundMusic) { + [player play]; + } + } else { + [player play]; + } +} + +@end + + +@interface CDAudioManager (PrivateMethods) +-(BOOL) audioSessionSetActive:(BOOL) active; +-(BOOL) audioSessionSetCategory:(NSString*) category; +-(void) badAlContextHandler; +@end + + +@implementation CDAudioManager +#define BACKGROUND_MUSIC_CHANNEL kASC_Left + +@synthesize soundEngine, willPlayBackgroundMusic; +static CDAudioManager *sharedManager; +static tAudioManagerState _sharedManagerState = kAMStateUninitialised; +static tAudioManagerMode configuredMode; +static BOOL configured = FALSE; + +-(BOOL) audioSessionSetActive:(BOOL) active { + NSError *activationError = nil; + if ([[AVAudioSession sharedInstance] setActive:active error:&activationError]) { + _audioSessionActive = active; + CDLOGINFO(@"Denshion::CDAudioManager - Audio session set active %i succeeded", active); + return YES; + } else { + //Failed + CDLOG(@"Denshion::CDAudioManager - Audio session set active %i failed with error %@", active, activationError); + return NO; + } +} + +-(BOOL) audioSessionSetCategory:(NSString*) category { + NSError *categoryError = nil; + if ([[AVAudioSession sharedInstance] setCategory:category error:&categoryError]) { + CDLOGINFO(@"Denshion::CDAudioManager - Audio session set category %@ succeeded", category); + return YES; + } else { + //Failed + CDLOG(@"Denshion::CDAudioManager - Audio session set category %@ failed with error %@", category, categoryError); + return NO; + } +} + +// Init ++ (CDAudioManager *) sharedManager +{ + @synchronized(self) { + if (!sharedManager) { + if (!configured) { + //Set defaults here + configuredMode = kAMM_FxPlusMusicIfNoOtherAudio; + } + sharedManager = [[CDAudioManager alloc] init:configuredMode]; + _sharedManagerState = kAMStateInitialised;//This is only really relevant when using asynchronous initialisation + [[NSNotificationCenter defaultCenter] postNotificationName:kCDN_AudioManagerInitialised object:nil]; + } + } + return sharedManager; +} + ++ (tAudioManagerState) sharedManagerState { + return _sharedManagerState; +} + +/** + * Call this to set up audio manager asynchronously. Initialisation is finished when sharedManagerState == kAMStateInitialised + */ ++ (void) initAsynchronously: (tAudioManagerMode) mode { + @synchronized(self) { + if (_sharedManagerState == kAMStateUninitialised) { + _sharedManagerState = kAMStateInitialising; + [CDAudioManager configure:mode]; + CDAsynchInitialiser *initOp = [[[CDAsynchInitialiser alloc] init] autorelease]; + NSOperationQueue *opQ = [[[NSOperationQueue alloc] init] autorelease]; + [opQ addOperation:initOp]; + } + } +} + ++ (id) alloc +{ + @synchronized(self) { + NSAssert(sharedManager == nil, @"Attempted to allocate a second instance of a singleton."); + return [super alloc]; + } + return nil; +} + +/* + * Call this method before accessing the shared manager in order to configure the shared audio manager + */ ++ (void) configure: (tAudioManagerMode) mode { + configuredMode = mode; + configured = TRUE; +} + +-(BOOL) isOtherAudioPlaying { + UInt32 isPlaying = 0; + UInt32 varSize = sizeof(isPlaying); + AudioSessionGetProperty (kAudioSessionProperty_OtherAudioIsPlaying, &varSize, &isPlaying); + return (isPlaying != 0); +} + +-(void) setMode:(tAudioManagerMode) mode { + + _mode = mode; + switch (_mode) { + + case kAMM_FxOnly: + //Share audio with other app + CDLOGINFO(@"Denshion::CDAudioManager - Audio will be shared"); + //_audioSessionCategory = kAudioSessionCategory_AmbientSound; + _audioSessionCategory = AVAudioSessionCategoryAmbient; + willPlayBackgroundMusic = NO; + break; + + case kAMM_FxPlusMusic: + //Use audio exclusively - if other audio is playing it will be stopped + CDLOGINFO(@"Denshion::CDAudioManager - Audio will be exclusive"); + //_audioSessionCategory = kAudioSessionCategory_SoloAmbientSound; + _audioSessionCategory = AVAudioSessionCategorySoloAmbient; + willPlayBackgroundMusic = YES; + break; + + case kAMM_MediaPlayback: + //Use audio exclusively, ignore mute switch and sleep + CDLOGINFO(@"Denshion::CDAudioManager - Media playback mode, audio will be exclusive"); + //_audioSessionCategory = kAudioSessionCategory_MediaPlayback; + _audioSessionCategory = AVAudioSessionCategoryPlayback; + willPlayBackgroundMusic = YES; + break; + + case kAMM_PlayAndRecord: + //Use audio exclusively, ignore mute switch and sleep, has inputs and outputs + CDLOGINFO(@"Denshion::CDAudioManager - Play and record mode, audio will be exclusive"); + //_audioSessionCategory = kAudioSessionCategory_PlayAndRecord; + _audioSessionCategory = AVAudioSessionCategoryPlayAndRecord; + willPlayBackgroundMusic = YES; + break; + + default: + //kAudioManagerFxPlusMusicIfNoOtherAudio + if ([self isOtherAudioPlaying]) { + CDLOGINFO(@"Denshion::CDAudioManager - Other audio is playing audio will be shared"); + //_audioSessionCategory = kAudioSessionCategory_AmbientSound; + _audioSessionCategory = AVAudioSessionCategoryAmbient; + willPlayBackgroundMusic = NO; + } else { + CDLOGINFO(@"Denshion::CDAudioManager - Other audio is not playing audio will be exclusive"); + //_audioSessionCategory = kAudioSessionCategory_SoloAmbientSound; + _audioSessionCategory = AVAudioSessionCategorySoloAmbient; + willPlayBackgroundMusic = YES; + } + + break; + } + + [self audioSessionSetCategory:_audioSessionCategory]; + +} + +/** + * This method is used to work around various bugs introduced in 4.x OS versions. In some circumstances the + * audio session is interrupted but never resumed, this results in the loss of OpenAL audio when following + * standard practices. If we detect this situation then we will attempt to resume the audio session ourselves. + * Known triggers: lock the device then unlock it (iOS 4.2 gm), playback a song using MPMediaPlayer (iOS 4.0) + */ +- (void) badAlContextHandler { + if (_interrupted && alcGetCurrentContext() == NULL) { + CDLOG(@"Denshion::CDAudioManager - bad OpenAL context detected, attempting to resume audio session"); + [self audioSessionResumed]; + } +} + +- (id) init: (tAudioManagerMode) mode { + if ((self = [super init])) { + + //Initialise the audio session + AVAudioSession* session = [AVAudioSession sharedInstance]; + session.delegate = self; + + _mode = mode; + backgroundMusicCompletionSelector = nil; + _isObservingAppEvents = FALSE; + _mute = NO; + _resigned = NO; + _interrupted = NO; + enabled_ = YES; + _audioSessionActive = NO; + [self setMode:mode]; + soundEngine = [[CDSoundEngine alloc] init]; + + //Set up audioSource channels + audioSourceChannels = [[NSMutableArray alloc] init]; + CDLongAudioSource *leftChannel = [[CDLongAudioSource alloc] init]; + leftChannel.backgroundMusic = YES; + CDLongAudioSource *rightChannel = [[CDLongAudioSource alloc] init]; + rightChannel.backgroundMusic = NO; + [audioSourceChannels insertObject:leftChannel atIndex:kASC_Left]; + [audioSourceChannels insertObject:rightChannel atIndex:kASC_Right]; + [leftChannel release]; + [rightChannel release]; + //Used to support legacy APIs + backgroundMusic = [self audioSourceForChannel:BACKGROUND_MUSIC_CHANNEL]; + backgroundMusic.delegate = self; + + //Add handler for bad al context messages, these are posted by the sound engine. + [[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(badAlContextHandler) name:kCDN_BadAlContext object:nil]; + + } + return self; +} + +-(void) dealloc { + CDLOGINFO(@"Denshion::CDAudioManager - deallocating"); + [self stopBackgroundMusic]; + [soundEngine release]; + [[NSNotificationCenter defaultCenter] removeObserver:self]; + [self audioSessionSetActive:NO]; + [audioSourceChannels release]; + [super dealloc]; +} + +/** Retrieves the audio source for the specified channel */ +-(CDLongAudioSource*) audioSourceForChannel:(tAudioSourceChannel) channel +{ + return (CDLongAudioSource*)[audioSourceChannels objectAtIndex:channel]; +} + +/** Loads the data from the specified file path to the channel's audio source */ +-(CDLongAudioSource*) audioSourceLoad:(NSString*) filePath channel:(tAudioSourceChannel) channel +{ + CDLongAudioSource *audioSource = [self audioSourceForChannel:channel]; + if (audioSource) { + [audioSource load:filePath]; + } + return audioSource; +} + +-(BOOL) isBackgroundMusicPlaying { + return [self.backgroundMusic isPlaying]; +} + +//NB: originally I tried using a route change listener and intended to store the current route, +//however, on a 3gs running 3.1.2 no route change is generated when the user switches the +//ringer mute switch to off (i.e. enables sound) therefore polling is the only reliable way to +//determine ringer switch state +-(BOOL) isDeviceMuted { + +#if TARGET_IPHONE_SIMULATOR + //Calling audio route stuff on the simulator causes problems + return NO; +#else + CFStringRef newAudioRoute; + UInt32 propertySize = sizeof (CFStringRef); + + AudioSessionGetProperty ( + kAudioSessionProperty_AudioRoute, + &propertySize, + &newAudioRoute + ); + + if (newAudioRoute == NULL) { + //Don't expect this to happen but playing safe otherwise a null in the CFStringCompare will cause a crash + return YES; + } else { + CFComparisonResult newDeviceIsMuted = CFStringCompare ( + newAudioRoute, + (CFStringRef) @"", + 0 + ); + + return (newDeviceIsMuted == kCFCompareEqualTo); + } +#endif +} + +#pragma mark Audio Interrupt Protocol + +-(BOOL) mute { + return _mute; +} + +-(void) setMute:(BOOL) muteValue { + if (muteValue != _mute) { + _mute = muteValue; + [soundEngine setMute:muteValue]; + for( CDLongAudioSource *audioSource in audioSourceChannels) { + audioSource.mute = muteValue; + } + } +} + +-(BOOL) enabled { + return enabled_; +} + +-(void) setEnabled:(BOOL) enabledValue { + if (enabledValue != enabled_) { + enabled_ = enabledValue; + [soundEngine setEnabled:enabled_]; + for( CDLongAudioSource *audioSource in audioSourceChannels) { + audioSource.enabled = enabled_; + } + } +} + +-(CDLongAudioSource*) backgroundMusic +{ + return backgroundMusic; +} + +//Load background music ready for playing +-(void) preloadBackgroundMusic:(NSString*) filePath +{ + [self.backgroundMusic load:filePath]; +} + +-(void) playBackgroundMusic:(NSString*) filePath loop:(BOOL) loop +{ + [self.backgroundMusic load:filePath]; + + if (loop) { + [self.backgroundMusic setNumberOfLoops:-1]; + } else { + [self.backgroundMusic setNumberOfLoops:0]; + } + + if (!willPlayBackgroundMusic || _mute) { + CDLOGINFO(@"Denshion::CDAudioManager - play bgm aborted because audio is not exclusive or sound is muted"); + return; + } + + [self.backgroundMusic play]; +} + +-(void) stopBackgroundMusic +{ + [self.backgroundMusic stop]; +} + +-(void) pauseBackgroundMusic +{ + [self.backgroundMusic pause]; +} + +-(void) resumeBackgroundMusic +{ + if (!willPlayBackgroundMusic || _mute) { + CDLOGINFO(@"Denshion::CDAudioManager - resume bgm aborted because audio is not exclusive or sound is muted"); + return; + } + + [self.backgroundMusic resume]; +} + +-(void) rewindBackgroundMusic +{ + [self.backgroundMusic rewind]; +} + +-(void) setBackgroundMusicCompletionListener:(id) listener selector:(SEL) selector { + backgroundMusicCompletionListener = listener; + backgroundMusicCompletionSelector = selector; +} + +/* + * Call this method to have the audio manager automatically handle application resign and + * become active. Pass a tAudioManagerResignBehavior to indicate the desired behavior + * for resigning and becoming active again. + * + * If autohandle is YES then the applicationWillResignActive and applicationDidBecomActive + * methods are automatically called, otherwise you must call them yourself at the appropriate time. + * + * Based on idea of Dominique Bongard + */ +-(void) setResignBehavior:(tAudioManagerResignBehavior) resignBehavior autoHandle:(BOOL) autoHandle { + + if (!_isObservingAppEvents && autoHandle) { + [[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(applicationWillResignActive:) name:@"UIApplicationWillResignActiveNotification" object:nil]; + [[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(applicationDidBecomeActive:) name:@"UIApplicationDidBecomeActiveNotification" object:nil]; + [[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(applicationWillTerminate:) name:@"UIApplicationWillTerminateNotification" object:nil]; + _isObservingAppEvents = TRUE; + } + _resignBehavior = resignBehavior; +} + +- (void) applicationWillResignActive { + self->_resigned = YES; + + //Set the audio sesssion to one that allows sharing so that other audio won't be clobbered on resume + [self audioSessionSetCategory:AVAudioSessionCategoryAmbient]; + + switch (_resignBehavior) { + + case kAMRBStopPlay: + + for( CDLongAudioSource *audioSource in audioSourceChannels) { + if (audioSource.isPlaying) { + audioSource->systemPaused = YES; + audioSource->systemPauseLocation = audioSource.audioSourcePlayer.currentTime; + [audioSource stop]; + } else { + //Music is either paused or stopped, if it is paused it will be restarted + //by OS so we will stop it. + audioSource->systemPaused = NO; + [audioSource stop]; + } + } + break; + + case kAMRBStop: + //Stop music regardless of whether it is playing or not because if it was paused + //then the OS would resume it + for( CDLongAudioSource *audioSource in audioSourceChannels) { + [audioSource stop]; + } + + default: + break; + + } + CDLOGINFO(@"Denshion::CDAudioManager - handled resign active"); +} + +//Called when application resigns active only if setResignBehavior has been called +- (void) applicationWillResignActive:(NSNotification *) notification +{ + [self applicationWillResignActive]; +} + +- (void) applicationDidBecomeActive { + + if (self->_resigned) { + _resigned = NO; + //Reset the mode incase something changed with audio while we were inactive + [self setMode:_mode]; + switch (_resignBehavior) { + + case kAMRBStopPlay: + + //Music had been stopped but stop maintains current time + //so playing again will continue from where music was before resign active. + //We check if music can be played because while we were inactive the user might have + //done something that should force music to not play such as starting a track in the iPod + if (self.willPlayBackgroundMusic) { + for( CDLongAudioSource *audioSource in audioSourceChannels) { + if (audioSource->systemPaused) { + [audioSource resume]; + audioSource->systemPaused = NO; + } + } + } + break; + + default: + break; + + } + CDLOGINFO(@"Denshion::CDAudioManager - audio manager handled become active"); + } +} + +//Called when application becomes active only if setResignBehavior has been called +- (void) applicationDidBecomeActive:(NSNotification *) notification +{ + [self applicationDidBecomeActive]; +} + +//Called when application terminates only if setResignBehavior has been called +- (void) applicationWillTerminate:(NSNotification *) notification +{ + CDLOGINFO(@"Denshion::CDAudioManager - audio manager handling terminate"); + [self stopBackgroundMusic]; +} + +/** The audio source completed playing */ +- (void) cdAudioSourceDidFinishPlaying:(CDLongAudioSource *) audioSource { + CDLOGINFO(@"Denshion::CDAudioManager - audio manager got told background music finished"); + if (backgroundMusicCompletionSelector != nil) { + [backgroundMusicCompletionListener performSelector:backgroundMusicCompletionSelector]; + } +} + +-(void) beginInterruption { + CDLOGINFO(@"Denshion::CDAudioManager - begin interruption"); + [self audioSessionInterrupted]; +} + +-(void) endInterruption { + CDLOGINFO(@"Denshion::CDAudioManager - end interruption"); + [self audioSessionResumed]; +} + +#if __CC_PLATFORM_IOS >= 40000 +-(void) endInterruptionWithFlags:(NSUInteger)flags { + CDLOGINFO(@"Denshion::CDAudioManager - interruption ended with flags %i",flags); + if (flags == AVAudioSessionInterruptionFlags_ShouldResume) { + [self audioSessionResumed]; + } +} +#endif + +-(void)audioSessionInterrupted +{ + if (!_interrupted) { + CDLOGINFO(@"Denshion::CDAudioManager - Audio session interrupted"); + _interrupted = YES; + + // Deactivate the current audio session + [self audioSessionSetActive:NO]; + + if (alcGetCurrentContext() != NULL) { + CDLOGINFO(@"Denshion::CDAudioManager - Setting OpenAL context to NULL"); + + ALenum error = AL_NO_ERROR; + + // set the current context to NULL will 'shutdown' openAL + alcMakeContextCurrent(NULL); + + if((error = alGetError()) != AL_NO_ERROR) { + CDLOG(@"Denshion::CDAudioManager - Error making context current %x\n", error); + } + #pragma unused(error) + } + } +} + +-(void)audioSessionResumed +{ + if (_interrupted) { + CDLOGINFO(@"Denshion::CDAudioManager - Audio session resumed"); + _interrupted = NO; + + BOOL activationResult = NO; + // Reactivate the current audio session + activationResult = [self audioSessionSetActive:YES]; + + //This code is to handle a problem with iOS 4.0 and 4.01 where reactivating the session can fail if + //task switching is performed too rapidly. A test case that reliably reproduces the issue is to call the + //iPhone and then hang up after two rings (timing may vary ;)) + //Basically we keep waiting and trying to let the OS catch up with itself but the number of tries is + //limited. + if (!activationResult) { + CDLOG(@"Denshion::CDAudioManager - Failure reactivating audio session, will try wait-try cycle"); + int activateCount = 0; + while (!activationResult && activateCount < 10) { + [NSThread sleepForTimeInterval:0.5]; + activationResult = [self audioSessionSetActive:YES]; + activateCount++; + CDLOGINFO(@"Denshion::CDAudioManager - Reactivation attempt %i status = %i",activateCount,activationResult); + } + } + + if (alcGetCurrentContext() == NULL) { + CDLOGINFO(@"Denshion::CDAudioManager - Restoring OpenAL context"); + ALenum error = AL_NO_ERROR; + // Restore open al context + alcMakeContextCurrent([soundEngine openALContext]); + if((error = alGetError()) != AL_NO_ERROR) { + CDLOG(@"Denshion::CDAudioManager - Error making context current%x\n", error); + } + #pragma unused(error) + } + } +} + ++(void) end { + [sharedManager release]; + sharedManager = nil; +} + +@end + +/////////////////////////////////////////////////////////////////////////////////////// +@implementation CDLongAudioSourceFader + +-(void) _setTargetProperty:(float) newVal { + ((CDLongAudioSource*)target).volume = newVal; +} + +-(float) _getTargetProperty { + return ((CDLongAudioSource*)target).volume; +} + +-(void) _stopTarget { + //Pause instead of stop as stop releases resources and causes problems in the simulator + [((CDLongAudioSource*)target) pause]; +} + +-(Class) _allowableType { + return [CDLongAudioSource class]; +} + +@end +/////////////////////////////////////////////////////////////////////////////////////// +@implementation CDBufferManager + +-(id) initWithEngine:(CDSoundEngine *) theSoundEngine { + if ((self = [super init])) { + soundEngine = theSoundEngine; + loadedBuffers = [[NSMutableDictionary alloc] initWithCapacity:CD_BUFFERS_START]; + freedBuffers = [[NSMutableArray alloc] init]; + nextBufferId = 0; + } + return self; +} + +-(void) dealloc { + [loadedBuffers release]; + [freedBuffers release]; + [super dealloc]; +} + +-(int) bufferForFile:(NSString*) filePath create:(BOOL) create { + + NSNumber* soundId = (NSNumber*)[loadedBuffers objectForKey:filePath]; + if(soundId == nil) + { + if (create) { + NSNumber* bufferId = nil; + //First try to get a buffer from the free buffers + if ([freedBuffers count] > 0) { + bufferId = [[[freedBuffers lastObject] retain] autorelease]; + [freedBuffers removeLastObject]; + CDLOGINFO(@"Denshion::CDBufferManager reusing buffer id %i",[bufferId intValue]); + } else { + bufferId = [[NSNumber alloc] initWithInt:nextBufferId]; + [bufferId autorelease]; + CDLOGINFO(@"Denshion::CDBufferManager generating new buffer id %i",[bufferId intValue]); + nextBufferId++; + } + + if ([soundEngine loadBuffer:[bufferId intValue] filePath:filePath]) { + //File successfully loaded + CDLOGINFO(@"Denshion::CDBufferManager buffer loaded %@ %@",bufferId,filePath); + [loadedBuffers setObject:bufferId forKey:filePath]; + return [bufferId intValue]; + } else { + //File didn't load, put buffer id on free list + [freedBuffers addObject:bufferId]; + return kCDNoBuffer; + } + } else { + //No matching buffer was found + return kCDNoBuffer; + } + } else { + return [soundId intValue]; + } +} + +-(void) releaseBufferForFile:(NSString *) filePath { + int bufferId = [self bufferForFile:filePath create:NO]; + if (bufferId != kCDNoBuffer) { + [soundEngine unloadBuffer:bufferId]; + [loadedBuffers removeObjectForKey:filePath]; + NSNumber *freedBufferId = [[NSNumber alloc] initWithInt:bufferId]; + [freedBufferId autorelease]; + [freedBuffers addObject:freedBufferId]; + } +} +@end + + + diff --git "a/21451198\345\215\242\350\266\205/project5/MyPlane/libs/CocosDenshion/CDConfig.h" "b/21451198\345\215\242\350\266\205/project5/MyPlane/libs/CocosDenshion/CDConfig.h" new file mode 100644 index 00000000..b258a1fd --- /dev/null +++ "b/21451198\345\215\242\350\266\205/project5/MyPlane/libs/CocosDenshion/CDConfig.h" @@ -0,0 +1,60 @@ +/* + Copyright (c) 2010 Steve Oldmeadow + + Permission is hereby granted, free of charge, to any person obtaining a copy + of this software and associated documentation files (the "Software"), to deal + in the Software without restriction, including without limitation the rights + to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + copies of the Software, and to permit persons to whom the Software is + furnished to do so, subject to the following conditions: + + The above copyright notice and this permission notice shall be included in + all copies or substantial portions of the Software. + + THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + THE SOFTWARE. + + $Id$ + */ +#define COCOSDENSHION_VERSION "Aphex.rc" + + +/** + If enabled code useful for debugging such as parameter check assertions will be performed. + If you experience any problems you should enable this and test your code with a debug build. + */ +//#define CD_DEBUG 1 + +/** + The total number of sounds/buffers that can be loaded assuming memory is sufficient + */ +//Number of buffers slots that will be initially created +#define CD_BUFFERS_START 64 +//Number of buffers that will be added +#define CD_BUFFERS_INCREMENT 16 + +/** + If enabled, OpenAL code will use static buffers. When static buffers are used the audio + data is managed outside of OpenAL, this eliminates a memcpy operation which leads to + higher performance when loading sounds. + + However, the downside is that when the audio data is freed you must + be certain that it is no longer being accessed otherwise your app will crash. Testing on OS 2.2.1 + and 3.1.2 has shown that this may occur if a buffer is being used by a source with state = AL_PLAYING + when the buffer is deleted. If the data is freed too quickly after the source is stopped then + a crash will occur. The implemented workaround is that when static buffers are used the unloadBuffer code will wait for + any playing sources to finish playing before the associated buffer and data are deleted, however, this delay may negate any + performance gains that are achieved during loading. + + Performance tests on a 1st gen iPod running OS 2.2.1 loading the CocosDenshionDemo sounds were ~0.14 seconds without + static buffers and ~0.12 seconds when using static buffers. + + */ +//#define CD_USE_STATIC_BUFFERS 1 + + diff --git "a/21451198\345\215\242\350\266\205/project5/MyPlane/libs/CocosDenshion/CDOpenALSupport.h" "b/21451198\345\215\242\350\266\205/project5/MyPlane/libs/CocosDenshion/CDOpenALSupport.h" new file mode 100644 index 00000000..a7f21b1c --- /dev/null +++ "b/21451198\345\215\242\350\266\205/project5/MyPlane/libs/CocosDenshion/CDOpenALSupport.h" @@ -0,0 +1,77 @@ +/* + + Disclaimer: IMPORTANT: This Apple software is supplied to you by + Apple Inc. ("Apple") in consideration of your agreement to the + following terms, and your use, installation, modification or + redistribution of this Apple software constitutes acceptance of these + terms. If you do not agree with these terms, please do not use, + install, modify or redistribute this Apple software. + + In consideration of your agreement to abide by the following terms, and + subject to these terms, Apple grants you a personal, non-exclusive + license, under Apple's copyrights in this original Apple software (the + "Apple Software"), to use, reproduce, modify and redistribute the Apple + Software, with or without modifications, in source and/or binary forms; + provided that if you redistribute the Apple Software in its entirety and + without modifications, you must retain this notice and the following + text and disclaimers in all such redistributions of the Apple Software. + Neither the name, trademarks, service marks or logos of Apple Inc. + may be used to endorse or promote products derived from the Apple + Software without specific prior written permission from Apple. Except + as expressly stated in this notice, no other rights or licenses, express + or implied, are granted by Apple herein, including but not limited to + any patent rights that may be infringed by your derivative works or by + other works in which the Apple Software may be incorporated. + + The Apple Software is provided by Apple on an "AS IS" basis. APPLE + MAKES NO WARRANTIES, EXPRESS OR IMPLIED, INCLUDING WITHOUT LIMITATION + THE IMPLIED WARRANTIES OF NON-INFRINGEMENT, MERCHANTABILITY AND FITNESS + FOR A PARTICULAR PURPOSE, REGARDING THE APPLE SOFTWARE OR ITS USE AND + OPERATION ALONE OR IN COMBINATION WITH YOUR PRODUCTS. + + IN NO EVENT SHALL APPLE BE LIABLE FOR ANY SPECIAL, INDIRECT, INCIDENTAL + OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + INTERRUPTION) ARISING IN ANY WAY OUT OF THE USE, REPRODUCTION, + MODIFICATION AND/OR DISTRIBUTION OF THE APPLE SOFTWARE, HOWEVER CAUSED + AND WHETHER UNDER THEORY OF CONTRACT, TORT (INCLUDING NEGLIGENCE), + STRICT LIABILITY OR OTHERWISE, EVEN IF APPLE HAS BEEN ADVISED OF THE + POSSIBILITY OF SUCH DAMAGE. + + Copyright (C) 2009 Apple Inc. All Rights Reserved. + + $Id$ + */ + +/* + This file contains code from version 1.1 and 1.4 of MyOpenALSupport.h taken from Apple's oalTouch version. + The 1.4 version code is used for loading IMA4 files, however, this code causes very noticeable clicking + when used to load wave files that are looped so the 1.1 version code is used specifically for loading + wav files. + */ + +#ifndef __CD_OPENAL_H +#define __CD_OPENAL_H + +#ifdef __cplusplus +extern "C" { +#endif + + +#import +#import +#import + + +//Taken from oalTouch MyOpenALSupport 1.1 +void* CDloadWaveAudioData(CFURLRef inFileURL, ALsizei *outDataSize, ALenum *outDataFormat, ALsizei* outSampleRate); +void* CDloadCafAudioData(CFURLRef inFileURL, ALsizei *outDataSize, ALenum *outDataFormat, ALsizei* outSampleRate); +void* CDGetOpenALAudioData(CFURLRef inFileURL, ALsizei *outDataSize, ALenum *outDataFormat, ALsizei* outSampleRate); + +#ifdef __cplusplus +} +#endif + +#endif + + diff --git "a/21451198\345\215\242\350\266\205/project5/MyPlane/libs/CocosDenshion/CDOpenALSupport.m" "b/21451198\345\215\242\350\266\205/project5/MyPlane/libs/CocosDenshion/CDOpenALSupport.m" new file mode 100644 index 00000000..d2d9e397 --- /dev/null +++ "b/21451198\345\215\242\350\266\205/project5/MyPlane/libs/CocosDenshion/CDOpenALSupport.m" @@ -0,0 +1,250 @@ +/* + + Disclaimer: IMPORTANT: This Apple software is supplied to you by + Apple Inc. ("Apple") in consideration of your agreement to the + following terms, and your use, installation, modification or + redistribution of this Apple software constitutes acceptance of these + terms. If you do not agree with these terms, please do not use, + install, modify or redistribute this Apple software. + + In consideration of your agreement to abide by the following terms, and + subject to these terms, Apple grants you a personal, non-exclusive + license, under Apple's copyrights in this original Apple software (the + "Apple Software"), to use, reproduce, modify and redistribute the Apple + Software, with or without modifications, in source and/or binary forms; + provided that if you redistribute the Apple Software in its entirety and + without modifications, you must retain this notice and the following + text and disclaimers in all such redistributions of the Apple Software. + Neither the name, trademarks, service marks or logos of Apple Inc. + may be used to endorse or promote products derived from the Apple + Software without specific prior written permission from Apple. Except + as expressly stated in this notice, no other rights or licenses, express + or implied, are granted by Apple herein, including but not limited to + any patent rights that may be infringed by your derivative works or by + other works in which the Apple Software may be incorporated. + + The Apple Software is provided by Apple on an "AS IS" basis. APPLE + MAKES NO WARRANTIES, EXPRESS OR IMPLIED, INCLUDING WITHOUT LIMITATION + THE IMPLIED WARRANTIES OF NON-INFRINGEMENT, MERCHANTABILITY AND FITNESS + FOR A PARTICULAR PURPOSE, REGARDING THE APPLE SOFTWARE OR ITS USE AND + OPERATION ALONE OR IN COMBINATION WITH YOUR PRODUCTS. + + IN NO EVENT SHALL APPLE BE LIABLE FOR ANY SPECIAL, INDIRECT, INCIDENTAL + OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + INTERRUPTION) ARISING IN ANY WAY OUT OF THE USE, REPRODUCTION, + MODIFICATION AND/OR DISTRIBUTION OF THE APPLE SOFTWARE, HOWEVER CAUSED + AND WHETHER UNDER THEORY OF CONTRACT, TORT (INCLUDING NEGLIGENCE), + STRICT LIABILITY OR OTHERWISE, EVEN IF APPLE HAS BEEN ADVISED OF THE + POSSIBILITY OF SUCH DAMAGE. + + Copyright (C) 2009 Apple Inc. All Rights Reserved. + + $Id: CDOpenALSupport.h 16 2010-03-11 06:22:10Z steveoldmeadow $ + */ + +#import "CDOpenALSupport.h" +#import "CocosDenshion.h" +#import +#import + +//Taken from oalTouch MyOpenALSupport 1.1 +void* CDloadWaveAudioData(CFURLRef inFileURL, ALsizei *outDataSize, ALenum *outDataFormat, ALsizei* outSampleRate) +{ + OSStatus err = noErr; + UInt64 fileDataSize = 0; + AudioStreamBasicDescription theFileFormat; + UInt32 thePropertySize = sizeof(theFileFormat); + AudioFileID afid = 0; + void* theData = NULL; + + // Open a file with ExtAudioFileOpen() + err = AudioFileOpenURL(inFileURL, kAudioFileReadPermission, 0, &afid); + if(err) { CDLOG(@"MyGetOpenALAudioData: AudioFileOpenURL FAILED, Error = %ld\n", err); goto Exit; } + + // Get the audio data format + err = AudioFileGetProperty(afid, kAudioFilePropertyDataFormat, &thePropertySize, &theFileFormat); + if(err) { CDLOG(@"MyGetOpenALAudioData: AudioFileGetProperty(kAudioFileProperty_DataFormat) FAILED, Error = %ld\n", err); goto Exit; } + + if (theFileFormat.mChannelsPerFrame > 2) { + CDLOG(@"MyGetOpenALAudioData - Unsupported Format, channel count is greater than stereo\n"); goto Exit; + } + + if ((theFileFormat.mFormatID != kAudioFormatLinearPCM) || (!TestAudioFormatNativeEndian(theFileFormat))) { + CDLOG(@"MyGetOpenALAudioData - Unsupported Format, must be little-endian PCM\n"); goto Exit; + } + + if ((theFileFormat.mBitsPerChannel != 8) && (theFileFormat.mBitsPerChannel != 16)) { + CDLOG(@"MyGetOpenALAudioData - Unsupported Format, must be 8 or 16 bit PCM\n"); goto Exit; + } + + + thePropertySize = sizeof(fileDataSize); + err = AudioFileGetProperty(afid, kAudioFilePropertyAudioDataByteCount, &thePropertySize, &fileDataSize); + if(err) { CDLOG(@"MyGetOpenALAudioData: AudioFileGetProperty(kAudioFilePropertyAudioDataByteCount) FAILED, Error = %ld\n", err); goto Exit; } + + // Read all the data into memory + UInt32 dataSize = (UInt32)fileDataSize; + theData = malloc(dataSize); + if (theData) + { + memset(theData, 0, dataSize); + + AudioFileReadBytes(afid, false, 0, &dataSize, theData); + if(err == noErr) + { + // success + *outDataSize = (ALsizei)dataSize; + //This fix was added by me, however, 8 bit sounds have a clipping sound at the end so aren't really usable (SO) + if (theFileFormat.mBitsPerChannel == 16) { + *outDataFormat = (theFileFormat.mChannelsPerFrame > 1) ? AL_FORMAT_STEREO16 : AL_FORMAT_MONO16; + } else { + *outDataFormat = (theFileFormat.mChannelsPerFrame > 1) ? AL_FORMAT_STEREO8 : AL_FORMAT_MONO8; + } + *outSampleRate = (ALsizei)theFileFormat.mSampleRate; + } + else + { + // failure + free (theData); + theData = NULL; // make sure to return NULL + CDLOG(@"MyGetOpenALAudioData: ExtAudioFileRead FAILED, Error = %ld\n", err); goto Exit; + } + } + +Exit: + // Dispose the ExtAudioFileRef, it is no longer needed + if (afid) AudioFileClose(afid); + return theData; +} + +//Taken from oalTouch MyOpenALSupport 1.4 +void* CDloadCafAudioData(CFURLRef inFileURL, ALsizei *outDataSize, ALenum *outDataFormat, ALsizei* outSampleRate) +{ + OSStatus status = noErr; + BOOL abort = NO; + SInt64 theFileLengthInFrames = 0; + AudioStreamBasicDescription theFileFormat; + UInt32 thePropertySize = sizeof(theFileFormat); + ExtAudioFileRef extRef = NULL; + void* theData = NULL; + AudioStreamBasicDescription theOutputFormat; + UInt32 dataSize = 0; + + // Open a file with ExtAudioFileOpen() + status = ExtAudioFileOpenURL(inFileURL, &extRef); + if (status != noErr) + { + CDLOG(@"MyGetOpenALAudioData: ExtAudioFileOpenURL FAILED, Error = %ld\n", status); + abort = YES; + } + if (abort) + goto Exit; + + // Get the audio data format + status = ExtAudioFileGetProperty(extRef, kExtAudioFileProperty_FileDataFormat, &thePropertySize, &theFileFormat); + if (status != noErr) + { + CDLOG(@"MyGetOpenALAudioData: ExtAudioFileGetProperty(kExtAudioFileProperty_FileDataFormat) FAILED, Error = %ld\n", status); + abort = YES; + } + if (abort) + goto Exit; + + if (theFileFormat.mChannelsPerFrame > 2) + { + CDLOG(@"MyGetOpenALAudioData - Unsupported Format, channel count is greater than stereo\n"); + abort = YES; + } + if (abort) + goto Exit; + + // Set the client format to 16 bit signed integer (native-endian) data + // Maintain the channel count and sample rate of the original source format + theOutputFormat.mSampleRate = theFileFormat.mSampleRate; + theOutputFormat.mChannelsPerFrame = theFileFormat.mChannelsPerFrame; + + theOutputFormat.mFormatID = kAudioFormatLinearPCM; + theOutputFormat.mBytesPerPacket = 2 * theOutputFormat.mChannelsPerFrame; + theOutputFormat.mFramesPerPacket = 1; + theOutputFormat.mBytesPerFrame = 2 * theOutputFormat.mChannelsPerFrame; + theOutputFormat.mBitsPerChannel = 16; + theOutputFormat.mFormatFlags = kAudioFormatFlagsNativeEndian | kAudioFormatFlagIsPacked | kAudioFormatFlagIsSignedInteger; + + // Set the desired client (output) data format + status = ExtAudioFileSetProperty(extRef, kExtAudioFileProperty_ClientDataFormat, sizeof(theOutputFormat), &theOutputFormat); + if (status != noErr) + { + CDLOG(@"MyGetOpenALAudioData: ExtAudioFileSetProperty(kExtAudioFileProperty_ClientDataFormat) FAILED, Error = %ld\n", status); + abort = YES; + } + if (abort) + goto Exit; + + // Get the total frame count + thePropertySize = sizeof(theFileLengthInFrames); + status = ExtAudioFileGetProperty(extRef, kExtAudioFileProperty_FileLengthFrames, &thePropertySize, &theFileLengthInFrames); + if (status != noErr) + { + CDLOG(@"MyGetOpenALAudioData: ExtAudioFileGetProperty(kExtAudioFileProperty_FileLengthFrames) FAILED, Error = %ld\n", status); + abort = YES; + } + if (abort) + goto Exit; + + // Read all the data into memory + dataSize = (UInt32) theFileLengthInFrames * theOutputFormat.mBytesPerFrame; + theData = malloc(dataSize); + if (theData) + { + memset(theData, 0, dataSize); + + AudioBufferList theDataBuffer; + theDataBuffer.mNumberBuffers = 1; + theDataBuffer.mBuffers[0].mDataByteSize = dataSize; + theDataBuffer.mBuffers[0].mNumberChannels = theOutputFormat.mChannelsPerFrame; + theDataBuffer.mBuffers[0].mData = theData; + + // Read the data into an AudioBufferList + status = ExtAudioFileRead(extRef, (UInt32*)&theFileLengthInFrames, &theDataBuffer); + if(status == noErr) + { + // success + *outDataSize = (ALsizei)dataSize; + *outDataFormat = (theOutputFormat.mChannelsPerFrame > 1) ? AL_FORMAT_STEREO16 : AL_FORMAT_MONO16; + *outSampleRate = (ALsizei)theOutputFormat.mSampleRate; + } + else + { + // failure + free (theData); + theData = NULL; // make sure to return NULL + CDLOG(@"MyGetOpenALAudioData: ExtAudioFileRead FAILED, Error = %ld\n", status); + abort = YES; + } + } + if (abort) + goto Exit; + +Exit: + // Dispose the ExtAudioFileRef, it is no longer needed + if (extRef) ExtAudioFileDispose(extRef); + return theData; +} + +void* CDGetOpenALAudioData(CFURLRef inFileURL, ALsizei *outDataSize, ALenum *outDataFormat, ALsizei* outSampleRate) { + + CFStringRef extension = CFURLCopyPathExtension(inFileURL); + CFComparisonResult isWavFile = 0; + if (extension != NULL) { + isWavFile = CFStringCompare (extension,(CFStringRef)@"wav", kCFCompareCaseInsensitive); + CFRelease(extension); + } + + if (isWavFile == kCFCompareEqualTo) { + return CDloadWaveAudioData(inFileURL, outDataSize, outDataFormat, outSampleRate); + } else { + return CDloadCafAudioData(inFileURL, outDataSize, outDataFormat, outSampleRate); + } +} + diff --git "a/21451198\345\215\242\350\266\205/project5/MyPlane/libs/CocosDenshion/CDXMacOSXSupport.h" "b/21451198\345\215\242\350\266\205/project5/MyPlane/libs/CocosDenshion/CDXMacOSXSupport.h" new file mode 100644 index 00000000..c1a99f05 --- /dev/null +++ "b/21451198\345\215\242\350\266\205/project5/MyPlane/libs/CocosDenshion/CDXMacOSXSupport.h" @@ -0,0 +1,232 @@ +/* + Copyright (c) 2010 Steve Oldmeadow + + Permission is hereby granted, free of charge, to any person obtaining a copy + of this software and associated documentation files (the "Software"), to deal + in the Software without restriction, including without limitation the rights + to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + copies of the Software, and to permit persons to whom the Software is + furnished to do so, subject to the following conditions: + + The above copyright notice and this permission notice shall be included in + all copies or substantial portions of the Software. + + THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + THE SOFTWARE. + + $Id$ + */ + +/** + A set of proxy classes to allow iOS audio code to run on MacOS X. AVAudioPlayer is implemented using NSSound. + AVAudioSession is a "do nothing" class as it isn't really relevant on MacOS X. + + Limitations: + AVAudioPlayer numberOfLoops not correctly supported. Looping is either on or off, can not specify a specific number of loops. + AVAudioPlayer panning not supported. + AVAudioPlayer metering not supported. + AVAudioSession nothing is supported, not applicable to MacOS X. + */ + +#import +#ifdef __IPHONE_OS_VERSION_MAX_ALLOWED +#elif defined(__MAC_OS_X_VERSION_MAX_ALLOWED) + +#import +#import + +enum AudioSessionProperties { + kAudioSessionProperty_OtherAudioIsPlaying, + kAudioSessionProperty_AudioRoute +}; + +extern OSStatus AudioSessionGetProperty(UInt32 inID, UInt32 *ioDataSize, void *outData); + +/** + Based on AVAudioPlayer.h header in AVFoundation headers + */ +@class NSData, NSURL, NSError, NSDictionary; +@protocol AVAudioPlayerDelegate; + +/* This class is available with iPhone 2.2 or later */ +@interface AVAudioPlayer : NSObject { + + // properties + id delegate; + NSUInteger numberOfChannels; + BOOL playing; + NSTimeInterval duration; + NSURL *url; + NSData *data; + float pan; + float volume; + NSTimeInterval currentTime; + NSTimeInterval deviceCurrentTime; + NSInteger numberOfLoops; + BOOL meteringEnabled; + + +@private + NSSound* _player; +} + +/* For all of these init calls, if a return value of nil is given you can check outError to see what the problem was. + If not nil, then the object is usable for playing + */ + +/* all data must be in the form of an audio file understood by CoreAudio */ +- (id)initWithContentsOfURL:(NSURL *)theUrl error:(NSError **)outError; +- (id)initWithData:(NSData *)theData error:(NSError **)outError; + +/* transport control */ +/* methods that return BOOL return YES on success and NO on failure. */ +- (BOOL)prepareToPlay; /* get ready to play the sound. happens automatically on play. */ +- (BOOL)play; /* sound is played asynchronously. */ +- (BOOL)playAtTime:(NSTimeInterval) time; /* play a sound some time in the future. time should be greater than deviceCurrentTime. */ +- (void)pause; /* pauses playback, but remains ready to play. */ +- (void)stop; /* stops playback. no longer ready to play. */ + +/* properties */ + +@property(readonly, getter=isPlaying) BOOL playing; + +@property(readonly) NSUInteger numberOfChannels; +@property(readonly) NSTimeInterval duration; /* the duration of the sound. */ + +@property(assign) id delegate; /* the delegate will be sent playerDidFinishPlaying */ + +/* one of these three properties will be non-nil based on the init... method used */ +@property(readonly) NSURL *url; /* returns nil if object was not created with a URL */ +@property(readonly) NSData *data; /* returns nil if object was not created with a data object */ +@property float pan; /* set panning. -1.0 is left, 0.0 is center, 1.0 is right. */ +@property float volume; /* The volume for the sound. The nominal range is from 0.0 to 1.0. */ + +/* If the sound is playing, currentTime is the offset into the sound of the current playback position. + If the sound is not playing, currentTime is the offset into the sound where playing would start. */ +@property NSTimeInterval currentTime; + +/* returns the current time associated with the output device */ +@property(readonly) NSTimeInterval deviceCurrentTime; + +/* "numberOfLoops" is the number of times that the sound will return to the beginning upon reaching the end. + A value of zero means to play the sound just once. + A value of one will result in playing the sound twice, and so on.. + Any negative number will loop indefinitely until stopped. + */ +@property NSInteger numberOfLoops; + +/* metering */ + +@property(getter=isMeteringEnabled) BOOL meteringEnabled; /* turns level metering on or off. default is off. */ + +- (void)updateMeters; /* call to refresh meter values */ +- (float)peakPowerForChannel:(NSUInteger)channelNumber; /* returns peak power in decibels for a given channel */ +- (float)averagePowerForChannel:(NSUInteger)channelNumber; /* returns average power in decibels for a given channel */ + +@end + +/* A protocol for delegates of AVAudioPlayer */ +@protocol AVAudioPlayerDelegate +@optional +/* audioPlayerDidFinishPlaying:successfully: is called when a sound has finished playing. This method is NOT called if the player is stopped due to an interruption. */ +- (void)audioPlayerDidFinishPlaying:(AVAudioPlayer *)player successfully:(BOOL)flag; + +/* if an error occurs while decoding it will be reported to the delegate. */ +- (void)audioPlayerDecodeErrorDidOccur:(AVAudioPlayer *)player error:(NSError *)error; + +/* audioPlayerBeginInterruption: is called when the audio session has been interrupted while the player was playing. The player will have been paused. */ +- (void)audioPlayerBeginInterruption:(AVAudioPlayer *)player; + +/* audioPlayerEndInterruption:withFlags: is called when the audio session interruption has ended and this player had been interrupted while playing. */ +/* Currently the only flag is AVAudioSessionInterruptionFlags_ShouldResume. */ +- (void)audioPlayerEndInterruption:(AVAudioPlayer *)player withFlags:(NSUInteger)flags; + +/* audioPlayerEndInterruption: is called when the preferred method, audioPlayerEndInterruption:withFlags:, is not implemented. */ +- (void)audioPlayerEndInterruption:(AVAudioPlayer *)player; +@end + + +/** + Taken from AVAudioSession.h header in AVFoundation headers + */ + +/* This protocol is available with iPhone 3.0 or later */ +@protocol AVAudioSessionDelegate; +@class NSError, NSString; + +/* values for the category property */ +extern NSString *const AVAudioSessionCategoryAmbient; +extern NSString *const AVAudioSessionCategorySoloAmbient; +extern NSString *const AVAudioSessionCategoryPlayback; +extern NSString *const AVAudioSessionCategoryRecord; +extern NSString *const AVAudioSessionCategoryPlayAndRecord; +extern NSString *const AVAudioSessionCategoryAudioProcessing; + +enum { + AVAudioSessionInterruptionFlags_ShouldResume = 1 +}; + +enum { + AVAudioSessionSetActiveFlags_NotifyOthersOnDeactivation = 1 +}; + +@interface AVAudioSession : NSObject { + + // properties + NSString* category; + double preferredHardwareSampleRate; + NSTimeInterval preferredIOBufferDuration; + + BOOL inputIsAvailable; + double currentHardwareSampleRate; + NSInteger currentHardwareInputNumberOfChannels; + NSInteger currentHardwareOutputNumberOfChannels; + id delegate; + +@private + __strong void *_impl; +} + +/* returns singleton instance */ ++ (id)sharedInstance; + +@property(assign) id delegate; + +- (BOOL)setActive:(BOOL)beActive error:(NSError**)outError; +- (BOOL)setActive:(BOOL)beActive withFlags:(NSInteger)flags error:(NSError**)outError; + +- (BOOL)setCategory:(NSString*)theCategory error:(NSError**)outError; +- (BOOL)setPreferredHardwareSampleRate:(double)sampleRate error:(NSError**)outError; +- (BOOL)setPreferredIOBufferDuration:(NSTimeInterval)duration error:(NSError**)outError; + +@property(readonly) NSString* category; +@property(readonly) double preferredHardwareSampleRate; +@property(readonly) NSTimeInterval preferredIOBufferDuration; + +@property(readonly) BOOL inputIsAvailable; +@property(readonly) double currentHardwareSampleRate; +@property(readonly) NSInteger currentHardwareInputNumberOfChannels; +@property(readonly) NSInteger currentHardwareOutputNumberOfChannels; + +@end + + +/* A protocol for delegates of AVAudioSession */ +@protocol AVAudioSessionDelegate +@optional + +- (void)beginInterruption; + +- (void)endInterruptionWithFlags:(NSUInteger)flags; + +- (void)endInterruption; /* endInterruptionWithFlags: will be called instead if implemented. */ + +- (void)inputIsAvailableChanged:(BOOL)isInputAvailable; +@end + +#endif diff --git "a/21451198\345\215\242\350\266\205/project5/MyPlane/libs/CocosDenshion/CDXMacOSXSupport.m" "b/21451198\345\215\242\350\266\205/project5/MyPlane/libs/CocosDenshion/CDXMacOSXSupport.m" new file mode 100644 index 00000000..99972155 --- /dev/null +++ "b/21451198\345\215\242\350\266\205/project5/MyPlane/libs/CocosDenshion/CDXMacOSXSupport.m" @@ -0,0 +1,175 @@ +/* + Copyright (c) 2010 Steve Oldmeadow + + Permission is hereby granted, free of charge, to any person obtaining a copy + of this software and associated documentation files (the "Software"), to deal + in the Software without restriction, including without limitation the rights + to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + copies of the Software, and to permit persons to whom the Software is + furnished to do so, subject to the following conditions: + + The above copyright notice and this permission notice shall be included in + all copies or substantial portions of the Software. + + THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + THE SOFTWARE. + + $Id$ + */ + +#import +#ifdef __IPHONE_OS_VERSION_MAX_ALLOWED +#elif defined(__MAC_OS_X_VERSION_MAX_ALLOWED) + +#import "CDXMacOSXSupport.h" +#import "SimpleAudioEngine.h" + +NSString * const AVAudioSessionCategoryAmbient = @"AVAudioSessionCategoryAmbient"; +NSString *const AVAudioSessionCategorySoloAmbient = @"AVAudioSessionCategorySoloAmbient"; +NSString *const AVAudioSessionCategoryPlayback = @"AVAudioSessionCategoryPlayback"; +NSString *const AVAudioSessionCategoryRecord = @"AVAudioSessionCategoryRecord"; +NSString *const AVAudioSessionCategoryPlayAndRecord = @"AVAudioSessionCategoryPlayAndRecord"; +NSString *const AVAudioSessionCategoryAudioProcessing = @"AVAudioSessionCategoryAudioProcessing"; + +OSStatus AudioSessionGetProperty(UInt32 inID, UInt32 *ioDataSize, void *outData) { + //TODO: set outData appropriately + return 0; +} + +@implementation AVAudioPlayer + +@synthesize delegate, numberOfChannels, pan, deviceCurrentTime, url, data; + +- (id)initWithContentsOfURL:(NSURL *)theUrl error:(NSError **)outError { + if ((self = [super init])) { + _player = [[NSSound alloc] initWithContentsOfURL:theUrl byReference:YES]; + if (_player != nil) { + _player.delegate = self; + CDLOG(@"Denshion::CDXMacOSXSupport - NSSound allocated for %@", theUrl); + } + } + return self; +} + +- (id)initWithData:(NSData *)theData error:(NSError **)outError { + if ((self = [super init])) { + _player = [[NSSound alloc] initWithData:theData]; + if (_player != nil) { + _player.delegate = self; + CDLOG(@"Denshion::CDXMacOSXSupport - NSSound allocated for %@", theData); + } + } + return self; +} + + +-(void) dealloc { + [_player release]; + [super dealloc]; +} + +- (void)sound:(NSSound *)sound didFinishPlaying:(BOOL)finished { + if (self.delegate && [self.delegate respondsToSelector:@selector(audioPlayerDidFinishPlaying:successfully:)]) { + [self.delegate audioPlayerDidFinishPlaying:self successfully:finished]; + } +} + +- (BOOL)play { + BOOL result; + result = [_player play]; + if (!result) { + //May be paused, try resuming instead + result = [_player resume]; + } + return result; +} + +-(void) pause { + [_player pause]; +} + +-(void) stop { + [_player stop]; +} + +-(BOOL) isPlaying { + return [_player isPlaying]; +} + +-(void) setVolume:(float) vol { + [_player setVolume:vol]; +} + +-(float) volume { + return [_player volume]; +} + +-(void) setNumberOfLoops:(NSInteger) nOfLoops { + if (nOfLoops < 0) { + [_player setLoops:YES]; + } else { + [_player setLoops:NO]; + } +} + +-(NSInteger) numberOfLoops { + if (_player.loops) { + return -1; + } else { + return 0; + } +} + +-(void) setCurrentTime:(NSTimeInterval) aCurrentTime { + [_player setCurrentTime:aCurrentTime]; +} + +-(NSTimeInterval) currentTime { + return [_player currentTime]; +} + +-(NSTimeInterval) duration { + return [_player duration]; +} + +#pragma mark unsupported +- (BOOL)prepareToPlay { + return YES; +} +-(BOOL)playAtTime:(NSTimeInterval)time { + return YES; +} +-(void) setMeteringEnabled:(BOOL) enabled { +} +-(BOOL) isMeteringEnabled { + return NO; +} +- (void)updateMeters{} +- (float)peakPowerForChannel:(NSUInteger)channelNumber{return 0.0f;} +- (float)averagePowerForChannel:(NSUInteger)channelNumber{return 0.0f;} +@end + +/** + A "do nothing" implementation - AVAudioSession is not really relevant to Mac OS X. + */ +@implementation AVAudioSession +@synthesize delegate, category, preferredHardwareSampleRate, preferredIOBufferDuration; +@synthesize inputIsAvailable, currentHardwareSampleRate, currentHardwareInputNumberOfChannels, currentHardwareOutputNumberOfChannels; + ++ (id)sharedInstance { + return nil; +} + +- (BOOL)setActive:(BOOL)beActive error:(NSError**)outError {return YES;} +- (BOOL)setActive:(BOOL)beActive withFlags:(NSInteger)flags error:(NSError**)outError {return YES;} +- (BOOL)setCategory:(NSString*)theCategory error:(NSError**)outError {return YES;} +- (BOOL)setPreferredHardwareSampleRate:(double)sampleRate error:(NSError**)outError {return YES;} +- (BOOL)setPreferredIOBufferDuration:(NSTimeInterval)duration error:(NSError**)outError {return YES;} + +@end +#endif diff --git "a/21451198\345\215\242\350\266\205/project5/MyPlane/libs/CocosDenshion/CDXPropertyModifierAction.h" "b/21451198\345\215\242\350\266\205/project5/MyPlane/libs/CocosDenshion/CDXPropertyModifierAction.h" new file mode 100644 index 00000000..efecf1e6 --- /dev/null +++ "b/21451198\345\215\242\350\266\205/project5/MyPlane/libs/CocosDenshion/CDXPropertyModifierAction.h" @@ -0,0 +1,45 @@ +/* + Copyright (c) 2010 Steve Oldmeadow + + Permission is hereby granted, free of charge, to any person obtaining a copy + of this software and associated documentation files (the "Software"), to deal + in the Software without restriction, including without limitation the rights + to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + copies of the Software, and to permit persons to whom the Software is + furnished to do so, subject to the following conditions: + + The above copyright notice and this permission notice shall be included in + all copies or substantial portions of the Software. + + THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + THE SOFTWARE. + + $Id$ + */ + +#import "cocos2d.h" +#import "SimpleAudioEngine.h" + +/** Base class for actions that modify audio properties + @since v 1.0 + */ +@interface CDXPropertyModifierAction : CCActionInterval { + CDPropertyModifier *modifier; + float lastSetValue; +} +/** creates the action */ ++(id) actionWithDuration:(ccTime)t modifier:(CDPropertyModifier*) aModifier; + +/** initializes the action */ +-(id) initWithDuration:(ccTime)t modifier:(CDPropertyModifier*) aModifier; + ++(void) fadeSoundEffects:(ccTime)t finalVolume:(float)endVol curveType:(tCDInterpolationType)curve shouldStop:(BOOL) stop; ++(void) fadeSoundEffect:(ccTime)t finalVolume:(float)endVol curveType:(tCDInterpolationType)curve shouldStop:(BOOL) stop effect:(CDSoundSource*) effect; ++(void) fadeBackgroundMusic:(ccTime)t finalVolume:(float)endVol curveType:(tCDInterpolationType) curve shouldStop:(BOOL) stop; + +@end diff --git "a/21451198\345\215\242\350\266\205/project5/MyPlane/libs/CocosDenshion/CDXPropertyModifierAction.m" "b/21451198\345\215\242\350\266\205/project5/MyPlane/libs/CocosDenshion/CDXPropertyModifierAction.m" new file mode 100644 index 00000000..66f71605 --- /dev/null +++ "b/21451198\345\215\242\350\266\205/project5/MyPlane/libs/CocosDenshion/CDXPropertyModifierAction.m" @@ -0,0 +1,123 @@ +/* + Copyright (c) 2010 Steve Oldmeadow + + Permission is hereby granted, free of charge, to any person obtaining a copy + of this software and associated documentation files (the "Software"), to deal + in the Software without restriction, including without limitation the rights + to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + copies of the Software, and to permit persons to whom the Software is + furnished to do so, subject to the following conditions: + + The above copyright notice and this permission notice shall be included in + all copies or substantial portions of the Software. + + THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + THE SOFTWARE. + + $Id$ + */ + +#import "CDXPropertyModifierAction.h" + +@implementation CDXPropertyModifierAction + ++(id) actionWithDuration:(ccTime)t modifier:(CDPropertyModifier*) aModifier; +{ + return [[[self alloc] initWithDuration:t modifier:aModifier] autorelease]; +} + +-(id) initWithDuration:(ccTime)t modifier:(CDPropertyModifier*) aModifier; +{ + if( (self=[super initWithDuration: t]) ) { + //Release the previous modifier + if (modifier) { + [modifier release]; + } + modifier = aModifier; + [modifier retain]; + //lastSetValue = [modifier _getTargetProperty];//Issue 1304 + } + return self; +} + + + +-(void) startWithTarget:(id)aTarget +{ + [super startWithTarget:aTarget]; + lastSetValue = [modifier _getTargetProperty]; +} + +-(void) dealloc { + CDLOG(@"Denshon::CDXPropertyModifierAction deallocated %@",self); + [modifier release]; + [super dealloc]; +} + +-(id) copyWithZone: (NSZone*) zone +{ + CDXPropertyModifierAction *copy = [[[self class] allocWithZone: zone] initWithDuration:[self duration] modifier: modifier]; + return copy; +} + +-(void) update: (ccTime) t +{ + //Check if modified property has been externally modified and if so bail out + if ([modifier _getTargetProperty] != lastSetValue) { + CCDirector *director = [CCDirector sharedDirector]; + [[director actionManager] removeAction:self]; + return; + } + [modifier modify:t]; + lastSetValue = [modifier _getTargetProperty]; +} + ++(void) fadeSoundEffects:(ccTime)t finalVolume:(float)endVol curveType:(tCDInterpolationType)curve shouldStop:(BOOL) stop { + CDSoundEngine* se = [CDAudioManager sharedManager].soundEngine; + //Create a fader object + CDSoundEngineFader* fader = [[CDSoundEngineFader alloc] init:se interpolationType:curve startVal:se.masterGain endVal:endVol]; + [fader setStopTargetWhenComplete:stop]; + //Create a property modifier action to wrap the fader + CDXPropertyModifierAction* action = [CDXPropertyModifierAction actionWithDuration:t modifier:fader]; + [fader release];//Action will retain + + CCDirector *director = [CCDirector sharedDirector]; + [[director actionManager] addAction:action target:se paused:NO]; +} + ++(void) fadeSoundEffect:(ccTime)t finalVolume:(float)endVol curveType:(tCDInterpolationType)curve shouldStop:(BOOL) stop effect:(CDSoundSource*) effect{ + //Create a fader object + CDSoundSourceFader* fader = [[CDSoundSourceFader alloc] init:effect interpolationType:curve startVal:effect.gain endVal:endVol]; + [fader setStopTargetWhenComplete:stop]; + //Create a property modifier action to wrap the fader + CDXPropertyModifierAction* action = [CDXPropertyModifierAction actionWithDuration:t modifier:fader]; + [fader release];//Action will retain + + CCDirector *director = [CCDirector sharedDirector]; + [[director actionManager] addAction:action target:effect paused:NO]; +} + + ++(void) fadeBackgroundMusic:(ccTime)t finalVolume:(float)endVol curveType:(tCDInterpolationType) curve shouldStop:(BOOL) stop +{ + //Background music is mapped to the left "channel" + CDLongAudioSource *player = [[CDAudioManager sharedManager] audioSourceForChannel:kASC_Left]; + CDLongAudioSourceFader* fader = [[CDLongAudioSourceFader alloc] init:player interpolationType:curve startVal:player.volume endVal:endVol]; + [fader setStopTargetWhenComplete:stop]; + //Create a property modifier action to wrap the fader + CDXPropertyModifierAction* action = [CDXPropertyModifierAction actionWithDuration:t modifier:fader]; + [fader release];//Action will retain + + CCDirector *director = [CCDirector sharedDirector]; + [[director actionManager] addAction:action target:player paused:NO]; +} + +@end + + + diff --git "a/21451198\345\215\242\350\266\205/project5/MyPlane/libs/CocosDenshion/CocosDenshion.h" "b/21451198\345\215\242\350\266\205/project5/MyPlane/libs/CocosDenshion/CocosDenshion.h" new file mode 100644 index 00000000..4566c7c5 --- /dev/null +++ "b/21451198\345\215\242\350\266\205/project5/MyPlane/libs/CocosDenshion/CocosDenshion.h" @@ -0,0 +1,440 @@ +/* + Copyright (c) 2010 Steve Oldmeadow + + Permission is hereby granted, free of charge, to any person obtaining a copy + of this software and associated documentation files (the "Software"), to deal + in the Software without restriction, including without limitation the rights + to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + copies of the Software, and to permit persons to whom the Software is + furnished to do so, subject to the following conditions: + + The above copyright notice and this permission notice shall be included in + all copies or substantial portions of the Software. + + THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + THE SOFTWARE. + + $Id$ + */ + + + +/** +@file +@b IMPORTANT +There are 3 different ways of using CocosDenshion. Depending on which you choose you +will need to include different files and frameworks. + +@par SimpleAudioEngine +This is recommended for basic audio requirements. If you just want to play some sound fx +and some background music and have no interest in learning the lower level workings then +this is the interface to use. + +Requirements: + - Firmware: OS 2.2 or greater + - Files: SimpleAudioEngine.*, CocosDenshion.* + - Frameworks: OpenAL, AudioToolbox, AVFoundation + +@par CDAudioManager +CDAudioManager is basically a thin wrapper around an AVAudioPlayer object used for playing +background music and a CDSoundEngine object used for playing sound effects. It manages the +audio session for you deals with audio session interruption. It is fairly low level and it +is expected you have some understanding of the underlying technologies. For example, for +many use cases regarding background music it is expected you will work directly with the +backgroundMusic AVAudioPlayer which is exposed as a property. + +Requirements: + - Firmware: OS 2.2 or greater + - Files: CDAudioManager.*, CocosDenshion.* + - Frameworks: OpenAL, AudioToolbox, AVFoundation + +@par CDSoundEngine +CDSoundEngine is a sound engine built upon OpenAL and derived from Apple's oalTouch +example. It can playback up to 32 sounds simultaneously with control over pitch, pan +and gain. It can be set up to handle audio session interruption automatically. You +may decide to use CDSoundEngine directly instead of CDAudioManager or SimpleAudioEngine +because you require OS 2.0 compatibility. + +Requirements: + - Firmware: OS 2.0 or greater + - Files: CocosDenshion.* + - Frameworks: OpenAL, AudioToolbox + +*/ + +#import +#import +#import +#import +#import "CDConfig.h" + + +#if !defined(CD_DEBUG) || CD_DEBUG == 0 +#define CDLOG(...) do {} while (0) +#define CDLOGINFO(...) do {} while (0) + +#elif CD_DEBUG == 1 +#define CDLOG(...) NSLog(__VA_ARGS__) +#define CDLOGINFO(...) do {} while (0) + +#elif CD_DEBUG > 1 +#define CDLOG(...) NSLog(__VA_ARGS__) +#define CDLOGINFO(...) NSLog(__VA_ARGS__) +#endif // CD_DEBUG + + +#import "CDOpenALSupport.h" + +//Tested source limit on 2.2.1 and 3.1.2 with up to 128 sources and appears to work. Older OS versions e.g 2.2 may support only 32 +#define CD_SOURCE_LIMIT 32 //Total number of sources we will ever want, may actually get less +#define CD_NO_SOURCE 0xFEEDFAC //Return value indicating playback failed i.e. no source +#define CD_IGNORE_AUDIO_SESSION 0xBEEFBEE //Used internally to indicate audio session will not be handled +#define CD_MUTE 0xFEEDBAB //Return value indicating sound engine is muted or non functioning +#define CD_NO_SOUND = -1; + +#define CD_SAMPLE_RATE_HIGH 44100 +#define CD_SAMPLE_RATE_MID 22050 +#define CD_SAMPLE_RATE_LOW 16000 +#define CD_SAMPLE_RATE_BASIC 8000 +#define CD_SAMPLE_RATE_DEFAULT 44100 + +extern NSString * const kCDN_BadAlContext; +extern NSString * const kCDN_AsynchLoadComplete; + +extern float const kCD_PitchDefault; +extern float const kCD_PitchLowerOneOctave; +extern float const kCD_PitchHigherOneOctave; +extern float const kCD_PanDefault; +extern float const kCD_PanFullLeft; +extern float const kCD_PanFullRight; +extern float const kCD_GainDefault; + +enum bufferState { + CD_BS_EMPTY = 0, + CD_BS_LOADED = 1, + CD_BS_FAILED = 2 +}; + +typedef struct _sourceGroup { + int startIndex; + int currentIndex; + int totalSources; + bool enabled; + bool nonInterruptible; + int *sourceStatuses;//pointer into array of source status information +} sourceGroup; + +typedef struct _bufferInfo { + ALuint bufferId; + int bufferState; + void* bufferData; + ALenum format; + ALsizei sizeInBytes; + ALsizei frequencyInHertz; +} bufferInfo; + +typedef struct _sourceInfo { + bool usable; + ALuint sourceId; + ALuint attachedBufferId; +} sourceInfo; + +#pragma mark CDAudioTransportProtocol + +@protocol CDAudioTransportProtocol +/** Play the audio */ +-(BOOL) play; +/** Pause the audio, retain resources */ +-(BOOL) pause; +/** Stop the audio, release resources */ +-(BOOL) stop; +/** Return playback to beginning */ +-(BOOL) rewind; +@end + +#pragma mark CDAudioInterruptProtocol + +@protocol CDAudioInterruptProtocol +/** Is audio mute */ +-(BOOL) mute; +/** If YES then audio is silenced but not stopped, calls to start new audio will proceed but silently */ +-(void) setMute:(BOOL) muteValue; +/** Is audio enabled */ +-(BOOL) enabled; +/** If NO then all audio is stopped and any calls to start new audio will be ignored */ +-(void) setEnabled:(BOOL) enabledValue; +@end + +#pragma mark CDUtilities +/** + Collection of utilities required by CocosDenshion + */ +@interface CDUtilities : NSObject +{ +} + +/** Fundamentally the same as the corresponding method is CCFileUtils but added to break binding to cocos2d */ ++(NSString*) fullPathFromRelativePath:(NSString*) relPath; + +@end + + +#pragma mark CDSoundEngine + +/** CDSoundEngine is built upon OpenAL and works with SDK 2.0. + CDSoundEngine is a sound engine built upon OpenAL and derived from Apple's oalTouch + example. It can playback up to 32 sounds simultaneously with control over pitch, pan + and gain. It can be set up to handle audio session interruption automatically. You + may decide to use CDSoundEngine directly instead of CDAudioManager or SimpleAudioEngine + because you require OS 2.0 compatibility. + + Requirements: + - Firmware: OS 2.0 or greater + - Files: CocosDenshion.* + - Frameworks: OpenAL, AudioToolbox + + @since v0.8 + */ +@class CDSoundSource; +@interface CDSoundEngine : NSObject { + + bufferInfo *_buffers; + sourceInfo *_sources; + sourceGroup *_sourceGroups; + ALCcontext *context; + NSUInteger _sourceGroupTotal; + UInt32 _audioSessionCategory; + BOOL _handleAudioSession; + ALfloat _preMuteGain; + NSObject *_mutexBufferLoad; + BOOL mute_; + BOOL enabled_; + + ALenum lastErrorCode_; + BOOL functioning_; + float asynchLoadProgress_; + BOOL getGainWorks_; + + //For managing dynamic allocation of sources and buffers + int sourceTotal_; + int bufferTotal; + +} + +@property (readwrite, nonatomic) ALfloat masterGain; +@property (readonly) ALenum lastErrorCode;//Last OpenAL error code that was generated +@property (readonly) BOOL functioning;//Is the sound engine functioning +@property (readwrite) float asynchLoadProgress; +@property (readonly) BOOL getGainWorks;//Does getting the gain for a source work +/** Total number of sources available */ +@property (readonly) int sourceTotal; +/** Total number of source groups that have been defined */ +@property (readonly) NSUInteger sourceGroupTotal; + +/** Sets the sample rate for the audio mixer. For best performance this should match the sample rate of your audio content */ ++(void) setMixerSampleRate:(Float32) sampleRate; + +/** Initializes the engine with a group definition and a total number of groups */ +-(id)init; + +/** Plays a sound in a channel group with a pitch, pan and gain. The sound could played looped or not */ +-(ALuint) playSound:(int) soundId sourceGroupId:(int)sourceGroupId pitch:(float) pitch pan:(float) pan gain:(float) gain loop:(BOOL) loop; + +/** Creates and returns a sound source object for the specified sound within the specified source group. + */ +-(CDSoundSource *) soundSourceForSound:(int) soundId sourceGroupId:(int) sourceGroupId; + +/** Stops playing a sound */ +- (void) stopSound:(ALuint) sourceId; +/** Stops playing a source group */ +- (void) stopSourceGroup:(int) sourceGroupId; +/** Stops all playing sounds */ +-(void) stopAllSounds; +-(void) defineSourceGroups:(NSArray*) sourceGroupDefinitions; +-(void) defineSourceGroups:(int[]) sourceGroupDefinitions total:(NSUInteger) total; +-(void) setSourceGroupNonInterruptible:(int) sourceGroupId isNonInterruptible:(BOOL) isNonInterruptible; +-(void) setSourceGroupEnabled:(int) sourceGroupId enabled:(BOOL) enabled; +-(BOOL) sourceGroupEnabled:(int) sourceGroupId; +-(BOOL) loadBufferFromData:(int) soundId soundData:(ALvoid*) soundData format:(ALenum) format size:(ALsizei) size freq:(ALsizei) freq; +-(BOOL) loadBuffer:(int) soundId filePath:(NSString*) filePath; +-(void) loadBuffersAsynchronously:(NSArray *) loadRequests; +-(BOOL) unloadBuffer:(int) soundId; +-(ALCcontext *) openALContext; + +/** Returns the duration of the buffer in seconds or a negative value if the buffer id is invalid */ +-(float) bufferDurationInSeconds:(int) soundId; +/** Returns the size of the buffer in bytes or a negative value if the buffer id is invalid */ +-(ALsizei) bufferSizeInBytes:(int) soundId; +/** Returns the sampling frequency of the buffer in hertz or a negative value if the buffer id is invalid */ +-(ALsizei) bufferFrequencyInHertz:(int) soundId; + +/** Used internally, never call unless you know what you are doing */ +-(void) _soundSourcePreRelease:(CDSoundSource *) soundSource; + +@end + +#pragma mark CDSoundSource +/** CDSoundSource is a wrapper around an OpenAL sound source. + It allows you to manipulate properties such as pitch, gain, pan and looping while the + sound is playing. CDSoundSource is based on the old CDSourceWrapper class but with much + added functionality. + + @since v1.0 + */ +@interface CDSoundSource : NSObject { + ALenum lastError; +@public + ALuint _sourceId; + ALuint _sourceIndex; + CDSoundEngine* _engine; + int _soundId; + float _preMuteGain; + BOOL enabled_; + BOOL mute_; +} +@property (readwrite, nonatomic) float pitch; +@property (readwrite, nonatomic) float gain; +@property (readwrite, nonatomic) float pan; +@property (readwrite, nonatomic) BOOL looping; +@property (readonly) BOOL isPlaying; +@property (readwrite, nonatomic) int soundId; +/** Returns the duration of the attached buffer in seconds or a negative value if the buffer is invalid */ +@property (readonly) float durationInSeconds; + +/** Stores the last error code that occurred. Check against AL_NO_ERROR */ +@property (readonly) ALenum lastError; +/** Do not init yourself, get an instance from the sourceForSound factory method on CDSoundEngine */ +-(id)init:(ALuint) theSourceId sourceIndex:(int) index soundEngine:(CDSoundEngine*) engine; + +@end + +#pragma mark CDAudioInterruptTargetGroup + +/** Container for objects that implement audio interrupt protocol i.e. they can be muted and enabled. + Setting mute and enabled for the group propagates to all children. + Designed to be used with your CDSoundSource objects to get them to comply with global enabled and mute settings + if that is what you want to do.*/ +@interface CDAudioInterruptTargetGroup : NSObject { + BOOL mute_; + BOOL enabled_; + NSMutableArray *children_; +} +-(void) addAudioInterruptTarget:(NSObject*) interruptibleTarget; +@end + +#pragma mark CDAsynchBufferLoader + +/** CDAsynchBufferLoader + TODO + */ +@interface CDAsynchBufferLoader : NSOperation { + NSArray *_loadRequests; + CDSoundEngine *_soundEngine; +} + +-(id) init:(NSArray *)loadRequests soundEngine:(CDSoundEngine *) theSoundEngine; + +@end + +#pragma mark CDBufferLoadRequest + +/** CDBufferLoadRequest */ +@interface CDBufferLoadRequest: NSObject +{ + NSString *filePath; + int soundId; + //id loader; +} + +@property (readonly) NSString *filePath; +@property (readonly) int soundId; + +- (id)init:(int) theSoundId filePath:(const NSString *) theFilePath; +@end + +/** Interpolation type */ +typedef enum { + kIT_Linear, //!Straight linear interpolation fade + kIT_SCurve, //!S curved interpolation + kIT_Exponential //!Exponential interpolation +} tCDInterpolationType; + +#pragma mark CDFloatInterpolator +@interface CDFloatInterpolator: NSObject +{ + float start; + float end; + float lastValue; + tCDInterpolationType interpolationType; +} +@property (readwrite, nonatomic) float start; +@property (readwrite, nonatomic) float end; +@property (readwrite, nonatomic) tCDInterpolationType interpolationType; + +/** Return a value between min and max based on t which represents fractional progress where 0 is the start + and 1 is the end */ +-(float) interpolate:(float) t; +-(id) init:(tCDInterpolationType) type startVal:(float) startVal endVal:(float) endVal; + +@end + +#pragma mark CDPropertyModifier + +/** Base class for classes that modify properties such as pitch, pan and gain */ +@interface CDPropertyModifier: NSObject +{ + CDFloatInterpolator *interpolator; + float startValue; + float endValue; + id target; + BOOL stopTargetWhenComplete; + +} +@property (readwrite, nonatomic) BOOL stopTargetWhenComplete; +@property (readwrite, nonatomic) float startValue; +@property (readwrite, nonatomic) float endValue; +@property (readwrite, nonatomic) tCDInterpolationType interpolationType; + +-(id) init:(id) theTarget interpolationType:(tCDInterpolationType) type startVal:(float) startVal endVal:(float) endVal; +/** Set to a fractional value between 0 and 1 where 0 equals the start and 1 equals the end*/ +-(void) modify:(float) t; + +-(void) _setTargetProperty:(float) newVal; +-(float) _getTargetProperty; +-(void) _stopTarget; +-(Class) _allowableType; + +@end + +#pragma mark CDSoundSourceFader + +/** Fader for CDSoundSource objects */ +@interface CDSoundSourceFader : CDPropertyModifier{} +@end + +#pragma mark CDSoundSourcePanner + +/** Panner for CDSoundSource objects */ +@interface CDSoundSourcePanner : CDPropertyModifier{} +@end + +#pragma mark CDSoundSourcePitchBender + +/** Pitch bender for CDSoundSource objects */ +@interface CDSoundSourcePitchBender : CDPropertyModifier{} +@end + +#pragma mark CDSoundEngineFader + +/** Fader for CDSoundEngine objects */ +@interface CDSoundEngineFader : CDPropertyModifier{} +@end + + + + diff --git "a/21451198\345\215\242\350\266\205/project5/MyPlane/libs/CocosDenshion/CocosDenshion.m" "b/21451198\345\215\242\350\266\205/project5/MyPlane/libs/CocosDenshion/CocosDenshion.m" new file mode 100644 index 00000000..747559c3 --- /dev/null +++ "b/21451198\345\215\242\350\266\205/project5/MyPlane/libs/CocosDenshion/CocosDenshion.m" @@ -0,0 +1,1610 @@ +/* + Copyright (c) 2010 Steve Oldmeadow + + Permission is hereby granted, free of charge, to any person obtaining a copy + of this software and associated documentation files (the "Software"), to deal + in the Software without restriction, including without limitation the rights + to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + copies of the Software, and to permit persons to whom the Software is + furnished to do so, subject to the following conditions: + + The above copyright notice and this permission notice shall be included in + all copies or substantial portions of the Software. + + THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + THE SOFTWARE. + + $Id$ + */ + +#import "CocosDenshion.h" + +// Use cocos2d Fileutils or Builtin fileutils ? +#ifndef CD_USE_OWN_FILEUTILS +#import "CCFileUtils.h" +#endif + +ALvoid alBufferDataStaticProc(const ALint bid, ALenum format, ALvoid* data, ALsizei size, ALsizei freq); +ALvoid alcMacOSXMixerOutputRateProc(const ALdouble value); + + +typedef ALvoid AL_APIENTRY (*alBufferDataStaticProcPtr) (const ALint bid, ALenum format, ALvoid* data, ALsizei size, ALsizei freq); +ALvoid alBufferDataStaticProc(const ALint bid, ALenum format, ALvoid* data, ALsizei size, ALsizei freq) +{ + static alBufferDataStaticProcPtr proc = NULL; + + if (proc == NULL) { + proc = (alBufferDataStaticProcPtr) alcGetProcAddress(NULL, (const ALCchar*) "alBufferDataStatic"); + } + + if (proc) + proc(bid, format, data, size, freq); + + return; +} + +typedef ALvoid AL_APIENTRY (*alcMacOSXMixerOutputRateProcPtr) (const ALdouble value); +ALvoid alcMacOSXMixerOutputRateProc(const ALdouble value) +{ + static alcMacOSXMixerOutputRateProcPtr proc = NULL; + + if (proc == NULL) { + proc = (alcMacOSXMixerOutputRateProcPtr) alcGetProcAddress(NULL, (const ALCchar*) "alcMacOSXMixerOutputRate"); + } + + if (proc) + proc(value); + + return; +} + +NSString * const kCDN_BadAlContext = @"kCDN_BadAlContext"; +NSString * const kCDN_AsynchLoadComplete = @"kCDN_AsynchLoadComplete"; +float const kCD_PitchDefault = 1.0f; +float const kCD_PitchLowerOneOctave = 0.5f; +float const kCD_PitchHigherOneOctave = 2.0f; +float const kCD_PanDefault = 0.0f; +float const kCD_PanFullLeft = -1.0f; +float const kCD_PanFullRight = 1.0f; +float const kCD_GainDefault = 1.0f; + +@interface CDSoundEngine (PrivateMethods) +-(BOOL) _initOpenAL; +-(void) _testGetGain; +-(void) _dumpSourceGroupsInfo; +-(void) _getSourceIndexForSourceGroup; +-(void) _freeSourceGroups; +-(BOOL) _setUpSourceGroups:(int[]) definitions total:(NSUInteger) total; +@end + +#pragma mark - +#pragma mark CDUtilities + +@implementation CDUtilities + ++(NSString*) fullPathFromRelativePath:(NSString*) relPath +{ +#ifndef CD_USE_OWN_FILEUTILS + return [[CCFileUtils sharedFileUtils] fullPathForFilenameIgnoringResolutions:relPath]; +#else + // do not convert an absolute path (starting with '/') + if(([relPath length] > 0) && ([relPath characterAtIndex:0] == '/')) + { + return relPath; + } + + NSMutableArray *imagePathComponents = [NSMutableArray arrayWithArray:[relPath pathComponents]]; + NSString *file = [imagePathComponents lastObject]; + + [imagePathComponents removeLastObject]; + NSString *imageDirectory = [NSString pathWithComponents:imagePathComponents]; + + NSString *fullpath = [[NSBundle mainBundle] pathForResource:file ofType:nil inDirectory:imageDirectory]; + if (fullpath == nil) + fullpath = relPath; + + return fullpath; +#endif +} + +@end + +#pragma mark - +#pragma mark CDSoundEngine + +@implementation CDSoundEngine + +static Float32 _mixerSampleRate; +static BOOL _mixerRateSet = NO; + +@synthesize lastErrorCode = lastErrorCode_; +@synthesize functioning = functioning_; +@synthesize asynchLoadProgress = asynchLoadProgress_; +@synthesize getGainWorks = getGainWorks_; +@synthesize sourceTotal = sourceTotal_; + ++ (void) setMixerSampleRate:(Float32) sampleRate { + _mixerRateSet = YES; + _mixerSampleRate = sampleRate; +} + +- (void) _testGetGain { + float testValue = 0.7f; + ALuint testSourceId = _sources[0].sourceId; + alSourcef(testSourceId, AL_GAIN, 0.0f);//Start from know value + alSourcef(testSourceId, AL_GAIN, testValue); + ALfloat gainVal; + alGetSourcef(testSourceId, AL_GAIN, &gainVal); + getGainWorks_ = (gainVal == testValue); +} + +//Generate sources one at a time until we fail +-(void) _generateSources { + + _sources = (sourceInfo*)malloc( sizeof(_sources[0]) * CD_SOURCE_LIMIT); + BOOL hasFailed = NO; + sourceTotal_ = 0; + alGetError();//Clear error + while (!hasFailed && sourceTotal_ < CD_SOURCE_LIMIT) { + alGenSources(1, &(_sources[sourceTotal_].sourceId)); + if (alGetError() == AL_NO_ERROR) { + //Now try attaching source to null buffer + alSourcei(_sources[sourceTotal_].sourceId, AL_BUFFER, 0); + if (alGetError() == AL_NO_ERROR) { + _sources[sourceTotal_].usable = true; + sourceTotal_++; + } else { + hasFailed = YES; + } + } else { + _sources[sourceTotal_].usable = false; + hasFailed = YES; + } + } + //Mark the rest of the sources as not usable + for (int i=sourceTotal_; i < CD_SOURCE_LIMIT; i++) { + _sources[i].usable = false; + } +} + +-(void) _generateBuffers:(int) startIndex endIndex:(int) endIndex { + if (_buffers) { + alGetError(); + for (int i=startIndex; i <= endIndex; i++) { + alGenBuffers(1, &_buffers[i].bufferId); + _buffers[i].bufferData = NULL; + if (alGetError() == AL_NO_ERROR) { + _buffers[i].bufferState = CD_BS_EMPTY; + } else { + _buffers[i].bufferState = CD_BS_FAILED; + CDLOG(@"Denshion::CDSoundEngine - buffer creation failed %i",i); + } + } + } +} + +/** + * Internal method called during init + */ +- (BOOL) _initOpenAL +{ + //ALenum error; + context = NULL; + ALCdevice *newDevice = NULL; + + //Set the mixer rate for the audio mixer + if (!_mixerRateSet) { + _mixerSampleRate = CD_SAMPLE_RATE_DEFAULT; + } + alcMacOSXMixerOutputRateProc(_mixerSampleRate); + CDLOGINFO(@"Denshion::CDSoundEngine - mixer output rate set to %0.2f",_mixerSampleRate); + + // Create a new OpenAL Device + // Pass NULL to specify the system's default output device + newDevice = alcOpenDevice(NULL); + if (newDevice != NULL) + { + // Create a new OpenAL Context + // The new context will render to the OpenAL Device just created + context = alcCreateContext(newDevice, 0); + if (context != NULL) + { + // Make the new context the Current OpenAL Context + alcMakeContextCurrent(context); + + // Create some OpenAL Buffer Objects + [self _generateBuffers:0 endIndex:bufferTotal-1]; + + // Create some OpenAL Source Objects + [self _generateSources]; + + } + } else { + return FALSE;//No device + } + alGetError();//Clear error + return TRUE; +} + +- (void) dealloc { + + ALCcontext *currentContext = NULL; + ALCdevice *device = NULL; + + [self stopAllSounds]; + + CDLOGINFO(@"Denshion::CDSoundEngine - Deallocing sound engine."); + [self _freeSourceGroups]; + + // Delete the Sources + CDLOGINFO(@"Denshion::CDSoundEngine - deleting sources."); + for (int i=0; i < sourceTotal_; i++) { + alSourcei(_sources[i].sourceId, AL_BUFFER, 0);//Detach from current buffer + alDeleteSources(1, &(_sources[i].sourceId)); + if((lastErrorCode_ = alGetError()) != AL_NO_ERROR) { + CDLOG(@"Denshion::CDSoundEngine - Error deleting source! %x\n", lastErrorCode_); + } + } + + // Delete the Buffers + CDLOGINFO(@"Denshion::CDSoundEngine - deleting buffers."); + for (int i=0; i < bufferTotal; i++) { + alDeleteBuffers(1, &_buffers[i].bufferId); +#ifdef CD_USE_STATIC_BUFFERS + if (_buffers[i].bufferData) { + free(_buffers[i].bufferData); + } +#endif + } + CDLOGINFO(@"Denshion::CDSoundEngine - free buffers."); + free(_buffers); + currentContext = alcGetCurrentContext(); + //Get device for active context + device = alcGetContextsDevice(currentContext); + //Release context + CDLOGINFO(@"Denshion::CDSoundEngine - destroy context."); + alcDestroyContext(currentContext); + //Close device + CDLOGINFO(@"Denshion::CDSoundEngine - close device."); + alcCloseDevice(device); + CDLOGINFO(@"Denshion::CDSoundEngine - free sources."); + free(_sources); + + //Release mutexes + [_mutexBufferLoad release]; + + [super dealloc]; +} + +-(NSUInteger) sourceGroupTotal { + return _sourceGroupTotal; +} + +-(void) _freeSourceGroups +{ + CDLOGINFO(@"Denshion::CDSoundEngine freeing source groups"); + if(_sourceGroups) { + for (int i=0; i < _sourceGroupTotal; i++) { + if (_sourceGroups[i].sourceStatuses) { + free(_sourceGroups[i].sourceStatuses); + CDLOGINFO(@"Denshion::CDSoundEngine freed source statuses %i",i); + } + } + free(_sourceGroups); + } +} + +-(BOOL) _redefineSourceGroups:(int[]) definitions total:(NSUInteger) total +{ + if (_sourceGroups) { + //Stop all sounds + [self stopAllSounds]; + //Need to free source groups + [self _freeSourceGroups]; + } + return [self _setUpSourceGroups:definitions total:total]; +} + +-(BOOL) _setUpSourceGroups:(int[]) definitions total:(NSUInteger) total +{ + _sourceGroups = (sourceGroup *)malloc( sizeof(_sourceGroups[0]) * total); + if(!_sourceGroups) { + CDLOG(@"Denshion::CDSoundEngine - source groups memory allocation failed"); + return NO; + } + + _sourceGroupTotal = total; + int sourceCount = 0; + for (int i=0; i < _sourceGroupTotal; i++) { + + _sourceGroups[i].startIndex = 0; + _sourceGroups[i].currentIndex = _sourceGroups[i].startIndex; + _sourceGroups[i].enabled = false; + _sourceGroups[i].nonInterruptible = false; + _sourceGroups[i].totalSources = definitions[i]; + _sourceGroups[i].sourceStatuses = malloc(sizeof(_sourceGroups[i].sourceStatuses[0]) * _sourceGroups[i].totalSources); + if (_sourceGroups[i].sourceStatuses) { + for (int j=0; j < _sourceGroups[i].totalSources; j++) { + //First bit is used to indicate whether source is locked, index is shifted back 1 bit + _sourceGroups[i].sourceStatuses[j] = (sourceCount + j) << 1; + } + } + sourceCount += definitions[i]; + } + return YES; +} + +-(void) defineSourceGroups:(int[]) sourceGroupDefinitions total:(NSUInteger) total { + [self _redefineSourceGroups:sourceGroupDefinitions total:total]; +} + +-(void) defineSourceGroups:(NSArray*) sourceGroupDefinitions { + CDLOGINFO(@"Denshion::CDSoundEngine - source groups defined by NSArray."); + NSUInteger totalDefs = [sourceGroupDefinitions count]; + int* defs = (int *)malloc( sizeof(int) * totalDefs); + int currentIndex = 0; + for (id currentDef in sourceGroupDefinitions) { + if ([currentDef isKindOfClass:[NSNumber class]]) { + defs[currentIndex] = (int)[(NSNumber*)currentDef integerValue]; + CDLOGINFO(@"Denshion::CDSoundEngine - found definition %i.",defs[currentIndex]); + } else { + CDLOG(@"Denshion::CDSoundEngine - warning, did not understand source definition."); + defs[currentIndex] = 0; + } + currentIndex++; + } + [self _redefineSourceGroups:defs total:totalDefs]; + free(defs); +} + +- (id)init +{ + if ((self = [super init])) { + + //Create mutexes + _mutexBufferLoad = [[NSObject alloc] init]; + + asynchLoadProgress_ = 0.0f; + + bufferTotal = CD_BUFFERS_START; + _buffers = (bufferInfo *)malloc( sizeof(_buffers[0]) * bufferTotal); + + // Initialize our OpenAL environment + if ([self _initOpenAL]) { + //Set up the default source group - a single group that contains all the sources + int sourceDefs[1]; + sourceDefs[0] = self.sourceTotal; + [self _setUpSourceGroups:sourceDefs total:1]; + + functioning_ = YES; + //Synchronize premute gain + _preMuteGain = self.masterGain; + mute_ = NO; + enabled_ = YES; + //Test whether get gain works for sources + [self _testGetGain]; + } else { + //Something went wrong with OpenAL + functioning_ = NO; + } + } + + return self; +} + +/** + * Delete the buffer identified by soundId + * @return true if buffer deleted successfully, otherwise false + */ +- (BOOL) unloadBuffer:(int) soundId +{ + //Ensure soundId is within array bounds otherwise memory corruption will occur + if (soundId < 0 || soundId >= bufferTotal) { + CDLOG(@"Denshion::CDSoundEngine - soundId is outside array bounds, maybe you need to increase CD_MAX_BUFFERS"); + return FALSE; + } + + //Before a buffer can be deleted any sources that are attached to it must be stopped + for (int i=0; i < sourceTotal_; i++) { + //Note: tried getting the AL_BUFFER attribute of the source instead but doesn't + //appear to work on a device - just returned zero. + if (_buffers[soundId].bufferId == _sources[i].attachedBufferId) { + + CDLOG(@"Denshion::CDSoundEngine - Found attached source %i %i %i",i,_buffers[soundId].bufferId,_sources[i].sourceId); +#ifdef CD_USE_STATIC_BUFFERS + //When using static buffers a crash may occur if a source is playing with a buffer that is about + //to be deleted even though we stop the source and successfully delete the buffer. Crash is confirmed + //on 2.2.1 and 3.1.2, however, it will only occur if a source is used rapidly after having its prior + //data deleted. To avoid any possibility of the crash we wait for the source to finish playing. + ALint state; + + alGetSourcei(_sources[i].sourceId, AL_SOURCE_STATE, &state); + + if (state == AL_PLAYING) { + CDLOG(@"Denshion::CDSoundEngine - waiting for source to complete playing before removing buffer data"); + alSourcei(_sources[i].sourceId, AL_LOOPING, FALSE);//Turn off looping otherwise loops will never end + while (state == AL_PLAYING) { + alGetSourcei(_sources[i].sourceId, AL_SOURCE_STATE, &state); + usleep(10000); + } + } +#endif + //Stop source and detach + alSourceStop(_sources[i].sourceId); + if((lastErrorCode_ = alGetError()) != AL_NO_ERROR) { + CDLOG(@"Denshion::CDSoundEngine - error stopping source: %x\n", lastErrorCode_); + } + + alSourcei(_sources[i].sourceId, AL_BUFFER, 0);//Attach to "NULL" buffer to detach + if((lastErrorCode_ = alGetError()) != AL_NO_ERROR) { + CDLOG(@"Denshion::CDSoundEngine - error detaching buffer: %x\n", lastErrorCode_); + } else { + //Record that source is now attached to nothing + _sources[i].attachedBufferId = 0; + } + } + } + + alDeleteBuffers(1, &_buffers[soundId].bufferId); + if((lastErrorCode_ = alGetError()) != AL_NO_ERROR) { + CDLOG(@"Denshion::CDSoundEngine - error deleting buffer: %x\n", lastErrorCode_); + _buffers[soundId].bufferState = CD_BS_FAILED; + return FALSE; + } else { +#ifdef CD_USE_STATIC_BUFFERS + //Free previous data, if alDeleteBuffer has returned without error then no + if (_buffers[soundId].bufferData) { + CDLOGINFO(@"Denshion::CDSoundEngine - freeing static data for soundId %i @ %i",soundId,_buffers[soundId].bufferData); + free(_buffers[soundId].bufferData);//Free the old data + _buffers[soundId].bufferData = NULL; + } +#endif + } + + alGenBuffers(1, &_buffers[soundId].bufferId); + if((lastErrorCode_ = alGetError()) != AL_NO_ERROR) { + CDLOG(@"Denshion::CDSoundEngine - error regenerating buffer: %x\n", lastErrorCode_); + _buffers[soundId].bufferState = CD_BS_FAILED; + return FALSE; + } else { + //We now have an empty buffer + _buffers[soundId].bufferState = CD_BS_EMPTY; + CDLOGINFO(@"Denshion::CDSoundEngine - buffer %i successfully unloaded\n",soundId); + return TRUE; + } +} + +/** + * Load buffers asynchronously + * Check asynchLoadProgress for progress. asynchLoadProgress represents fraction of completion. When it equals 1.0 loading + * is complete. NB: asynchLoadProgress is simply based on the number of load requests, it does not take into account + * file sizes. + * @param An array of CDBufferLoadRequest objects + */ +- (void) loadBuffersAsynchronously:(NSArray *) loadRequests { + @synchronized(self) { + asynchLoadProgress_ = 0.0f; + CDAsynchBufferLoader *loaderOp = [[[CDAsynchBufferLoader alloc] init:loadRequests soundEngine:self] autorelease]; + NSOperationQueue *opQ = [[[NSOperationQueue alloc] init] autorelease]; + [opQ addOperation:loaderOp]; + } +} + +-(BOOL) _resizeBuffers:(int) increment { + + void * tmpBufferInfos = realloc( _buffers, sizeof(_buffers[0]) * (bufferTotal + increment) ); + + if(!tmpBufferInfos) { + free(tmpBufferInfos); + return NO; + } else { + _buffers = tmpBufferInfos; + int oldBufferTotal = bufferTotal; + bufferTotal = bufferTotal + increment; + [self _generateBuffers:oldBufferTotal endIndex:bufferTotal-1]; + return YES; + } +} + +-(BOOL) loadBufferFromData:(int) soundId soundData:(ALvoid*) soundData format:(ALenum) format size:(ALsizei) size freq:(ALsizei) freq { + + @synchronized(_mutexBufferLoad) { + + if (!functioning_) { + //OpenAL initialisation has previously failed + CDLOG(@"Denshion::CDSoundEngine - Loading buffer failed because sound engine state != functioning"); + return FALSE; + } + + //Ensure soundId is within array bounds otherwise memory corruption will occur + if (soundId < 0) { + CDLOG(@"Denshion::CDSoundEngine - soundId is negative"); + return FALSE; + } + + if (soundId >= bufferTotal) { + //Need to resize the buffers + int requiredIncrement = CD_BUFFERS_INCREMENT; + while (bufferTotal + requiredIncrement <= soundId) { + requiredIncrement += CD_BUFFERS_INCREMENT; + } + CDLOGINFO(@"Denshion::CDSoundEngine - attempting to resize buffers by %i for sound %i",requiredIncrement,soundId); + if (![self _resizeBuffers:requiredIncrement]) { + CDLOG(@"Denshion::CDSoundEngine - buffer resize failed"); + return FALSE; + } + } + + if (soundData) + { + if (_buffers[soundId].bufferState != CD_BS_EMPTY) { + CDLOGINFO(@"Denshion::CDSoundEngine - non empty buffer, regenerating"); + if (![self unloadBuffer:soundId]) { + //Deletion of buffer failed, delete buffer routine has set buffer state and lastErrorCode + return NO; + } + } + +#ifdef CD_DEBUG + //Check that sample rate matches mixer rate and warn if they do not + if (freq != (int)_mixerSampleRate) { + CDLOGINFO(@"Denshion::CDSoundEngine - WARNING sample rate does not match mixer sample rate performance may not be optimal."); + } +#endif + +#ifdef CD_USE_STATIC_BUFFERS + alBufferDataStaticProc(_buffers[soundId].bufferId, format, soundData, size, freq); + _buffers[soundId].bufferData = data;//Save the pointer to the new data +#else + alBufferData(_buffers[soundId].bufferId, format, soundData, size, freq); +#endif + if((lastErrorCode_ = alGetError()) != AL_NO_ERROR) { + CDLOG(@"Denshion::CDSoundEngine - error attaching audio to buffer: %x", lastErrorCode_); + _buffers[soundId].bufferState = CD_BS_FAILED; + return FALSE; + } + } else { + CDLOG(@"Denshion::CDSoundEngine Buffer data is null!"); + _buffers[soundId].bufferState = CD_BS_FAILED; + return FALSE; + } + + _buffers[soundId].format = format; + _buffers[soundId].sizeInBytes = size; + _buffers[soundId].frequencyInHertz = freq; + _buffers[soundId].bufferState = CD_BS_LOADED; + CDLOGINFO(@"Denshion::CDSoundEngine Buffer %i loaded format:%i freq:%i size:%i",soundId,format,freq,size); + return TRUE; + }//end mutex +} + +/** + * Load sound data for later play back. + * @return TRUE if buffer loaded okay for play back otherwise false + */ +- (BOOL) loadBuffer:(int) soundId filePath:(NSString*) filePath +{ + + ALvoid* data; + ALenum format; + ALsizei size; + ALsizei freq; + + CDLOGINFO(@"Denshion::CDSoundEngine - Loading openAL buffer %i %@", soundId, filePath); + + CFURLRef fileURL = nil; + NSString *path = [CDUtilities fullPathFromRelativePath:filePath]; + if (path) { + fileURL = (CFURLRef)[[NSURL fileURLWithPath:path] retain]; + } + + if (fileURL) + { + data = CDGetOpenALAudioData(fileURL, &size, &format, &freq); + CFRelease(fileURL); + BOOL result = [self loadBufferFromData:soundId soundData:data format:format size:size freq:freq]; +#ifndef CD_USE_STATIC_BUFFERS + free(data);//Data can be freed here because alBufferData performs a memcpy +#endif + return result; + } else { + CDLOG(@"Denshion::CDSoundEngine Could not find file: %@\n", filePath); + //Don't change buffer state here as it will be the same as before method was called + return FALSE; + } +} + +-(BOOL) validateBufferId:(int) soundId { + if (soundId < 0 || soundId >= bufferTotal) { + CDLOGINFO(@"Denshion::CDSoundEngine - validateBufferId buffer outside range %i",soundId); + return NO; + } else if (_buffers[soundId].bufferState != CD_BS_LOADED) { + CDLOGINFO(@"Denshion::CDSoundEngine - validateBufferId invalide buffer state %i",soundId); + return NO; + } else { + return YES; + } +} + +-(float) bufferDurationInSeconds:(int) soundId { + if ([self validateBufferId:soundId]) { + float factor = 0.0f; + switch (_buffers[soundId].format) { + case AL_FORMAT_MONO8: + factor = 1.0f; + break; + case AL_FORMAT_MONO16: + factor = 0.5f; + break; + case AL_FORMAT_STEREO8: + factor = 0.5f; + break; + case AL_FORMAT_STEREO16: + factor = 0.25f; + break; + } + return (float)_buffers[soundId].sizeInBytes/(float)_buffers[soundId].frequencyInHertz * factor; + } else { + return -1.0f; + } +} + +-(ALsizei) bufferSizeInBytes:(int) soundId { + if ([self validateBufferId:soundId]) { + return _buffers[soundId].sizeInBytes; + } else { + return -1.0f; + } +} + +-(ALsizei) bufferFrequencyInHertz:(int) soundId { + if ([self validateBufferId:soundId]) { + return _buffers[soundId].frequencyInHertz; + } else { + return -1.0f; + } +} + +- (ALfloat) masterGain { + if (mute_) { + //When mute the real gain will always be 0 therefore return the preMuteGain value + return _preMuteGain; + } else { + ALfloat gain; + alGetListenerf(AL_GAIN, &gain); + return gain; + } +} + +/** + * Overall gain setting multiplier. e.g 0.5 is half the gain. + */ +- (void) setMasterGain:(ALfloat) newGainValue { + if (mute_) { + _preMuteGain = newGainValue; + } else { + alListenerf(AL_GAIN, newGainValue); + } +} + +#pragma mark CDSoundEngine AudioInterrupt protocol +- (BOOL) mute { + return mute_; +} + +/** + * Setting mute silences all sounds but playing sounds continue to advance playback + */ +- (void) setMute:(BOOL) newMuteValue { + + if (newMuteValue == mute_) { + return; + } + + mute_ = newMuteValue; + if (mute_) { + //Remember what the gain was + _preMuteGain = self.masterGain; + //Set gain to 0 - do not use the property as this will adjust preMuteGain when muted + alListenerf(AL_GAIN, 0.0f); + } else { + //Restore gain to what it was before being muted + self.masterGain = _preMuteGain; + } +} + +- (BOOL) enabled { + return enabled_; +} + +- (void) setEnabled:(BOOL)enabledValue +{ + if (enabled_ == enabledValue) { + return; + } + enabled_ = enabledValue; + if (enabled_ == NO) { + [self stopAllSounds]; + } +} + +-(void) _lockSource:(int) sourceIndex lock:(BOOL) lock { + BOOL found = NO; + for (int i=0; i < _sourceGroupTotal && !found; i++) { + if (_sourceGroups[i].sourceStatuses) { + for (int j=0; j < _sourceGroups[i].totalSources && !found; j++) { + //First bit is used to indicate whether source is locked, index is shifted back 1 bit + if((_sourceGroups[i].sourceStatuses[j] >> 1)==sourceIndex) { + if (lock) { + //Set first bit to lock this source + _sourceGroups[i].sourceStatuses[j] |= 1; + } else { + //Unset first bit to unlock this source + _sourceGroups[i].sourceStatuses[j] &= ~1; + } + found = YES; + } + } + } + } +} + +-(int) _getSourceIndexForSourceGroup:(int)sourceGroupId +{ + //Ensure source group id is valid to prevent memory corruption + if (sourceGroupId < 0 || sourceGroupId >= _sourceGroupTotal) { + CDLOG(@"Denshion::CDSoundEngine invalid source group id %i",sourceGroupId); + return CD_NO_SOURCE; + } + + int sourceIndex = -1;//Using -1 to indicate no source found + BOOL complete = NO; + ALint sourceState = 0; + sourceGroup *thisSourceGroup = &_sourceGroups[sourceGroupId]; + thisSourceGroup->currentIndex = thisSourceGroup->startIndex; + while (!complete) { + //Iterate over sources looking for one that is not locked, first bit indicates if source is locked + if ((thisSourceGroup->sourceStatuses[thisSourceGroup->currentIndex] & 1) == 0) { + //This source is not locked + sourceIndex = thisSourceGroup->sourceStatuses[thisSourceGroup->currentIndex] >> 1;//shift back to get the index + if (thisSourceGroup->nonInterruptible) { + //Check if this source is playing, if so it can't be interrupted + alGetSourcei(_sources[sourceIndex].sourceId, AL_SOURCE_STATE, &sourceState); + if (sourceState != AL_PLAYING) { + //complete = YES; + //Set start index so next search starts at the next position + thisSourceGroup->startIndex = thisSourceGroup->currentIndex + 1; + break; + } else { + sourceIndex = -1;//The source index was no good because the source was playing + } + } else { + //complete = YES; + //Set start index so next search starts at the next position + thisSourceGroup->startIndex = thisSourceGroup->currentIndex + 1; + break; + } + } + thisSourceGroup->currentIndex++; + if (thisSourceGroup->currentIndex >= thisSourceGroup->totalSources) { + //Reset to the beginning + thisSourceGroup->currentIndex = 0; + } + if (thisSourceGroup->currentIndex == thisSourceGroup->startIndex) { + //We have looped around and got back to the start + complete = YES; + } + } + + //Reset start index to beginning if beyond bounds + if (thisSourceGroup->startIndex >= thisSourceGroup->totalSources) { + thisSourceGroup->startIndex = 0; + } + + if (sourceIndex >= 0) { + return sourceIndex; + } else { + return CD_NO_SOURCE; + } + +} + +/** + * Play a sound. + * @param soundId the id of the sound to play (buffer id). + * @param SourceGroupId the source group that will be used to play the sound. + * @param pitch pitch multiplier. e.g 1.0 is unaltered, 0.5 is 1 octave lower. + * @param pan stereo position. -1 is fully left, 0 is centre and 1 is fully right. + * @param gain gain multiplier. e.g. 1.0 is unaltered, 0.5 is half the gain + * @param loop should the sound be looped or one shot. + * @return the id of the source being used to play the sound or CD_MUTE if the sound engine is muted or non functioning + * or CD_NO_SOURCE if a problem occurs setting up the source + * + */ +- (ALuint)playSound:(int) soundId sourceGroupId:(int)sourceGroupId pitch:(float) pitch pan:(float) pan gain:(float) gain loop:(BOOL) loop { + +#ifdef CD_DEBUG + //Sanity check parameters - only in DEBUG + NSAssert(soundId >= 0, @"soundId can not be negative"); + NSAssert(soundId < bufferTotal, @"soundId exceeds limit"); + NSAssert(sourceGroupId >= 0, @"sourceGroupId can not be negative"); + NSAssert(sourceGroupId < _sourceGroupTotal, @"sourceGroupId exceeds limit"); + NSAssert(pitch > 0, @"pitch must be greater than zero"); + NSAssert(pan >= -1 && pan <= 1, @"pan must be between -1 and 1"); + NSAssert(gain >= 0, @"gain can not be negative"); +#endif + //If mute or initialisation has failed or buffer is not loaded then do nothing + if (!enabled_ || !functioning_ || _buffers[soundId].bufferState != CD_BS_LOADED || _sourceGroups[sourceGroupId].enabled) { +#ifdef CD_DEBUG + if (!functioning_) { + CDLOGINFO(@"Denshion::CDSoundEngine - sound playback aborted because sound engine is not functioning"); + } else if (_buffers[soundId].bufferState != CD_BS_LOADED) { + CDLOGINFO(@"Denshion::CDSoundEngine - sound playback aborted because buffer %i is not loaded", soundId); + } +#endif + return CD_MUTE; + } + + int sourceIndex = [self _getSourceIndexForSourceGroup:sourceGroupId];//This method ensures sourceIndex is valid + + if (sourceIndex != CD_NO_SOURCE) { + ALint state; + ALuint source = _sources[sourceIndex].sourceId; + ALuint buffer = _buffers[soundId].bufferId; + alGetError();//Clear the error code + alGetSourcei(source, AL_SOURCE_STATE, &state); + if (state == AL_PLAYING) { + alSourceStop(source); + } + alSourcei(source, AL_BUFFER, buffer);//Attach to sound + alSourcef(source, AL_PITCH, pitch);//Set pitch + alSourcei(source, AL_LOOPING, loop);//Set looping + alSourcef(source, AL_GAIN, gain);//Set gain/volume + float sourcePosAL[] = {pan, 0.0f, 0.0f};//Set position - just using left and right panning + alSourcefv(source, AL_POSITION, sourcePosAL); + alGetError();//Clear the error code + alSourcePlay(source); + if((lastErrorCode_ = alGetError()) == AL_NO_ERROR) { + //Everything was okay + _sources[sourceIndex].attachedBufferId = buffer; + return source; + } else { + if (alcGetCurrentContext() == NULL) { + CDLOGINFO(@"Denshion::CDSoundEngine - posting bad OpenAL context message"); + [[NSNotificationCenter defaultCenter] postNotificationName:kCDN_BadAlContext object:nil]; + } + return CD_NO_SOURCE; + } + } else { + return CD_NO_SOURCE; + } +} + +-(BOOL) _soundSourceAttachToBuffer:(CDSoundSource*) soundSource soundId:(int) soundId { + //Attach the source to the buffer + ALint state; + ALuint source = soundSource->_sourceId; + ALuint buffer = _buffers[soundId].bufferId; + alGetSourcei(source, AL_SOURCE_STATE, &state); + if (state == AL_PLAYING) { + alSourceStop(source); + } + alGetError();//Clear the error code + alSourcei(source, AL_BUFFER, buffer);//Attach to sound data + if((lastErrorCode_ = alGetError()) == AL_NO_ERROR) { + _sources[soundSource->_sourceIndex].attachedBufferId = buffer; + //_sourceBufferAttachments[soundSource->_sourceIndex] = buffer;//Keep track of which + soundSource->_soundId = soundId; + return YES; + } else { + return NO; + } +} + +/** + * Get a sound source for the specified sound in the specified source group + */ +-(CDSoundSource *) soundSourceForSound:(int) soundId sourceGroupId:(int) sourceGroupId +{ + if (!functioning_) { + return nil; + } + //Check if a source is available + int sourceIndex = [self _getSourceIndexForSourceGroup:sourceGroupId]; + if (sourceIndex != CD_NO_SOURCE) { + CDSoundSource *result = [[CDSoundSource alloc] init:_sources[sourceIndex].sourceId sourceIndex:sourceIndex soundEngine:self]; + [self _lockSource:sourceIndex lock:YES]; + //Try to attach to the buffer + if ([self _soundSourceAttachToBuffer:result soundId:soundId]) { + //Set to a known state + result.pitch = 1.0f; + result.pan = 0.0f; + result.gain = 1.0f; + result.looping = NO; + return [result autorelease]; + } else { + //Release the sound source we just created, this will also unlock the source + [result release]; + return nil; + } + } else { + //No available source within that source group + return nil; + } +} + +-(void) _soundSourcePreRelease:(CDSoundSource *) soundSource { + CDLOGINFO(@"Denshion::CDSoundEngine _soundSourcePreRelease %i",soundSource->_sourceIndex); + //Unlock the sound source's source + [self _lockSource:soundSource->_sourceIndex lock:NO]; +} + +/** + * Stop all sounds playing within a source group + */ +- (void) stopSourceGroup:(int) sourceGroupId { + + if (!functioning_ || sourceGroupId >= _sourceGroupTotal || sourceGroupId < 0) { + return; + } + int sourceCount = _sourceGroups[sourceGroupId].totalSources; + for (int i=0; i < sourceCount; i++) { + int sourceIndex = _sourceGroups[sourceGroupId].sourceStatuses[i] >> 1; + alSourceStop(_sources[sourceIndex].sourceId); + } + alGetError();//Clear error in case we stopped any sounds that couldn't be stopped +} + +/** + * Stop a sound playing. + * @param sourceId an OpenAL source identifier i.e. the return value of playSound + */ +- (void)stopSound:(ALuint) sourceId { + if (!functioning_) { + return; + } + alSourceStop(sourceId); + alGetError();//Clear error in case we stopped any sounds that couldn't be stopped +} + +- (void) stopAllSounds { + for (int i=0; i < sourceTotal_; i++) { + alSourceStop(_sources[i].sourceId); + } + alGetError();//Clear error in case we stopped any sounds that couldn't be stopped +} + +/** + * Set a source group as non interruptible. Default is that source groups are interruptible. + * Non interruptible means that if a request to play a sound is made for a source group and there are + * no free sources available then the play request will be ignored and CD_NO_SOURCE will be returned. + */ +- (void) setSourceGroupNonInterruptible:(int) sourceGroupId isNonInterruptible:(BOOL) isNonInterruptible { + //Ensure source group id is valid to prevent memory corruption + if (sourceGroupId < 0 || sourceGroupId >= _sourceGroupTotal) { + CDLOG(@"Denshion::CDSoundEngine setSourceGroupNonInterruptible invalid source group id %i",sourceGroupId); + return; + } + + if (isNonInterruptible) { + _sourceGroups[sourceGroupId].nonInterruptible = true; + } else { + _sourceGroups[sourceGroupId].nonInterruptible = false; + } +} + +/** + * Set the mute property for a source group. If mute is turned on any sounds in that source group + * will be stopped and further sounds in that source group will play. However, turning mute off + * will not restart any sounds that were playing when mute was turned on. Also the mute setting + * for the sound engine must be taken into account. If the sound engine is mute no sounds will play + * no matter what the source group mute setting is. + */ +- (void) setSourceGroupEnabled:(int) sourceGroupId enabled:(BOOL) enabled { + //Ensure source group id is valid to prevent memory corruption + if (sourceGroupId < 0 || sourceGroupId >= _sourceGroupTotal) { + CDLOG(@"Denshion::CDSoundEngine setSourceGroupEnabled invalid source group id %i",sourceGroupId); + return; + } + + if (enabled) { + _sourceGroups[sourceGroupId].enabled = true; + [self stopSourceGroup:sourceGroupId]; + } else { + _sourceGroups[sourceGroupId].enabled = false; + } +} + +/** + * Return the mute property for the source group identified by sourceGroupId + */ +- (BOOL) sourceGroupEnabled:(int) sourceGroupId { + return _sourceGroups[sourceGroupId].enabled; +} + +-(ALCcontext *) openALContext { + return context; +} + +- (void) _dumpSourceGroupsInfo { +#ifdef CD_DEBUG + CDLOGINFO(@"-------------- source Group Info --------------"); + for (int i=0; i < _sourceGroupTotal; i++) { + CDLOGINFO(@"Group: %i start:%i total:%i",i,_sourceGroups[i].startIndex, _sourceGroups[i].totalSources); + CDLOGINFO(@"----- mute:%i nonInterruptible:%i",_sourceGroups[i].enabled, _sourceGroups[i].nonInterruptible); + CDLOGINFO(@"----- Source statuses ----"); + for (int j=0; j < _sourceGroups[i].totalSources; j++) { + CDLOGINFO(@"Source status:%i index=%i locked=%i",j,_sourceGroups[i].sourceStatuses[j] >> 1, _sourceGroups[i].sourceStatuses[j] & 1); + } + } +#endif +} + +@end + +/////////////////////////////////////////////////////////////////////////////////////// +@implementation CDSoundSource + +@synthesize lastError; + +//Macro for handling the al error code +#define CDSOUNDSOURCE_UPDATE_LAST_ERROR (lastError = alGetError()) +#define CDSOUNDSOURCE_ERROR_HANDLER ( CDSOUNDSOURCE_UPDATE_LAST_ERROR == AL_NO_ERROR) + +-(id)init:(ALuint) theSourceId sourceIndex:(int) index soundEngine:(CDSoundEngine*) engine { + if ((self = [super init])) { + _sourceId = theSourceId; + _engine = engine; + _sourceIndex = index; + enabled_ = YES; + mute_ = NO; + _preMuteGain = self.gain; + } + return self; +} + +-(void) dealloc +{ + CDLOGINFO(@"Denshion::CDSoundSource deallocated %i",self->_sourceIndex); + + //Notify sound engine we are about to release + [_engine _soundSourcePreRelease:self]; + [super dealloc]; +} + +- (void) setPitch:(float) newPitchValue { + alSourcef(_sourceId, AL_PITCH, newPitchValue); + CDSOUNDSOURCE_UPDATE_LAST_ERROR; +} + +- (void) setGain:(float) newGainValue { + if (!mute_) { + alSourcef(_sourceId, AL_GAIN, newGainValue); + } else { + _preMuteGain = newGainValue; + } + CDSOUNDSOURCE_UPDATE_LAST_ERROR; +} + +- (void) setPan:(float) newPanValue { + float sourcePosAL[] = {newPanValue, 0.0f, 0.0f};//Set position - just using left and right panning + alSourcefv(_sourceId, AL_POSITION, sourcePosAL); + CDSOUNDSOURCE_UPDATE_LAST_ERROR; + +} + +- (void) setLooping:(BOOL) newLoopingValue { + alSourcei(_sourceId, AL_LOOPING, newLoopingValue); + CDSOUNDSOURCE_UPDATE_LAST_ERROR; + +} + +- (BOOL) isPlaying { + ALint state; + alGetSourcei(_sourceId, AL_SOURCE_STATE, &state); + CDSOUNDSOURCE_UPDATE_LAST_ERROR; + return (state == AL_PLAYING); +} + +- (float) pitch { + ALfloat pitchVal; + alGetSourcef(_sourceId, AL_PITCH, &pitchVal); + CDSOUNDSOURCE_UPDATE_LAST_ERROR; + return pitchVal; +} + +- (float) pan { + ALfloat sourcePosAL[] = {0.0f,0.0f,0.0f}; + alGetSourcefv(_sourceId, AL_POSITION, sourcePosAL); + CDSOUNDSOURCE_UPDATE_LAST_ERROR; + return sourcePosAL[0]; +} + +- (float) gain { + if (!mute_) { + ALfloat val; + alGetSourcef(_sourceId, AL_GAIN, &val); + CDSOUNDSOURCE_UPDATE_LAST_ERROR; + return val; + } else { + return _preMuteGain; + } +} + +- (BOOL) looping { + ALfloat val; + alGetSourcef(_sourceId, AL_LOOPING, &val); + CDSOUNDSOURCE_UPDATE_LAST_ERROR; + return val; +} + +-(BOOL) stop { + alSourceStop(_sourceId); + return CDSOUNDSOURCE_ERROR_HANDLER; +} + +-(BOOL) play { + if (enabled_) { + alSourcePlay(_sourceId); + CDSOUNDSOURCE_UPDATE_LAST_ERROR; + if (lastError != AL_NO_ERROR) { + if (alcGetCurrentContext() == NULL) { + CDLOGINFO(@"Denshion::CDSoundSource - posting bad OpenAL context message"); + [[NSNotificationCenter defaultCenter] postNotificationName:kCDN_BadAlContext object:nil]; + } + return NO; + } else { + return YES; + } + } else { + return NO; + } +} + +-(BOOL) pause { + alSourcePause(_sourceId); + return CDSOUNDSOURCE_ERROR_HANDLER; +} + +-(BOOL) rewind { + alSourceRewind(_sourceId); + return CDSOUNDSOURCE_ERROR_HANDLER; +} + +-(void) setSoundId:(int) soundId { + [_engine _soundSourceAttachToBuffer:self soundId:soundId]; +} + +-(int) soundId { + return _soundId; +} + +-(float) durationInSeconds { + return [_engine bufferDurationInSeconds:_soundId]; +} + +#pragma mark CDSoundSource AudioInterrupt protocol +- (BOOL) mute { + return mute_; +} + +/** + * Setting mute silences all sounds but playing sounds continue to advance playback + */ +- (void) setMute:(BOOL) newMuteValue { + + if (newMuteValue == mute_) { + return; + } + + if (newMuteValue) { + //Remember what the gain was + _preMuteGain = self.gain; + self.gain = 0.0f; + mute_ = newMuteValue;//Make sure this is done after setting the gain property as the setter behaves differently depending on mute value + } else { + //Restore gain to what it was before being muted + mute_ = newMuteValue; + self.gain = _preMuteGain; + } +} + +- (BOOL) enabled { + return enabled_; +} + +- (void) setEnabled:(BOOL)enabledValue +{ + if (enabled_ == enabledValue) { + return; + } + enabled_ = enabledValue; + if (enabled_ == NO) { + [self stop]; + } +} + +@end + +//////////////////////////////////////////////////////////////////////////// +#pragma mark - +#pragma mark CDAudioInterruptTargetGroup + +@implementation CDAudioInterruptTargetGroup + +-(id) init { + if ((self = [super init])) { + children_ = [[NSMutableArray alloc] initWithCapacity:32]; + enabled_ = YES; + mute_ = NO; + } + return self; +} + +-(void) addAudioInterruptTarget:(NSObject*) interruptibleTarget { + //Synchronize child with group settings; + [interruptibleTarget setMute:mute_]; + [interruptibleTarget setEnabled:enabled_]; + [children_ addObject:interruptibleTarget]; +} + +-(void) removeAudioInterruptTarget:(NSObject*) interruptibleTarget { + [children_ removeObjectIdenticalTo:interruptibleTarget]; +} + +- (BOOL) mute { + return mute_; +} + +/** + * Setting mute silences all sounds but playing sounds continue to advance playback + */ +- (void) setMute:(BOOL) newMuteValue { + + if (newMuteValue == mute_) { + return; + } + + for (NSObject* target in children_) { + [target setMute:newMuteValue]; + } +} + +- (BOOL) enabled { + return enabled_; +} + +- (void) setEnabled:(BOOL)enabledValue +{ + if (enabledValue == enabled_) { + return; + } + + for (NSObject* target in children_) { + [target setEnabled:enabledValue]; + } +} + +@end + + + +//////////////////////////////////////////////////////////////////////////// + +#pragma mark - +#pragma mark CDAsynchBufferLoader + +@implementation CDAsynchBufferLoader + +-(id) init:(NSArray *)loadRequests soundEngine:(CDSoundEngine *) theSoundEngine { + if ((self = [super init])) { + _loadRequests = loadRequests; + [_loadRequests retain]; + _soundEngine = theSoundEngine; + [_soundEngine retain]; + } + return self; +} + +-(void) main { + CDLOGINFO(@"Denshion::CDAsynchBufferLoader - loading buffers"); + [super main]; + _soundEngine.asynchLoadProgress = 0.0f; + + if ([_loadRequests count] > 0) { + float increment = 1.0f / [_loadRequests count]; + //Iterate over load request and load + for (CDBufferLoadRequest *loadRequest in _loadRequests) { + [_soundEngine loadBuffer:loadRequest.soundId filePath:loadRequest.filePath]; + _soundEngine.asynchLoadProgress += increment; + } + } + + //Completed + _soundEngine.asynchLoadProgress = 1.0f; + [[NSNotificationCenter defaultCenter] postNotificationName:kCDN_AsynchLoadComplete object:nil]; + +} + +-(void) dealloc { + [_loadRequests release]; + [_soundEngine release]; + [super dealloc]; +} + +@end + + +/////////////////////////////////////////////////////////////////////////////////////// +#pragma mark - +#pragma mark CDBufferLoadRequest + +@implementation CDBufferLoadRequest + +@synthesize filePath, soundId; + +-(id) init:(int) theSoundId filePath:(const NSString *) theFilePath { + if ((self = [super init])) { + soundId = theSoundId; + filePath = [theFilePath copy]; + } + return self; +} + +-(void) dealloc { + [filePath release]; + [super dealloc]; +} + +@end + +/////////////////////////////////////////////////////////////////////////////////////// +#pragma mark - +#pragma mark CDFloatInterpolator + +@implementation CDFloatInterpolator +@synthesize start,end,interpolationType; + +-(float) interpolate:(float) t { + + if (t < 1.0f) { + switch (interpolationType) { + case kIT_Linear: + //Linear interpolation + return ((end - start) * t) + start; + + case kIT_SCurve: + //Cubic s curve t^2 * (3 - 2t) + return ((float)(t * t * (3.0 - (2.0 * t))) * (end - start)) + start; + + case kIT_Exponential: + //Formulas taken from EaseAction + if (end > start) { + //Fade in + float logDelta = (t==0) ? 0 : powf(2, 10 * (t/1 - 1)) - 1 * 0.001f; + return ((end - start) * logDelta) + start; + } else { + //Fade Out + float logDelta = (-powf(2, -10 * t/1) + 1); + return ((end - start) * logDelta) + start; + } + default: + return 0.0f; + } + } else { + return end; + } +} + +-(id) init:(tCDInterpolationType) type startVal:(float) startVal endVal:(float) endVal { + if ((self = [super init])) { + start = startVal; + end = endVal; + interpolationType = type; + } + return self; +} + +@end + +/////////////////////////////////////////////////////////////////////////////////////// +#pragma mark - +#pragma mark CDPropertyModifier + +@implementation CDPropertyModifier + +@synthesize stopTargetWhenComplete; + +-(id) init:(id) theTarget interpolationType:(tCDInterpolationType) type startVal:(float) startVal endVal:(float) endVal { + if ((self = [super init])) { + if (target) { + //Release the previous target if there is one + [target release]; + } + target = theTarget; +#if CD_DEBUG + //Check target is of the required type + if (![theTarget isMemberOfClass:[self _allowableType]] ) { + CDLOG(@"Denshion::CDPropertyModifier target is not of type %@",[self _allowableType]); + NSAssert([theTarget isKindOfClass:[CDSoundEngine class]], @"CDPropertyModifier target not of required type"); + } +#endif + [target retain]; + startValue = startVal; + endValue = endVal; + if (interpolator) { + //Release previous interpolator if there is one + [interpolator release]; + } + interpolator = [[CDFloatInterpolator alloc] init:type startVal:startVal endVal:endVal]; + stopTargetWhenComplete = NO; + } + return self; +} + +-(void) dealloc { + CDLOGINFO(@"Denshion::CDPropertyModifier deallocated %@",self); + [target release]; + [interpolator release]; + [super dealloc]; +} + +-(void) modify:(float) t { + if (t < 1.0) { + [self _setTargetProperty:[interpolator interpolate:t]]; + } else { + //At the end + [self _setTargetProperty:endValue]; + if (stopTargetWhenComplete) { + [self _stopTarget]; + } + } +} + +-(float) startValue { + return startValue; +} + +-(void) setStartValue:(float) startVal +{ + startValue = startVal; + interpolator.start = startVal; +} + +-(float) endValue { + return startValue; +} + +-(void) setEndValue:(float) endVal +{ + endValue = endVal; + interpolator.end = endVal; +} + +-(tCDInterpolationType) interpolationType { + return interpolator.interpolationType; +} + +-(void) setInterpolationType:(tCDInterpolationType) interpolationType { + interpolator.interpolationType = interpolationType; +} + +-(void) _setTargetProperty:(float) newVal { + +} + +-(float) _getTargetProperty { + return 0.0f; +} + +-(void) _stopTarget { + +} + +-(Class) _allowableType { + return [NSObject class]; +} +@end + +/////////////////////////////////////////////////////////////////////////////////////// +#pragma mark - +#pragma mark CDSoundSourceFader + +@implementation CDSoundSourceFader + +-(void) _setTargetProperty:(float) newVal { + ((CDSoundSource*)target).gain = newVal; +} + +-(float) _getTargetProperty { + return ((CDSoundSource*)target).gain; +} + +-(void) _stopTarget { + [((CDSoundSource*)target) stop]; +} + +-(Class) _allowableType { + return [CDSoundSource class]; +} + +@end + +/////////////////////////////////////////////////////////////////////////////////////// +#pragma mark - +#pragma mark CDSoundSourcePanner + +@implementation CDSoundSourcePanner + +-(void) _setTargetProperty:(float) newVal { + ((CDSoundSource*)target).pan = newVal; +} + +-(float) _getTargetProperty { + return ((CDSoundSource*)target).pan; +} + +-(void) _stopTarget { + [((CDSoundSource*)target) stop]; +} + +-(Class) _allowableType { + return [CDSoundSource class]; +} + +@end + +/////////////////////////////////////////////////////////////////////////////////////// +#pragma mark - +#pragma mark CDSoundSourcePitchBender + +@implementation CDSoundSourcePitchBender + +-(void) _setTargetProperty:(float) newVal { + ((CDSoundSource*)target).pitch = newVal; +} + +-(float) _getTargetProperty { + return ((CDSoundSource*)target).pitch; +} + +-(void) _stopTarget { + [((CDSoundSource*)target) stop]; +} + +-(Class) _allowableType { + return [CDSoundSource class]; +} + +@end + +/////////////////////////////////////////////////////////////////////////////////////// +#pragma mark - +#pragma mark CDSoundEngineFader + +@implementation CDSoundEngineFader + +-(void) _setTargetProperty:(float) newVal { + ((CDSoundEngine*)target).masterGain = newVal; +} + +-(float) _getTargetProperty { + return ((CDSoundEngine*)target).masterGain; +} + +-(void) _stopTarget { + [((CDSoundEngine*)target) stopAllSounds]; +} + +-(Class) _allowableType { + return [CDSoundEngine class]; +} + +@end + + diff --git "a/21451198\345\215\242\350\266\205/project5/MyPlane/libs/CocosDenshion/README.md" "b/21451198\345\215\242\350\266\205/project5/MyPlane/libs/CocosDenshion/README.md" new file mode 100644 index 00000000..829f7fb6 --- /dev/null +++ "b/21451198\345\215\242\350\266\205/project5/MyPlane/libs/CocosDenshion/README.md" @@ -0,0 +1,5 @@ +CocosDenshion +============= + +Official CocosDenshion repository: + http://github.com/steveoldmeadow/cocos2d-iphone diff --git "a/21451198\345\215\242\350\266\205/project5/MyPlane/libs/CocosDenshion/SimpleAudioEngine.h" "b/21451198\345\215\242\350\266\205/project5/MyPlane/libs/CocosDenshion/SimpleAudioEngine.h" new file mode 100644 index 00000000..470e7b5b --- /dev/null +++ "b/21451198\345\215\242\350\266\205/project5/MyPlane/libs/CocosDenshion/SimpleAudioEngine.h" @@ -0,0 +1,90 @@ +/* + Copyright (c) 2010 Steve Oldmeadow + + Permission is hereby granted, free of charge, to any person obtaining a copy + of this software and associated documentation files (the "Software"), to deal + in the Software without restriction, including without limitation the rights + to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + copies of the Software, and to permit persons to whom the Software is + furnished to do so, subject to the following conditions: + + The above copyright notice and this permission notice shall be included in + all copies or substantial portions of the Software. + + THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + THE SOFTWARE. + + $Id$ + */ + + +#import "CDAudioManager.h" + +/** + A wrapper to the CDAudioManager object. + This is recommended for basic audio requirements. If you just want to play some sound fx + and some background music and have no interest in learning the lower level workings then + this is the interface to use. + + Requirements: + - Firmware: OS 2.2 or greater + - Files: SimpleAudioEngine.*, CocosDenshion.* + - Frameworks: OpenAL, AudioToolbox, AVFoundation + @since v0.8 + */ +@interface SimpleAudioEngine : NSObject { + + BOOL mute_; + BOOL enabled_; +} + +/** Background music volume. Range is 0.0f to 1.0f. This will only have an effect if willPlayBackgroundMusic returns YES */ +@property (readwrite) float backgroundMusicVolume; +/** Effects volume. Range is 0.0f to 1.0f */ +@property (readwrite) float effectsVolume; +/** If NO it indicates background music will not be played either because no background music is loaded or the audio session does not permit it.*/ +@property (readonly) BOOL willPlayBackgroundMusic; + +/** returns the shared instance of the SimpleAudioEngine object */ ++ (SimpleAudioEngine*) sharedEngine; + +/** Preloads a music file so it will be ready to play as background music */ +-(void) preloadBackgroundMusic:(NSString*) filePath; + +/** plays background music in a loop*/ +-(void) playBackgroundMusic:(NSString*) filePath; +/** plays background music, if loop is true the music will repeat otherwise it will be played once */ +-(void) playBackgroundMusic:(NSString*) filePath loop:(BOOL) loop; +/** stops playing background music */ +-(void) stopBackgroundMusic; +/** pauses the background music */ +-(void) pauseBackgroundMusic; +/** resume background music that has been paused */ +-(void) resumeBackgroundMusic; +/** rewind the background music */ +-(void) rewindBackgroundMusic; +/** returns whether or not the background music is playing */ +-(BOOL) isBackgroundMusicPlaying; + +/** plays an audio effect with a file path*/ +-(ALuint) playEffect:(NSString*) filePath; +/** stop a sound that is playing, note you must pass in the soundId that is returned when you started playing the sound with playEffect */ +-(void) stopEffect:(ALuint) soundId; +/** plays an audio effect with a file path, pitch, pan and gain */ +-(ALuint) playEffect:(NSString*) filePath pitch:(Float32) pitch pan:(Float32) pan gain:(Float32) gain; +/** preloads an audio effect */ +-(void) preloadEffect:(NSString*) filePath; +/** unloads an audio effect from memory */ +-(void) unloadEffect:(NSString*) filePath; +/** Gets a CDSoundSource object set up to play the specified file. */ +-(CDSoundSource *) soundSourceForFile:(NSString*) filePath; + +/** Shuts down the shared audio engine instance so that it can be reinitialised */ ++(void) end; + +@end diff --git "a/21451198\345\215\242\350\266\205/project5/MyPlane/libs/CocosDenshion/SimpleAudioEngine.m" "b/21451198\345\215\242\350\266\205/project5/MyPlane/libs/CocosDenshion/SimpleAudioEngine.m" new file mode 100644 index 00000000..eb226a14 --- /dev/null +++ "b/21451198\345\215\242\350\266\205/project5/MyPlane/libs/CocosDenshion/SimpleAudioEngine.m" @@ -0,0 +1,220 @@ +/* + Copyright (c) 2010 Steve Oldmeadow + + Permission is hereby granted, free of charge, to any person obtaining a copy + of this software and associated documentation files (the "Software"), to deal + in the Software without restriction, including without limitation the rights + to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + copies of the Software, and to permit persons to whom the Software is + furnished to do so, subject to the following conditions: + + The above copyright notice and this permission notice shall be included in + all copies or substantial portions of the Software. + + THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + THE SOFTWARE. + + $Id$ + */ + +#import "SimpleAudioEngine.h" + +@implementation SimpleAudioEngine + +static SimpleAudioEngine *sharedEngine = nil; +static CDSoundEngine* soundEngine = nil; +static CDAudioManager *am = nil; +static CDBufferManager *bufferManager = nil; + +// Init ++ (SimpleAudioEngine *) sharedEngine +{ + @synchronized(self) { + if (!sharedEngine) + sharedEngine = [[SimpleAudioEngine alloc] init]; + } + return sharedEngine; +} + ++ (id) alloc +{ + @synchronized(self) { + NSAssert(sharedEngine == nil, @"Attempted to allocate a second instance of a singleton."); + return [super alloc]; + } + return nil; +} + +-(id) init +{ + if((self=[super init])) { + am = [CDAudioManager sharedManager]; + soundEngine = am.soundEngine; + bufferManager = [[CDBufferManager alloc] initWithEngine:soundEngine]; + mute_ = NO; + enabled_ = YES; + } + return self; +} + +// Memory +- (void) dealloc +{ + am = nil; + soundEngine = nil; + bufferManager = nil; + [super dealloc]; +} + ++(void) end +{ + am = nil; + [CDAudioManager end]; + [bufferManager release]; + [sharedEngine release]; + sharedEngine = nil; +} + +#pragma mark SimpleAudioEngine - background music + +-(void) preloadBackgroundMusic:(NSString*) filePath { + [am preloadBackgroundMusic:filePath]; +} + +-(void) playBackgroundMusic:(NSString*) filePath +{ + [am playBackgroundMusic:filePath loop:TRUE]; +} + +-(void) playBackgroundMusic:(NSString*) filePath loop:(BOOL) loop +{ + [am playBackgroundMusic:filePath loop:loop]; +} + +-(void) stopBackgroundMusic +{ + [am stopBackgroundMusic]; +} + +-(void) pauseBackgroundMusic { + [am pauseBackgroundMusic]; +} + +-(void) resumeBackgroundMusic { + [am resumeBackgroundMusic]; +} + +-(void) rewindBackgroundMusic { + [am rewindBackgroundMusic]; +} + +-(BOOL) isBackgroundMusicPlaying { + return [am isBackgroundMusicPlaying]; +} + +-(BOOL) willPlayBackgroundMusic { + return [am willPlayBackgroundMusic]; +} + +#pragma mark SimpleAudioEngine - sound effects + +-(ALuint) playEffect:(NSString*) filePath +{ + return [self playEffect:filePath pitch:1.0f pan:0.0f gain:1.0f]; +} + +-(ALuint) playEffect:(NSString*) filePath pitch:(Float32) pitch pan:(Float32) pan gain:(Float32) gain +{ + int soundId = [bufferManager bufferForFile:filePath create:YES]; + if (soundId != kCDNoBuffer) { + return [soundEngine playSound:soundId sourceGroupId:0 pitch:pitch pan:pan gain:gain loop:false]; + } else { + return CD_MUTE; + } +} + +-(void) stopEffect:(ALuint) soundId { + [soundEngine stopSound:soundId]; +} + +-(void) preloadEffect:(NSString*) filePath +{ + int soundId = [bufferManager bufferForFile:filePath create:YES]; + if (soundId == kCDNoBuffer) { + CDLOG(@"Denshion::SimpleAudioEngine sound failed to preload %@",filePath); + } +} + +-(void) unloadEffect:(NSString*) filePath +{ + CDLOGINFO(@"Denshion::SimpleAudioEngine unloadedEffect %@",filePath); + [bufferManager releaseBufferForFile:filePath]; +} + +#pragma mark Audio Interrupt Protocol +-(BOOL) mute +{ + return mute_; +} + +-(void) setMute:(BOOL) muteValue +{ + if (mute_ != muteValue) { + mute_ = muteValue; + am.mute = mute_; + } +} + +-(BOOL) enabled +{ + return enabled_; +} + +-(void) setEnabled:(BOOL) enabledValue +{ + if (enabled_ != enabledValue) { + enabled_ = enabledValue; + am.enabled = enabled_; + } +} + + +#pragma mark SimpleAudioEngine - BackgroundMusicVolume +-(float) backgroundMusicVolume +{ + return am.backgroundMusic.volume; +} + +-(void) setBackgroundMusicVolume:(float) volume +{ + am.backgroundMusic.volume = volume; +} + +#pragma mark SimpleAudioEngine - EffectsVolume +-(float) effectsVolume +{ + return am.soundEngine.masterGain; +} + +-(void) setEffectsVolume:(float) volume +{ + am.soundEngine.masterGain = volume; +} + +-(CDSoundSource *) soundSourceForFile:(NSString*) filePath { + int soundId = [bufferManager bufferForFile:filePath create:YES]; + if (soundId != kCDNoBuffer) { + CDSoundSource *result = [soundEngine soundSourceForSound:soundId sourceGroupId:0]; + CDLOGINFO(@"Denshion::SimpleAudioEngine sound source created for %@",filePath); + return result; + } else { + return nil; + } +} + +@end diff --git "a/21451198\345\215\242\350\266\205/project5/MyPlane/libs/LICENSE_CocosDenshion.txt" "b/21451198\345\215\242\350\266\205/project5/MyPlane/libs/LICENSE_CocosDenshion.txt" new file mode 100644 index 00000000..36c4251c --- /dev/null +++ "b/21451198\345\215\242\350\266\205/project5/MyPlane/libs/LICENSE_CocosDenshion.txt" @@ -0,0 +1,23 @@ + http://www.cocos2d-iphone.org/ + + CocosDenshion Sound Engine + + Copyright (c) 2010 Steve Oldmeadow + + Permission is hereby granted, free of charge, to any person obtaining a copy + of this software and associated documentation files (the "Software"), to deal + in the Software without restriction, including without limitation the rights + to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + copies of the Software, and to permit persons to whom the Software is + furnished to do so, subject to the following conditions: + + The above copyright notice and this permission notice shall be included in + all copies or substantial portions of the Software. + + THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + THE SOFTWARE. \ No newline at end of file diff --git "a/21451198\345\215\242\350\266\205/project5/MyPlane/libs/LICENSE_Kazmath.txt" "b/21451198\345\215\242\350\266\205/project5/MyPlane/libs/LICENSE_Kazmath.txt" new file mode 100644 index 00000000..028281d2 --- /dev/null +++ "b/21451198\345\215\242\350\266\205/project5/MyPlane/libs/LICENSE_Kazmath.txt" @@ -0,0 +1,35 @@ +https://github.com/Kazade/kazmath + +Kazmath is a 3D math library aimed at game programming. It is released under the modified BSD license. + +Authors + +Luke Benstead +Carsten Haubold + +License + +Copyright (c) 2008, Luke Benstead. +All rights reserved. + +Redistribution and use in source and binary forms, with or without modification, +are permitted provided that the following conditions are met: + + * Redistributions of source code must retain the above copyright notice, + this list of conditions and the following disclaimer. + * Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation + and/or other materials provided with the distribution. + +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND +ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED +WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR +ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES +(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; +LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON +ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS +SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + + diff --git "a/21451198\345\215\242\350\266\205/project5/MyPlane/libs/LICENSE_cocos2d.txt" "b/21451198\345\215\242\350\266\205/project5/MyPlane/libs/LICENSE_cocos2d.txt" new file mode 100644 index 00000000..bdc39e33 --- /dev/null +++ "b/21451198\345\215\242\350\266\205/project5/MyPlane/libs/LICENSE_cocos2d.txt" @@ -0,0 +1,24 @@ +cocos2d for iPhone: http://www.cocos2d-iphone.org + +Copyright (c) 2008-2011 - Ricardo Quesada and contributors +Copyright (c) 2011-2012 - Zynga Inc. and contributors +(see each file to see the different copyright owners) + + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in +all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN +THE SOFTWARE. diff --git "a/21451198\345\215\242\350\266\205/project5/MyPlane/libs/cocos2d/CCAction.h" "b/21451198\345\215\242\350\266\205/project5/MyPlane/libs/cocos2d/CCAction.h" new file mode 100644 index 00000000..b5c0ff4c --- /dev/null +++ "b/21451198\345\215\242\350\266\205/project5/MyPlane/libs/cocos2d/CCAction.h" @@ -0,0 +1,195 @@ +/* + * cocos2d for iPhone: http://www.cocos2d-iphone.org + * + * Copyright (c) 2008-2010 Ricardo Quesada + * Copyright (c) 2011 Zynga Inc. + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + * THE SOFTWARE. + * + */ + + +#include +#import + +#import "ccTypes.h" + +enum { + //! Default tag + kCCActionTagInvalid = -1, +}; + +/** Base class for CCAction objects. + */ +@interface CCAction : NSObject +{ + id _originalTarget; + id _target; + NSInteger _tag; +} + +/** The "target". The action will modify the target properties. + The target will be set with the 'startWithTarget' method. + When the 'stop' method is called, target will be set to nil. + The target is 'assigned', it is not 'retained'. + */ +@property (nonatomic,readonly,assign) id target; + +/** The original target, since target can be nil. + Is the target that were used to run the action. Unless you are doing something complex, like CCActionManager, you should NOT call this method. + @since v0.8.2 +*/ +@property (nonatomic,readonly,assign) id originalTarget; + + +/** The action tag. An identifier of the action */ +@property (nonatomic,readwrite,assign) NSInteger tag; + +/** Allocates and initializes the action */ ++(id) action; + +/** Initializes the action */ +-(id) init; + +-(id) copyWithZone: (NSZone*) zone; + +//! return YES if the action has finished +-(BOOL) isDone; +//! called before the action start. It will also set the target. +-(void) startWithTarget:(id)target; +//! called after the action has finished. It will set the 'target' to nil. +//! IMPORTANT: You should never call "[action stop]" manually. Instead, use: "[target stopAction:action];" +-(void) stop; +//! called every frame with its delta time. DON'T override unless you know what you are doing. +-(void) step: (ccTime) dt; +//! called once per frame. time a value between 0 and 1 +//! For example: +//! * 0 means that the action just started +//! * 0.5 means that the action is in the middle +//! * 1 means that the action is over +-(void) update: (ccTime) time; + +@end + +/** Base class actions that do have a finite time duration. + Possible actions: + - An action with a duration of 0 seconds + - An action with a duration of 35.5 seconds + Infinite time actions are valid + */ +@interface CCFiniteTimeAction : CCAction +{ + //! duration in seconds + ccTime _duration; +} +//! duration in seconds of the action +@property (nonatomic,readwrite) ccTime duration; + +/** returns a reversed action */ +- (CCFiniteTimeAction*) reverse; +@end + + +@class CCActionInterval; +/** Repeats an action for ever. + To repeat the an action for a limited number of times use the Repeat action. + @warning This action can't be Sequence-able because it is not an IntervalAction + */ +@interface CCRepeatForever : CCAction +{ + CCActionInterval *_innerAction; +} +/** Inner action */ +@property (nonatomic, readwrite, retain) CCActionInterval *innerAction; + +/** creates the action */ ++(id) actionWithAction: (CCActionInterval*) action; +/** initializes the action */ +-(id) initWithAction: (CCActionInterval*) action; +@end + +/** Changes the speed of an action, making it take longer (speed<1) + or less (speed>1) time. + Useful to simulate 'slow motion' or 'fast forward' effect. + @warning This action can't be Sequence-able because it is not an CCIntervalAction + */ +@interface CCSpeed : CCAction +{ + CCActionInterval *_innerAction; + CGFloat _speed; +} +/** alter the speed of the inner function in runtime */ +@property (nonatomic,readwrite) CGFloat speed; +/** Inner action of CCSpeed */ +@property (nonatomic, readwrite, retain) CCActionInterval *innerAction; + +/** creates the action */ ++(id) actionWithAction: (CCActionInterval*) action speed:(CGFloat)value; +/** initializes the action */ +-(id) initWithAction: (CCActionInterval*) action speed:(CGFloat)value; +@end + +@class CCNode; +/** CCFollow is an action that "follows" a node. + + Eg: + [layer runAction: [CCFollow actionWithTarget:hero]]; + + Instead of using CCCamera as a "follower", use this action instead. + @since v0.99.2 + */ +@interface CCFollow : CCAction +{ + /* node to follow */ + CCNode *_followedNode; + + /* whether camera should be limited to certain area */ + BOOL _boundarySet; + + /* if screen-size is bigger than the boundary - update not needed */ + BOOL _boundaryFullyCovered; + + /* fast access to the screen dimensions */ + CGPoint _halfScreenSize; + CGPoint _fullScreenSize; + + /* world boundaries */ + float _leftBoundary; + float _rightBoundary; + float _topBoundary; + float _bottomBoundary; +} + +/** alter behavior - turn on/off boundary */ +@property (nonatomic,readwrite) BOOL boundarySet; + +/** creates the action with no boundary set */ ++(id) actionWithTarget:(CCNode *)followedNode; + +/** creates the action with a set boundary */ ++(id) actionWithTarget:(CCNode *)followedNode worldBoundary:(CGRect)rect; + +/** initializes the action */ +-(id) initWithTarget:(CCNode *)followedNode; + +/** initializes the action with a set boundary */ +-(id) initWithTarget:(CCNode *)followedNode worldBoundary:(CGRect)rect; + +@end + diff --git "a/21451198\345\215\242\350\266\205/project5/MyPlane/libs/cocos2d/CCAction.m" "b/21451198\345\215\242\350\266\205/project5/MyPlane/libs/cocos2d/CCAction.m" new file mode 100644 index 00000000..77c673e7 --- /dev/null +++ "b/21451198\345\215\242\350\266\205/project5/MyPlane/libs/cocos2d/CCAction.m" @@ -0,0 +1,357 @@ +/* + * cocos2d for iPhone: http://www.cocos2d-iphone.org + * + * Copyright (c) 2008-2010 Ricardo Quesada + * Copyright (c) 2011 Zynga Inc. + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + * THE SOFTWARE. + * + */ + + +#import "CCDirector.h" +#import "ccMacros.h" +#import "CCAction.h" +#import "CCActionInterval.h" +#import "Support/CGPointExtension.h" + +// +// Action Base Class +// +#pragma mark - +#pragma mark Action +@implementation CCAction + +@synthesize tag = _tag, target = _target, originalTarget = _originalTarget; + ++(id) action +{ + return [[[self alloc] init] autorelease]; +} + +-(id) init +{ + if( (self=[super init]) ) { + _originalTarget = _target = nil; + _tag = kCCActionTagInvalid; + } + return self; +} + +-(void) dealloc +{ + CCLOGINFO(@"cocos2d: deallocing %@", self); + [super dealloc]; +} + +-(NSString*) description +{ + return [NSString stringWithFormat:@"<%@ = %p | Tag = %ld>", [self class], self, (long)_tag]; +} + +-(id) copyWithZone: (NSZone*) zone +{ + CCAction *copy = [[[self class] allocWithZone: zone] init]; + copy.tag = _tag; + return copy; +} + +-(void) startWithTarget:(id)aTarget +{ + _originalTarget = _target = aTarget; +} + +-(void) stop +{ + _target = nil; +} + +-(BOOL) isDone +{ + return YES; +} + +-(void) step: (ccTime) dt +{ + CCLOG(@"[Action step]. override me"); +} + +-(void) update: (ccTime) time +{ + CCLOG(@"[Action update]. override me"); +} +@end + +// +// FiniteTimeAction +// +#pragma mark - +#pragma mark FiniteTimeAction +@implementation CCFiniteTimeAction +@synthesize duration = _duration; + +- (CCFiniteTimeAction*) reverse +{ + CCLOG(@"cocos2d: FiniteTimeAction#reverse: Implement me"); + return nil; +} +@end + + +// +// RepeatForever +// +#pragma mark - +#pragma mark RepeatForever +@implementation CCRepeatForever +@synthesize innerAction=_innerAction; ++(id) actionWithAction: (CCActionInterval*) action +{ + return [[[self alloc] initWithAction: action] autorelease]; +} + +-(id) initWithAction: (CCActionInterval*) action +{ + if( (self=[super init]) ) + self.innerAction = action; + + return self; +} + +-(id) copyWithZone: (NSZone*) zone +{ + CCAction *copy = [[[self class] allocWithZone: zone] initWithAction:[[_innerAction copy] autorelease] ]; + return copy; +} + +-(void) dealloc +{ + [_innerAction release]; + [super dealloc]; +} + +-(void) startWithTarget:(id)aTarget +{ + [super startWithTarget:aTarget]; + [_innerAction startWithTarget:_target]; +} + +-(void) step:(ccTime) dt +{ + [_innerAction step: dt]; + if( [_innerAction isDone] ) { + ccTime diff = _innerAction.elapsed - _innerAction.duration; + [_innerAction startWithTarget:_target]; + + // to prevent jerk. issue #390, 1247 + [_innerAction step: 0.0f]; + [_innerAction step: diff]; + } +} + + +-(BOOL) isDone +{ + return NO; +} + +- (CCActionInterval *) reverse +{ + return [CCRepeatForever actionWithAction:[_innerAction reverse]]; +} +@end + +// +// Speed +// +#pragma mark - +#pragma mark Speed +@implementation CCSpeed +@synthesize speed=_speed; +@synthesize innerAction=_innerAction; + ++(id) actionWithAction: (CCActionInterval*) action speed:(CGFloat)value +{ + return [[[self alloc] initWithAction: action speed:value] autorelease]; +} + +-(id) initWithAction: (CCActionInterval*) action speed:(CGFloat)value +{ + if( (self=[super init]) ) { + self.innerAction = action; + _speed = value; + } + return self; +} + +-(id) copyWithZone: (NSZone*) zone +{ + CCAction *copy = [[[self class] allocWithZone: zone] initWithAction:[[_innerAction copy] autorelease] speed:_speed]; + return copy; +} + +-(void) dealloc +{ + [_innerAction release]; + [super dealloc]; +} + +-(void) startWithTarget:(id)aTarget +{ + [super startWithTarget:aTarget]; + [_innerAction startWithTarget:_target]; +} + +-(void) stop +{ + [_innerAction stop]; + [super stop]; +} + +-(void) step:(ccTime) dt +{ + [_innerAction step: dt * _speed]; +} + +-(BOOL) isDone +{ + return [_innerAction isDone]; +} + +- (CCActionInterval *) reverse +{ + return [CCSpeed actionWithAction:[_innerAction reverse] speed:_speed]; +} +@end + +// +// Follow +// +#pragma mark - +#pragma mark Follow +@implementation CCFollow + +@synthesize boundarySet = _boundarySet; + ++(id) actionWithTarget:(CCNode *) fNode +{ + return [[[self alloc] initWithTarget:fNode] autorelease]; +} + ++(id) actionWithTarget:(CCNode *) fNode worldBoundary:(CGRect)rect +{ + return [[[self alloc] initWithTarget:fNode worldBoundary:rect] autorelease]; +} + +-(id) initWithTarget:(CCNode *)fNode +{ + if( (self=[super init]) ) { + + _followedNode = [fNode retain]; + _boundarySet = FALSE; + _boundaryFullyCovered = FALSE; + + CGSize s = [[CCDirector sharedDirector] winSize]; + _fullScreenSize = CGPointMake(s.width, s.height); + _halfScreenSize = ccpMult(_fullScreenSize, .5f); + } + + return self; +} + +-(id) initWithTarget:(CCNode *)fNode worldBoundary:(CGRect)rect +{ + if( (self=[super init]) ) { + + _followedNode = [fNode retain]; + _boundarySet = TRUE; + _boundaryFullyCovered = FALSE; + + CGSize winSize = [[CCDirector sharedDirector] winSize]; + _fullScreenSize = CGPointMake(winSize.width, winSize.height); + _halfScreenSize = ccpMult(_fullScreenSize, .5f); + + _leftBoundary = -((rect.origin.x+rect.size.width) - _fullScreenSize.x); + _rightBoundary = -rect.origin.x ; + _topBoundary = -rect.origin.y; + _bottomBoundary = -((rect.origin.y+rect.size.height) - _fullScreenSize.y); + + if(_rightBoundary < _leftBoundary) + { + // screen width is larger than world's boundary width + //set both in the middle of the world + _rightBoundary = _leftBoundary = (_leftBoundary + _rightBoundary) / 2; + } + if(_topBoundary < _bottomBoundary) + { + // screen width is larger than world's boundary width + //set both in the middle of the world + _topBoundary = _bottomBoundary = (_topBoundary + _bottomBoundary) / 2; + } + + if( (_topBoundary == _bottomBoundary) && (_leftBoundary == _rightBoundary) ) + _boundaryFullyCovered = TRUE; + } + + return self; +} + +-(id) copyWithZone: (NSZone*) zone +{ + CCAction *copy = [[[self class] allocWithZone: zone] init]; + copy.tag = _tag; + return copy; +} + +-(void) step:(ccTime) dt +{ + if(_boundarySet) + { + // whole map fits inside a single screen, no need to modify the position - unless map boundaries are increased + if(_boundaryFullyCovered) + return; + + CGPoint tempPos = ccpSub( _halfScreenSize, _followedNode.position); + [_target setPosition:ccp(clampf(tempPos.x, _leftBoundary, _rightBoundary), clampf(tempPos.y, _bottomBoundary, _topBoundary))]; + } + else + [_target setPosition:ccpSub( _halfScreenSize, _followedNode.position )]; +} + + +-(BOOL) isDone +{ + return !_followedNode.isRunning; +} + +-(void) stop +{ + _target = nil; + [super stop]; +} + +-(void) dealloc +{ + [_followedNode release]; + [super dealloc]; +} + +@end + + diff --git "a/21451198\345\215\242\350\266\205/project5/MyPlane/libs/cocos2d/CCActionCamera.h" "b/21451198\345\215\242\350\266\205/project5/MyPlane/libs/cocos2d/CCActionCamera.h" new file mode 100644 index 00000000..e2e761c9 --- /dev/null +++ "b/21451198\345\215\242\350\266\205/project5/MyPlane/libs/cocos2d/CCActionCamera.h" @@ -0,0 +1,75 @@ +/* + * cocos2d for iPhone: http://www.cocos2d-iphone.org + * + * Copyright (c) 2008-2010 Ricardo Quesada + * Copyright (c) 2011 Zynga Inc. + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + * THE SOFTWARE. + * + */ + +#import "CCActionInterval.h" + +@class CCCamera; + +/** Base class for CCCamera actions + */ +@interface CCActionCamera : CCActionInterval +{ + float _centerXOrig; + float _centerYOrig; + float _centerZOrig; + + float _eyeXOrig; + float _eyeYOrig; + float _eyeZOrig; + + float _upXOrig; + float _upYOrig; + float _upZOrig; +} +// XXX Needed for BridgeSupport +-(void) startWithTarget:(id)aTarget; +@end + +/** CCOrbitCamera action + Orbits the camera around the center of the screen using spherical coordinates + */ +@interface CCOrbitCamera : CCActionCamera +{ + float _radius; + float _deltaRadius; + float _angleZ; + float _deltaAngleZ; + float _angleX; + float _deltaAngleX; + + float _radZ; + float _radDeltaZ; + float _radX; + float _radDeltaX; + +} +/** creates a CCOrbitCamera action with radius, delta-radius, z, deltaZ, x, deltaX */ ++(id) actionWithDuration:(float) t radius:(float)r deltaRadius:(float) dr angleZ:(float)z deltaAngleZ:(float)dz angleX:(float)x deltaAngleX:(float)dx; +/** initializes a CCOrbitCamera action with radius, delta-radius, z, deltaZ, x, deltaX */ +-(id) initWithDuration:(float) t radius:(float)r deltaRadius:(float) dr angleZ:(float)z deltaAngleZ:(float)dz angleX:(float)x deltaAngleX:(float)dx; +/** positions the camera according to spherical coordinates */ +-(void) sphericalRadius:(float*) r zenith:(float*) zenith azimuth:(float*) azimuth; +@end diff --git "a/21451198\345\215\242\350\266\205/project5/MyPlane/libs/cocos2d/CCActionCamera.m" "b/21451198\345\215\242\350\266\205/project5/MyPlane/libs/cocos2d/CCActionCamera.m" new file mode 100644 index 00000000..85f5ce4a --- /dev/null +++ "b/21451198\345\215\242\350\266\205/project5/MyPlane/libs/cocos2d/CCActionCamera.m" @@ -0,0 +1,147 @@ +/* + * cocos2d for iPhone: http://www.cocos2d-iphone.org + * + * Copyright (c) 2008-2010 Ricardo Quesada + * Copyright (c) 2011 Zynga Inc. + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + * THE SOFTWARE. + * + */ + + + +#import "CCActionCamera.h" +#import "CCNode.h" +#import "CCCamera.h" +#import "ccMacros.h" + +// +// CameraAction +// +@implementation CCActionCamera +-(void) startWithTarget:(id)aTarget +{ + [super startWithTarget:aTarget]; + CCCamera *camera = [_target camera]; + [camera centerX:&_centerXOrig centerY:&_centerYOrig centerZ:&_centerZOrig]; + [camera eyeX:&_eyeXOrig eyeY:&_eyeYOrig eyeZ:&_eyeZOrig]; + [camera upX:&_upXOrig upY:&_upYOrig upZ: &_upZOrig]; +} + +-(id) reverse +{ + return [CCReverseTime actionWithAction:self]; +} +@end + +@implementation CCOrbitCamera ++(id) actionWithDuration:(float)t radius:(float)r deltaRadius:(float) dr angleZ:(float)z deltaAngleZ:(float)dz angleX:(float)x deltaAngleX:(float)dx +{ + return [[[self alloc] initWithDuration:t radius:r deltaRadius:dr angleZ:z deltaAngleZ:dz angleX:x deltaAngleX:dx] autorelease]; +} + +-(id) copyWithZone: (NSZone*) zone +{ + return [[[self class] allocWithZone: zone] initWithDuration:_duration radius:_radius deltaRadius:_deltaRadius angleZ:_angleZ deltaAngleZ:_deltaAngleZ angleX:_angleX deltaAngleX:_deltaAngleX]; +} + + +-(id) initWithDuration:(float)t radius:(float)r deltaRadius:(float) dr angleZ:(float)z deltaAngleZ:(float)dz angleX:(float)x deltaAngleX:(float)dx +{ + if((self=[super initWithDuration:t]) ) { + + _radius = r; + _deltaRadius = dr; + _angleZ = z; + _deltaAngleZ = dz; + _angleX = x; + _deltaAngleX = dx; + + _radDeltaZ = (CGFloat)CC_DEGREES_TO_RADIANS(dz); + _radDeltaX = (CGFloat)CC_DEGREES_TO_RADIANS(dx); + } + + return self; +} + +-(void) startWithTarget:(id)aTarget +{ + [super startWithTarget:aTarget]; + float r, zenith, azimuth; + + [self sphericalRadius: &r zenith:&zenith azimuth:&azimuth]; + +#if 0 // isnan() is not supported on the simulator, and isnan() always returns false. + if( isnan(_radius) ) + _radius = r; + + if( isnan( _angleZ) ) + _angleZ = (CGFloat)CC_RADIANS_TO_DEGREES(zenith); + + if( isnan( _angleX ) ) + _angleX = (CGFloat)CC_RADIANS_TO_DEGREES(azimuth); +#endif + + _radZ = (CGFloat)CC_DEGREES_TO_RADIANS(_angleZ); + _radX = (CGFloat)CC_DEGREES_TO_RADIANS(_angleX); +} + +-(void) update: (ccTime) dt +{ + float r = (_radius + _deltaRadius * dt) *[CCCamera getZEye]; + float za = _radZ + _radDeltaZ * dt; + float xa = _radX + _radDeltaX * dt; + + float i = sinf(za) * cosf(xa) * r + _centerXOrig; + float j = sinf(za) * sinf(xa) * r + _centerYOrig; + float k = cosf(za) * r + _centerZOrig; + + [[_target camera] setEyeX:i eyeY:j eyeZ:k]; +} + +-(void) sphericalRadius:(float*) newRadius zenith:(float*) zenith azimuth:(float*) azimuth +{ + float ex, ey, ez, cx, cy, cz, x, y, z; + float r; // radius + float s; + + CCCamera *camera = [_target camera]; + [camera eyeX:&ex eyeY:&ey eyeZ:&ez]; + [camera centerX:&cx centerY:&cy centerZ:&cz]; + + x = ex-cx; + y = ey-cy; + z = ez-cz; + + r = sqrtf( x*x + y*y + z*z); + s = sqrtf( x*x + y*y); + if(s==0.0f) + s = FLT_EPSILON; + if(r==0.0f) + r = FLT_EPSILON; + + *zenith = acosf( z/r); + if( x < 0 ) + *azimuth = (float)M_PI - asinf(y/s); + else + *azimuth = asinf(y/s); + + *newRadius = r / [CCCamera getZEye]; +} +@end diff --git "a/21451198\345\215\242\350\266\205/project5/MyPlane/libs/cocos2d/CCActionCatmullRom.h" "b/21451198\345\215\242\350\266\205/project5/MyPlane/libs/cocos2d/CCActionCatmullRom.h" new file mode 100644 index 00000000..c6d6de97 --- /dev/null +++ "b/21451198\345\215\242\350\266\205/project5/MyPlane/libs/cocos2d/CCActionCatmullRom.h" @@ -0,0 +1,151 @@ +/* + * cocos2d for iPhone: http://www.cocos2d-iphone.org + * + * Copyright (c) 2008 Radu Gruian + * + * Copyright (c) 2011 Vit Valentin + * + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + * THE SOFTWARE. + * + * + * Orignal code by Radu Gruian: http://www.codeproject.com/Articles/30838/Overhauser-Catmull-Rom-Splines-for-Camera-Animatio.So + * + * Adapted to cocos2d-x by Vit Valentin + * + * Adapted from cocos2d-x to cocos2d-iphone by Ricardo Quesada + */ + + +#import "CCActionInterval.h" + +/** An Array that contain control points. + Used by CCCardinalSplineTo and (By) and CCCatmullRomTo (and By) actions. + */ +@interface CCPointArray : NSObject +{ + NSMutableArray *_controlPoints; +} + +/** Array that contains the control points */ +@property (nonatomic,readwrite,retain) NSMutableArray *controlPoints; + +/** creates and initializes a Points array with capacity */ + +(id) arrayWithCapacity:(NSUInteger)capacity; + +/** initializes a Catmull Rom config with a capacity hint */ +-(id) initWithCapacity:(NSUInteger)capacity; + +/** appends a control point */ +-(void) addControlPoint:(CGPoint)controlPoint; + +/** inserts a controlPoint at index */ +-(void) insertControlPoint:(CGPoint)controlPoint atIndex:(NSUInteger)index; + +/** replaces an existing controlPoint at index */ +-(void) replaceControlPoint:(CGPoint)controlPoint atIndex:(NSUInteger)index; + +/** get the value of a controlPoint at a given index */ +-(CGPoint) getControlPointAtIndex:(NSInteger)index; + +/** deletes a control point at a given index */ +-(void) removeControlPointAtIndex:(NSUInteger)index; + +/** returns the number of objects of the control point array */ +-(NSUInteger) count; + +/** returns a new copy of the array reversed. User is responsible for releasing this copy */ +-(CCPointArray*) reverse; + +/** reverse the current control point array inline, without generating a new one */ +-(void) reverseInline; +@end + +/** Cardinal Spline path. + http://en.wikipedia.org/wiki/Cubic_Hermite_spline#Cardinal_spline + */ +@interface CCCardinalSplineTo : CCActionInterval +{ + CCPointArray *_points; + CGFloat _deltaT; + CGFloat _tension; + CGPoint _previousPosition; + CGPoint _accumulatedDiff; +} + +/** Array of control points */ + @property (nonatomic,readwrite,retain) CCPointArray *points; + +/** creates an action with a Cardinal Spline array of points and tension */ ++(id) actionWithDuration:(ccTime)duration points:(CCPointArray*)points tension:(CGFloat)tension; + +/** initializes the action with a duration and an array of points */ +-(id) initWithDuration:(ccTime)duration points:(CCPointArray*)points tension:(CGFloat)tension; + +@end + +/** Cardinal Spline path. + http://en.wikipedia.org/wiki/Cubic_Hermite_spline#Cardinal_spline + */ +@interface CCCardinalSplineBy : CCCardinalSplineTo +{ + CGPoint _startPosition; +} +// XXX: To make BridgeSupport happy +-(void) startWithTarget:(id)target; +@end + +/** An action that moves the target with a CatmullRom curve to a destination point. + A Catmull Rom is a Cardinal Spline with a tension of 0.5. + http://en.wikipedia.org/wiki/Cubic_Hermite_spline#Catmull.E2.80.93Rom_spline + */ +@interface CCCatmullRomTo : CCCardinalSplineTo +{ +} +/** creates an action with a Cardinal Spline array of points and tension */ ++(id) actionWithDuration:(ccTime)dt points:(CCPointArray*)points; + +/** initializes the action with a duration and an array of points */ +-(id) initWithDuration:(ccTime)dt points:(CCPointArray*)points; +@end + +/** An action that moves the target with a CatmullRom curve by a certain distance. + A Catmull Rom is a Cardinal Spline with a tension of 0.5. + http://en.wikipedia.org/wiki/Cubic_Hermite_spline#Catmull.E2.80.93Rom_spline + */ +@interface CCCatmullRomBy : CCCardinalSplineBy +{ +} +/** creates an action with a Cardinal Spline array of points and tension */ ++(id) actionWithDuration:(ccTime)dt points:(CCPointArray*)points; + +/** initializes the action with a duration and an array of points */ +-(id) initWithDuration:(ccTime)dt points:(CCPointArray*)points; +@end + +#ifdef __cplusplus +extern "C" { +#endif + +/** Returns the Cardinal Spline position for a given set of control points, tension and time */ +CGPoint ccCardinalSplineAt( CGPoint p0, CGPoint p1, CGPoint p2, CGPoint p3, CGFloat tension, ccTime t ); + +#ifdef __cplusplus +} +#endif diff --git "a/21451198\345\215\242\350\266\205/project5/MyPlane/libs/cocos2d/CCActionCatmullRom.m" "b/21451198\345\215\242\350\266\205/project5/MyPlane/libs/cocos2d/CCActionCatmullRom.m" new file mode 100644 index 00000000..e67b7a87 --- /dev/null +++ "b/21451198\345\215\242\350\266\205/project5/MyPlane/libs/cocos2d/CCActionCatmullRom.m" @@ -0,0 +1,384 @@ +/* + * cocos2d for iPhone: http://www.cocos2d-iphone.org + * + * Copyright (c) 2008 Radu Gruian + * + * Copyright (c) 2011 Vit Valentin + * + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + * THE SOFTWARE. + * + * + * Orignal code by Radu Gruian: http://www.codeproject.com/Articles/30838/Overhauser-Catmull-Rom-Splines-for-Camera-Animatio.So + * + * Adapted to cocos2d-x by Vit Valentin + * + * Adapted from cocos2d-x to cocos2d-iphone by Ricardo Quesada + */ + + +#import "ccMacros.h" +#import "Support/CGPointExtension.h" +#import "CCActionCatmullRom.h" + +#pragma mark - CCPointArray + +@implementation CCPointArray + +@synthesize controlPoints = _controlPoints; + ++(id) arrayWithCapacity:(NSUInteger)capacity +{ + return [[[self alloc] initWithCapacity:capacity] autorelease]; +} + +-(id) init +{ + return [self initWithCapacity:50]; +} + +// designated initializer +-(id) initWithCapacity:(NSUInteger)capacity +{ + if( (self=[super init])) { + _controlPoints = [[NSMutableArray alloc] initWithCapacity:capacity]; + } + + return self; +} + +-(id) copyWithZone:(NSZone *)zone +{ + NSMutableArray *newArray = [_controlPoints mutableCopy]; + CCPointArray *points = [[[self class] allocWithZone:zone] initWithCapacity:10]; + points.controlPoints = newArray; + [newArray release]; + + return points; +} + +-(void) dealloc +{ + [_controlPoints release]; + + [super dealloc]; +} + +-(void) addControlPoint:(CGPoint)controlPoint +{ +#ifdef __CC_PLATFORM_MAC + NSValue *value = [NSValue valueWithPoint:NSPointFromCGPoint(controlPoint)]; +#elif defined(__CC_PLATFORM_IOS) + NSValue *value = [NSValue valueWithCGPoint:controlPoint]; +#endif + + [_controlPoints addObject:value]; +} + +-(void) insertControlPoint:(CGPoint)controlPoint atIndex:(NSUInteger)index +{ +#ifdef __CC_PLATFORM_MAC + NSValue *value = [NSValue valueWithPoint:NSPointFromCGPoint(controlPoint)]; +#elif defined(__CC_PLATFORM_IOS) + NSValue *value = [NSValue valueWithCGPoint:controlPoint]; +#endif + + [_controlPoints insertObject:value atIndex:index]; + +} + +-(CGPoint) getControlPointAtIndex:(NSInteger)index +{ + index = MIN([_controlPoints count]-1, MAX(index, 0)); + + NSValue *value = [_controlPoints objectAtIndex:index]; + +#ifdef __CC_PLATFORM_MAC + CGPoint point = NSPointToCGPoint([value pointValue]); +#elif defined(__CC_PLATFORM_IOS) + CGPoint point = [value CGPointValue]; +#endif + + return point; +} + +-(void) replaceControlPoint:(CGPoint)controlPoint atIndex:(NSUInteger)index +{ +#ifdef __CC_PLATFORM_MAC + NSValue *value = [NSValue valueWithPoint:NSPointFromCGPoint(controlPoint)]; +#elif defined(__CC_PLATFORM_IOS) + NSValue *value = [NSValue valueWithCGPoint:controlPoint]; +#endif + + [_controlPoints replaceObjectAtIndex:index withObject:value]; +} + +-(void) removeControlPointAtIndex:(NSUInteger)index +{ + [_controlPoints removeObjectAtIndex:index]; +} + +-(NSUInteger) count +{ + return [_controlPoints count]; +} + +-(CCPointArray*) reverse +{ + NSMutableArray *newArray = [[NSMutableArray alloc] initWithCapacity:[_controlPoints count]]; + NSEnumerator *enumerator = [_controlPoints reverseObjectEnumerator]; + for (id element in enumerator) + [newArray addObject:element]; + + CCPointArray *config = [[[self class] alloc] initWithCapacity:0]; + config.controlPoints = newArray; + + [newArray release]; + + return [config autorelease]; +} + +-(void) reverseInline +{ + NSUInteger l = [_controlPoints count]; + for( NSUInteger i=0; i 0, @"Invalid configuration. It must at least have one control point"); + + if( (self=[super initWithDuration:duration]) ) + { + self.points = points; + _tension = tension; + } + + return self; +} + +- (void)dealloc +{ + [_points release]; + [super dealloc]; +} + +-(void) startWithTarget:(id)target +{ + [super startWithTarget:target]; + +// _deltaT = (CGFloat) 1 / [_points count]; + + // Issue #1441 + _deltaT = (CGFloat) 1 / ([_points count]-1); + + _previousPosition = [(CCNode*)target position]; + _accumulatedDiff = CGPointZero; +} + +-(id) copyWithZone: (NSZone*) zone +{ + CCAction *copy = [[[self class] allocWithZone: zone] initWithDuration:[self duration] points:_points tension:_tension]; + return copy; +} + +-(void) update:(ccTime)dt +{ + NSUInteger p; + CGFloat lt; + + // eg. + // p..p..p..p..p..p..p + // 1..2..3..4..5..6..7 + // want p to be 1, 2, 3, 4, 5, 6 + if (dt == 1) { + p = [_points count] - 1; + lt = 1; + } else { + p = dt / _deltaT; + lt = (dt - _deltaT * (CGFloat)p) / _deltaT; + } + + // Interpolate + CGPoint pp0 = [_points getControlPointAtIndex:p-1]; + CGPoint pp1 = [_points getControlPointAtIndex:p+0]; + CGPoint pp2 = [_points getControlPointAtIndex:p+1]; + CGPoint pp3 = [_points getControlPointAtIndex:p+2]; + + CGPoint newPos = ccCardinalSplineAt( pp0, pp1, pp2, pp3, _tension, lt ); + +#if CC_ENABLE_STACKABLE_ACTIONS + CCNode *node = (CCNode*)_target; + CGPoint diff = ccpSub( node.position, _previousPosition); + if( diff.x !=0 || diff.y != 0 ) { + _accumulatedDiff = ccpAdd( _accumulatedDiff, diff); + newPos = ccpAdd( newPos, _accumulatedDiff); + } +#endif + + [self updatePosition:newPos]; +} + +-(void) updatePosition:(CGPoint)newPos +{ + [_target setPosition:newPos]; + _previousPosition = newPos; +} + +-(CCActionInterval*) reverse +{ + CCPointArray *reverse = [_points reverse]; + + return [[self class] actionWithDuration:_duration points:reverse tension:_tension]; +} +@end + +#pragma mark - CCCardinalSplineBy + +@implementation CCCardinalSplineBy + +-(void) startWithTarget:(id)target +{ + [super startWithTarget:target]; + + _startPosition = [(CCNode*)target position]; +} + +-(void) updatePosition:(CGPoint)newPos +{ + CGPoint p = ccpAdd(newPos, _startPosition); + [_target setPosition:p]; + _previousPosition = p; +} + +-(CCActionInterval*) reverse +{ + CCPointArray *copyConfig = [_points copy]; + + // + // convert "absolutes" to "diffs" + // + CGPoint p = [copyConfig getControlPointAtIndex:0]; + for( NSUInteger i=1; i < [copyConfig count];i++ ) { + + CGPoint current = [copyConfig getControlPointAtIndex:i]; + CGPoint diff = ccpSub(current,p); + [copyConfig replaceControlPoint:diff atIndex:i]; + + p = current; + } + + + // convert to "diffs" to "reverse absolute" + + CCPointArray *reverse = [copyConfig reverse]; + [copyConfig release]; + + // 1st element (which should be 0,0) should be here too + p = [reverse getControlPointAtIndex: [reverse count]-1]; + [reverse removeControlPointAtIndex:[reverse count]-1]; + + p = ccpNeg(p); + [reverse insertControlPoint:p atIndex:0]; + + for( NSUInteger i=1; i < [reverse count];i++ ) { + + CGPoint current = [reverse getControlPointAtIndex:i]; + current = ccpNeg(current); + CGPoint abs = ccpAdd( current, p); + [reverse replaceControlPoint:abs atIndex:i]; + + p = abs; + } + + return [[self class] actionWithDuration:_duration points:reverse tension:_tension]; +} +@end + +@implementation CCCatmullRomTo ++(id) actionWithDuration:(ccTime)dt points:(CCPointArray *)points +{ + return [[[self alloc] initWithDuration:dt points:points] autorelease]; +} + +-(id) initWithDuration:(ccTime)dt points:(CCPointArray *)points +{ + if( (self=[super initWithDuration:dt points:points tension:0.5f]) ) { + + } + + return self; +} +@end + +@implementation CCCatmullRomBy ++(id) actionWithDuration:(ccTime)dt points:(CCPointArray *)points +{ + return [[[self alloc] initWithDuration:dt points:points] autorelease]; +} + +-(id) initWithDuration:(ccTime)dt points:(CCPointArray *)points +{ + if( (self=[super initWithDuration:dt points:points tension:0.5f]) ) { + + } + + return self; +} +@end diff --git "a/21451198\345\215\242\350\266\205/project5/MyPlane/libs/cocos2d/CCActionEase.h" "b/21451198\345\215\242\350\266\205/project5/MyPlane/libs/cocos2d/CCActionEase.h" new file mode 100644 index 00000000..7719b3ec --- /dev/null +++ "b/21451198\345\215\242\350\266\205/project5/MyPlane/libs/cocos2d/CCActionEase.h" @@ -0,0 +1,292 @@ +/* + * cocos2d for iPhone: http://www.cocos2d-iphone.org + * + * Copyright (c) 2008-2009 Jason Booth + * Copyright (c) 2013 Nader Eloshaiker + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + * THE SOFTWARE. + * + */ + + +#import "CCActionInterval.h" + +/** Base class for Easing actions + */ +@interface CCActionEase : CCActionInterval +{ + CCActionInterval *_inner; +} +/** The inner action */ +@property (nonatomic, readonly) CCActionInterval *inner; + +/** creates the action */ ++(id) actionWithAction: (CCActionInterval*) action; +/** initializes the action */ +-(id) initWithAction: (CCActionInterval*) action; +@end + +/** Base class for Easing actions with rate parameters + */ +@interface CCEaseRateAction : CCActionEase +{ + float _rate; +} +/** rate value for the actions */ +@property (nonatomic,readwrite,assign) float rate; +/** Creates the action with the inner action and the rate parameter */ ++(id) actionWithAction: (CCActionInterval*) action rate:(float)rate; +/** Initializes the action with the inner action and the rate parameter */ +-(id) initWithAction: (CCActionInterval*) action rate:(float)rate; +@end + +/** CCEaseIn action with a rate + */ +@interface CCEaseIn : CCEaseRateAction +{} +// Needed for BridgeSupport +-(void) update: (ccTime) t; +@end + +/** CCEaseOut action with a rate + */ +@interface CCEaseOut : CCEaseRateAction +{} +// Needed for BridgeSupport +-(void) update: (ccTime) t; +@end + +/** CCEaseInOut action with a rate + */ +@interface CCEaseInOut : CCEaseRateAction +{} +// Needed for BridgeSupport +-(void) update: (ccTime) t; +@end + +/** CCEase Exponential In + */ +@interface CCEaseExponentialIn : CCActionEase +{} +// Needed for BridgeSupport +-(void) update: (ccTime) t; +@end + +/** Ease Exponential Out + */ +@interface CCEaseExponentialOut : CCActionEase +{} +// Needed for BridgeSupport +-(void) update: (ccTime) t; +@end + +/** Ease Exponential InOut + */ +@interface CCEaseExponentialInOut : CCActionEase +{} +// Needed for BridgeSupport +-(void) update: (ccTime) t; +@end + +/** CCEase Polynomial abstract class + @since v2.1 + */ +@interface CCEasePolynomial : CCActionEase { +@protected + NSUInteger _polynomialOrder; + CGFloat _intersetValue; //Used for InOut mid point time calculation + BOOL _hasInflection; //odd numbered polynomial orders will display a point of inflection where the curve will invert +} +/** Used to determine the steepness of the timing curve. + As the value increases, so does the steepness/rate of the curve. + Default value is 6, gives a similar curve to EaseExponential. + Values less than 6, produces a softer ease action. + Values greater than 6, produces a more pronounced action. + @warning Value must be greater than 1 + */ +@property (nonatomic, readwrite, assign) NSUInteger polynomialOrder; +@end + +/** CCEase Polynomial In + @since v2.1 + */ +@interface CCEasePolynomialIn : CCEasePolynomial +{} +// Needed for BridgeSupport +-(void) update: (ccTime) t; +@end + +/** Ease Polynomial Out + @since v2.1 + */ +@interface CCEasePolynomialOut : CCEasePolynomial +{} +// Needed for BridgeSupport +-(void) update: (ccTime) t; +@end + +/** Ease Polynomial InOut + @since v2.1 + */ +@interface CCEasePolynomialInOut : CCEasePolynomial +{} +// Needed for BridgeSupport +-(void) update: (ccTime) t; +@end + +/** Ease Sine In + */ +@interface CCEaseSineIn : CCActionEase +{} +// Needed for BridgeSupport +-(void) update: (ccTime) t; +@end + +/** Ease Sine Out + */ +@interface CCEaseSineOut : CCActionEase +{} +// Needed for BridgeSupport +-(void) update: (ccTime) t; +@end + +/** Ease Sine InOut + */ +@interface CCEaseSineInOut : CCActionEase +{} +// Needed for BridgeSupport +-(void) update: (ccTime) t; +@end + +/** Ease Elastic abstract class + @since v0.8.2 + */ +@interface CCEaseElastic : CCActionEase +{ + float _period; +} + +/** period of the wave in radians. default is 0.3 */ +@property (nonatomic,readwrite) float period; + +/** Creates the action with the inner action and the period in radians (default is 0.3) */ ++(id) actionWithAction: (CCActionInterval*) action period:(float)period; +/** Initializes the action with the inner action and the period in radians (default is 0.3) */ +-(id) initWithAction: (CCActionInterval*) action period:(float)period; +@end + +/** Ease Elastic In action. + @warning This action doesn't use a bijective function. Actions like Sequence might have an unexpected result when used with this action. + @since v0.8.2 + */ +@interface CCEaseElasticIn : CCEaseElastic +{} +// Needed for BridgeSupport +-(void) update: (ccTime) t; +@end + +/** Ease Elastic Out action. + @warning This action doesn't use a bijective function. Actions like Sequence might have an unexpected result when used with this action. + @since v0.8.2 + */ +@interface CCEaseElasticOut : CCEaseElastic +{} +// Needed for BridgeSupport +-(void) update: (ccTime) t; +@end + +/** Ease Elastic InOut action. + @warning This action doesn't use a bijective function. Actions like Sequence might have an unexpected result when used with this action. + @since v0.8.2 + */ +@interface CCEaseElasticInOut : CCEaseElastic +{} +// Needed for BridgeSupport +-(void) update: (ccTime) t; +@end + +/** CCEaseBounce abstract class. + @since v0.8.2 +*/ +@interface CCEaseBounce : CCActionEase +{} +// Needed for BridgeSupport +-(ccTime) bounceTime:(ccTime) t; +@end + +/** CCEaseBounceIn action. + @warning This action doesn't use a bijective function. Actions like Sequence might have an unexpected result when used with this action. + @since v0.8.2 +*/ +@interface CCEaseBounceIn : CCEaseBounce +{} +// Needed for BridgeSupport +-(void) update: (ccTime) t; +@end + +/** EaseBounceOut action. + @warning This action doesn't use a bijective function. Actions like Sequence might have an unexpected result when used with this action. + @since v0.8.2 + */ +@interface CCEaseBounceOut : CCEaseBounce +{} +// Needed for BridgeSupport +-(void) update: (ccTime) t; +@end + +/** CCEaseBounceInOut action. + @warning This action doesn't use a bijective function. Actions like Sequence might have an unexpected result when used with this action. + @since v0.8.2 + */ +@interface CCEaseBounceInOut : CCEaseBounce +{} +// Needed for BridgeSupport +-(void) update: (ccTime) t; +@end + +/** CCEaseBackIn action. + @warning This action doesn't use a bijective function. Actions like Sequence might have an unexpected result when used with this action. + @since v0.8.2 + */ +@interface CCEaseBackIn : CCActionEase +{} +// Needed for BridgeSupport +-(void) update: (ccTime) t; +@end + +/** CCEaseBackOut action. + @warning This action doesn't use a bijective function. Actions like Sequence might have an unexpected result when used with this action. + @since v0.8.2 + */ +@interface CCEaseBackOut : CCActionEase +{} +// Needed for BridgeSupport +-(void) update: (ccTime) t; +@end + +/** CCEaseBackInOut action. + @warning This action doesn't use a bijective function. Actions like Sequence might have an unexpected result when used with this action. + @since v0.8.2 + */ +@interface CCEaseBackInOut : CCActionEase +{} +// Needed for BridgeSupport +-(void) update: (ccTime) t; +@end + diff --git "a/21451198\345\215\242\350\266\205/project5/MyPlane/libs/cocos2d/CCActionEase.m" "b/21451198\345\215\242\350\266\205/project5/MyPlane/libs/cocos2d/CCActionEase.m" new file mode 100644 index 00000000..8a790b33 --- /dev/null +++ "b/21451198\345\215\242\350\266\205/project5/MyPlane/libs/cocos2d/CCActionEase.m" @@ -0,0 +1,656 @@ +/* + * cocos2d for iPhone: http://www.cocos2d-iphone.org + * + * Copyright (c) 2008-2009 Jason Booth + * Copyright (c) 2013 Nader Eloshaiker + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + * THE SOFTWARE. + * + */ + + +/* + * Elastic, Back and Bounce actions based on code from: + * http://github.com/NikhilK/silverlightfx/ + * + * by http://github.com/NikhilK + */ + +#import "CCActionEase.h" + +#ifndef M_PI_X_2 +#define M_PI_X_2 (float)M_PI * 2.0f +#endif + +#pragma mark EaseAction + +// +// EaseAction +// +@implementation CCActionEase + +@synthesize inner=_inner; + ++(id) actionWithAction: (CCActionInterval*) action +{ + return [[[self alloc] initWithAction: action] autorelease ]; +} + +-(id) initWithAction: (CCActionInterval*) action +{ + NSAssert( action!=nil, @"Ease: arguments must be non-nil"); + + if( (self=[super initWithDuration: action.duration]) ) + _inner = [action retain]; + + return self; +} + +-(id) copyWithZone: (NSZone*) zone +{ + CCAction *copy = [[[self class] allocWithZone:zone] initWithAction:[[_inner copy] autorelease]]; + return copy; +} + +-(void) dealloc +{ + [_inner release]; + [super dealloc]; +} + +-(void) startWithTarget:(id)aTarget +{ + [super startWithTarget:aTarget]; + [_inner startWithTarget:_target]; +} + +-(void) stop +{ + [_inner stop]; + [super stop]; +} + +-(void) update: (ccTime) t +{ + [_inner update: t]; +} + +-(CCActionInterval*) reverse +{ + return [[self class] actionWithAction: [_inner reverse]]; +} +@end + + +#pragma mark - +#pragma mark EaseRate + +// +// EaseRateAction +// +@implementation CCEaseRateAction +@synthesize rate=_rate; ++(id) actionWithAction: (CCActionInterval*) action rate:(float)rate +{ + return [[[self alloc] initWithAction: action rate:rate] autorelease ]; +} + +-(id) initWithAction: (CCActionInterval*) action rate:(float)rate +{ + if( (self=[super initWithAction:action ]) ) + self.rate = rate; + + return self; +} + +-(id) copyWithZone: (NSZone*) zone +{ + CCAction *copy = [[[self class] allocWithZone:zone] initWithAction:[[_inner copy] autorelease] rate:_rate]; + return copy; +} + +-(void) dealloc +{ + [super dealloc]; +} + +-(CCActionInterval*) reverse +{ + return [[self class] actionWithAction: [_inner reverse] rate:1/_rate]; +} +@end + +// +// EeseIn +// +@implementation CCEaseIn +-(void) update: (ccTime) t +{ + [_inner update: powf(t,_rate)]; +} +@end + +// +// EaseOut +// +@implementation CCEaseOut +-(void) update: (ccTime) t +{ + [_inner update: powf(t,1/_rate)]; +} +@end + +// +// EaseInOut +// +@implementation CCEaseInOut +-(void) update: (ccTime) t +{ + t *= 2; + if (t < 1) { + [_inner update: 0.5f * powf (t, _rate)]; + } + else { + [_inner update: 1.0f - 0.5f * powf(2-t, _rate)]; + } +} + +// InOut and OutIn are symmetrical +-(CCActionInterval*) reverse +{ + return [[self class] actionWithAction: [_inner reverse] rate:_rate]; +} + +@end + +#pragma mark - +#pragma mark EaseExponential + +// +// EaseExponentialIn +// +@implementation CCEaseExponentialIn +-(void) update: (ccTime) t +{ + [_inner update: (t==0) ? 0 : powf(2, 10 * (t/1 - 1)) /* - 1 * 0.001f */]; +} + +- (CCActionInterval*) reverse +{ + return [CCEaseExponentialOut actionWithAction: [_inner reverse]]; +} +@end + +// +// EaseExponentialOut +// +@implementation CCEaseExponentialOut +-(void) update: (ccTime) t +{ + [_inner update: (t==1) ? 1 : (-powf(2, -10 * t/1) + 1)]; +} + +- (CCActionInterval*) reverse +{ + return [CCEaseExponentialIn actionWithAction: [_inner reverse]]; +} +@end + +// +// EaseExponentialInOut +// +@implementation CCEaseExponentialInOut +-(void) update: (ccTime) t +{ + // prevents rouding errors + if( t != 1 && t != 0 ) { + t *= 2; + if (t < 1) + t = 0.5f * powf(2, 10 * (t - 1)); + else + t = 0.5f * (-powf(2, -10 * (t -1) ) + 2); + } + + [_inner update:t]; +} +@end + + +#pragma mark - +#pragma mark EasePolynomial + +// +// EasePolynomial +// +#define kDefaultPolynomial 6 +@implementation CCEasePolynomial + +@dynamic polynomialOrder; + ++(id) actionWithAction: (CCActionInterval*) action +{ + return [[[self alloc] initWithAction: action] autorelease]; +} + +-(id) initWithAction: (CCActionInterval*) action +{ + NSAssert( action!=nil, @"Ease: arguments must be non-nil"); + + if (self = [super initWithAction: action]) { + _polynomialOrder = kDefaultPolynomial; + _hasInflection = FALSE; + _intersetValue = 1.78179743628068f; + } + + return self; +} + +-(void)setPolynomialOrder:(NSUInteger)val { + NSAssert(val>1, @"Polynomial order must be greater than 1"); + _polynomialOrder = val; + _hasInflection = (val % 2 > 0); + _intersetValue = powf(0.5f, 1.0f / val) / 0.5f; +} + +-(NSUInteger)polynomialOrder { + return _polynomialOrder; +} +@end + +// +// EasePolynomialIn +// +@implementation CCEasePolynomialIn +-(void) update: (ccTime) t +{ + [_inner update: powf(t, _polynomialOrder)]; +} + +- (CCActionInterval*) reverse +{ + CCEasePolynomialOut *action = [CCEasePolynomialOut actionWithAction: [_inner reverse]]; + if (_polynomialOrder != kDefaultPolynomial) { + action.polynomialOrder = _polynomialOrder; + } + + return action; +} +@end + +// +// EasePolynomialOut +// +@implementation CCEasePolynomialOut +-(void) update: (ccTime) t +{ + if (_hasInflection) { + t = powf(t-1.0f, _polynomialOrder) + 1.0f; + } else { + t = -powf(t-1.0f, _polynomialOrder) + 1.0f; + } + + [_inner update:t]; +} + +- (CCActionInterval*) reverse +{ + CCEasePolynomialIn *action = [CCEasePolynomialIn actionWithAction: [_inner reverse]]; + if (_polynomialOrder != kDefaultPolynomial) { + action.polynomialOrder = _polynomialOrder; + } + + return action; +} +@end + +// +// EasePolynomialInOut +// +@implementation CCEasePolynomialInOut +-(void) update: (ccTime) t +{ + if (t < 0.5f) { + t = powf(t*_intersetValue, _polynomialOrder); + } else { + if (_hasInflection) { + t = powf((t - 1.0f)*_intersetValue, _polynomialOrder) + 1.0f; + } else { + t = -powf((t - 1.0f)*_intersetValue, _polynomialOrder) + 1.0f; + } + } + + [_inner update:t]; +} +@end + +#pragma mark - +#pragma mark EaseSin actions + +// +// EaseSineIn +// +@implementation CCEaseSineIn +-(void) update: (ccTime) t +{ + [_inner update:-1*cosf(t * (float)M_PI_2) +1]; +} + +- (CCActionInterval*) reverse +{ + return [CCEaseSineOut actionWithAction: [_inner reverse]]; +} +@end + +// +// EaseSineOut +// +@implementation CCEaseSineOut +-(void) update: (ccTime) t +{ + [_inner update:sinf(t * (float)M_PI_2)]; +} + +- (CCActionInterval*) reverse +{ + return [CCEaseSineIn actionWithAction: [_inner reverse]]; +} +@end + +// +// EaseSineInOut +// +@implementation CCEaseSineInOut +-(void) update: (ccTime) t +{ + [_inner update:-0.5f*(cosf( (float)M_PI*t) - 1)]; +} +@end + +#pragma mark - +#pragma mark EaseElastic actions + +// +// EaseElastic +// +@implementation CCEaseElastic + +@synthesize period = _period; + ++(id) actionWithAction: (CCActionInterval*) action +{ + return [[[self alloc] initWithAction:action period:0.3f] autorelease]; +} + ++(id) actionWithAction: (CCActionInterval*) action period:(float)period +{ + return [[[self alloc] initWithAction:action period:period] autorelease]; +} + +-(id) initWithAction: (CCActionInterval*) action +{ + return [self initWithAction:action period:0.3f]; +} + +-(id) initWithAction: (CCActionInterval*) action period:(float)period +{ + if( (self=[super initWithAction:action]) ) + _period = period; + + return self; +} + +-(id) copyWithZone: (NSZone*) zone +{ + CCAction *copy = [[[self class] allocWithZone:zone] initWithAction:[[_inner copy] autorelease] period:_period]; + return copy; +} + +-(CCActionInterval*) reverse +{ + NSAssert(NO,@"Override me"); + return nil; +} + +@end + +// +// EaseElasticIn +// + +@implementation CCEaseElasticIn +-(void) update: (ccTime) t +{ + ccTime newT = 0; + if (t == 0 || t == 1) + newT = t; + + else { + float s = _period / 4; + t = t - 1; + newT = -powf(2, 10 * t) * sinf( (t-s) *M_PI_X_2 / _period); + } + [_inner update:newT]; +} + +- (CCActionInterval*) reverse +{ + return [CCEaseElasticOut actionWithAction: [_inner reverse] period:_period]; +} + +@end + +// +// EaseElasticOut +// +@implementation CCEaseElasticOut + +-(void) update: (ccTime) t +{ + ccTime newT = 0; + if (t == 0 || t == 1) { + newT = t; + + } else { + float s = _period / 4; + newT = powf(2, -10 * t) * sinf( (t-s) *M_PI_X_2 / _period) + 1; + } + [_inner update:newT]; +} + +- (CCActionInterval*) reverse +{ + return [CCEaseElasticIn actionWithAction: [_inner reverse] period:_period]; +} + +@end + +// +// EaseElasticInOut +// +@implementation CCEaseElasticInOut +-(void) update: (ccTime) t +{ + ccTime newT = 0; + + if( t == 0 || t == 1 ) + newT = t; + else { + t = t * 2; + if(! _period ) + _period = 0.3f * 1.5f; + ccTime s = _period / 4; + + t = t -1; + if( t < 0 ) + newT = -0.5f * powf(2, 10 * t) * sinf((t - s) * M_PI_X_2 / _period); + else + newT = powf(2, -10 * t) * sinf((t - s) * M_PI_X_2 / _period) * 0.5f + 1; + } + [_inner update:newT]; +} + +- (CCActionInterval*) reverse +{ + return [CCEaseElasticInOut actionWithAction: [_inner reverse] period:_period]; +} + +@end + +#pragma mark - +#pragma mark EaseBounce actions + +// +// EaseBounce +// +@implementation CCEaseBounce +-(ccTime) bounceTime:(ccTime) t +{ + if (t < 1 / 2.75) { + return 7.5625f * t * t; + } + else if (t < 2 / 2.75) { + t -= 1.5f / 2.75f; + return 7.5625f * t * t + 0.75f; + } + else if (t < 2.5 / 2.75) { + t -= 2.25f / 2.75f; + return 7.5625f * t * t + 0.9375f; + } + + t -= 2.625f / 2.75f; + return 7.5625f * t * t + 0.984375f; +} +@end + +// +// EaseBounceIn +// + +@implementation CCEaseBounceIn + +-(void) update: (ccTime) t +{ + ccTime newT = t; + // prevents rounding errors + if( t !=0 && t!=1) + newT = 1 - [self bounceTime:1-t]; + + [_inner update:newT]; +} + +- (CCActionInterval*) reverse +{ + return [CCEaseBounceOut actionWithAction: [_inner reverse]]; +} + +@end + +@implementation CCEaseBounceOut + +-(void) update: (ccTime) t +{ + ccTime newT = t; + // prevents rounding errors + if( t !=0 && t!=1) + newT = [self bounceTime:t]; + + [_inner update:newT]; +} + +- (CCActionInterval*) reverse +{ + return [CCEaseBounceIn actionWithAction: [_inner reverse]]; +} + +@end + +@implementation CCEaseBounceInOut + +-(void) update: (ccTime) t +{ + ccTime newT; + // prevents possible rounding errors + if( t ==0 || t==1) + newT = t; + else if (t < 0.5) { + t = t * 2; + newT = (1 - [self bounceTime:1-t] ) * 0.5f; + } else + newT = [self bounceTime:t * 2 - 1] * 0.5f + 0.5f; + + [_inner update:newT]; +} +@end + +#pragma mark - +#pragma mark Ease Back actions + +// +// EaseBackIn +// +@implementation CCEaseBackIn + +-(void) update: (ccTime) t +{ + ccTime overshoot = 1.70158f; + [_inner update: t * t * ((overshoot + 1) * t - overshoot)]; +} + +- (CCActionInterval*) reverse +{ + return [CCEaseBackOut actionWithAction: [_inner reverse]]; +} +@end + +// +// EaseBackOut +// +@implementation CCEaseBackOut +-(void) update: (ccTime) t +{ + ccTime overshoot = 1.70158f; + + t = t - 1; + [_inner update: t * t * ((overshoot + 1) * t + overshoot) + 1]; +} + +- (CCActionInterval*) reverse +{ + return [CCEaseBackIn actionWithAction: [_inner reverse]]; +} +@end + +// +// EaseBackInOut +// +@implementation CCEaseBackInOut + +-(void) update: (ccTime) t +{ + ccTime overshoot = 1.70158f * 1.525f; + + t = t * 2; + if (t < 1) + [_inner update: (t * t * ((overshoot + 1) * t - overshoot)) / 2]; + else { + t = t - 2; + [_inner update: (t * t * ((overshoot + 1) * t + overshoot)) / 2 + 1]; + } +} +@end diff --git "a/21451198\345\215\242\350\266\205/project5/MyPlane/libs/cocos2d/CCActionGrid.h" "b/21451198\345\215\242\350\266\205/project5/MyPlane/libs/cocos2d/CCActionGrid.h" new file mode 100644 index 00000000..53fd1cc7 --- /dev/null +++ "b/21451198\345\215\242\350\266\205/project5/MyPlane/libs/cocos2d/CCActionGrid.h" @@ -0,0 +1,167 @@ +/* + * cocos2d for iPhone: http://www.cocos2d-iphone.org + * + * Copyright (c) 2009 On-Core + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + * THE SOFTWARE. + * + */ + + +#import "CCActionInterval.h" +#import "CCActionInstant.h" +#import "CCGrid.h" + +@class CCGridBase; + +/** Base class for Grid actions */ +@interface CCGridAction : CCActionInterval +{ + CGSize _gridSize; +} + +/** size of the grid */ +@property (nonatomic,readwrite) CGSize gridSize; + +/** creates the action with size and duration */ ++(id) actionWithDuration:(ccTime)duration size:(CGSize)gridSize; +/** initializes the action with size and duration */ +-(id) initWithDuration:(ccTime)duration size:(CGSize)gridSize; +/** returns the grid */ +-(CCGridBase *)grid; + +@end + +//////////////////////////////////////////////////////////// + +/** Base class for CCGrid3D actions. + Grid3D actions can modify a non-tiled grid. + */ +@interface CCGrid3DAction : CCGridAction +{ +} + +/** returns the vertex than belongs to certain position in the grid */ +-(ccVertex3F)vertex:(CGPoint)position; +/** returns the non-transformed vertex than belongs to certain position in the grid */ +-(ccVertex3F)originalVertex:(CGPoint)position; +/** sets a new vertex to a certain position of the grid */ +-(void)setVertex:(CGPoint)position vertex:(ccVertex3F)vertex; + +@end + +//////////////////////////////////////////////////////////// + +/** Base class for CCTiledGrid3D actions */ +@interface CCTiledGrid3DAction : CCGridAction +{ +} + +/** returns the tile that belongs to a certain position of the grid */ +-(ccQuad3)tile:(CGPoint)position; +/** returns the non-transformed tile that belongs to a certain position of the grid */ +-(ccQuad3)originalTile:(CGPoint)position; +/** sets a new tile to a certain position of the grid */ +-(void)setTile:(CGPoint)position coords:(ccQuad3)coords; + +@end + +//////////////////////////////////////////////////////////// + +/** CCAccelDeccelAmplitude action */ +@interface CCAccelDeccelAmplitude : CCActionInterval +{ + float _rate; + CCActionInterval *_other; +} + +/** amplitude rate */ +@property (nonatomic,readwrite) float rate; + +/** creates the action with an inner action that has the amplitude property, and a duration time */ ++(id)actionWithAction:(CCAction*)action duration:(ccTime)d; +/** initializes the action with an inner action that has the amplitude property, and a duration time */ +-(id)initWithAction:(CCAction*)action duration:(ccTime)d; + +@end + +//////////////////////////////////////////////////////////// + +/** CCAccelAmplitude action */ +@interface CCAccelAmplitude : CCActionInterval +{ + float _rate; + CCActionInterval *_other; +} + +/** amplitude rate */ +@property (nonatomic,readwrite) float rate; + +/** creates the action with an inner action that has the amplitude property, and a duration time */ ++(id)actionWithAction:(CCAction*)action duration:(ccTime)d; +/** initializes the action with an inner action that has the amplitude property, and a duration time */ +-(id)initWithAction:(CCAction*)action duration:(ccTime)d; + +@end + +//////////////////////////////////////////////////////////// + +/** CCDeccelAmplitude action */ +@interface CCDeccelAmplitude : CCActionInterval +{ + float _rate; + CCActionInterval *_other; +} + +/** amplitude rate */ +@property (nonatomic,readwrite) float rate; + +/** creates the action with an inner action that has the amplitude property, and a duration time */ ++(id)actionWithAction:(CCAction*)action duration:(ccTime)d; +/** initializes the action with an inner action that has the amplitude property, and a duration time */ +-(id)initWithAction:(CCAction*)action duration:(ccTime)d; + +@end + +//////////////////////////////////////////////////////////// + +/** CCStopGrid action. + Don't call this action if another grid action is active. + Call if you want to remove the the grid effect. Example: + [Sequence actions:[Lens ...], [StopGrid action], nil]; + */ +@interface CCStopGrid : CCActionInstant +{ +} +// to make BridgeSupport happy +-(void)startWithTarget:(id)aTarget; +@end + +//////////////////////////////////////////////////////////// + +/** CCReuseGrid action */ +@interface CCReuseGrid : CCActionInstant +{ + int _times; +} +/** creates an action with the number of times that the current grid will be reused */ ++(id) actionWithTimes: (int) times; +/** initializes an action with the number of times that the current grid will be reused */ +-(id) initWithTimes: (int) times; +@end diff --git "a/21451198\345\215\242\350\266\205/project5/MyPlane/libs/cocos2d/CCActionGrid.m" "b/21451198\345\215\242\350\266\205/project5/MyPlane/libs/cocos2d/CCActionGrid.m" new file mode 100644 index 00000000..fb0b17aa --- /dev/null +++ "b/21451198\345\215\242\350\266\205/project5/MyPlane/libs/cocos2d/CCActionGrid.m" @@ -0,0 +1,386 @@ +/* + * cocos2d for iPhone: http://www.cocos2d-iphone.org + * + * Copyright (c) 2009 On-Core + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + * THE SOFTWARE. + * + */ + + +#import "CCActionGrid.h" +#import "CCDirector.h" + +#pragma mark - +#pragma mark GridAction + +@implementation CCGridAction + +@synthesize gridSize = _gridSize; + ++(id) actionWithDuration:(ccTime)duration size:(CGSize)gridSize; +{ + return [[[self alloc] initWithDuration:duration size:gridSize] autorelease]; +} + +-(id) initWithDuration:(ccTime)duration size:(CGSize)gridSize; +{ + if ( (self = [super initWithDuration:duration]) ) + { + _gridSize = gridSize; + } + + return self; +} + +-(void)startWithTarget:(id)target +{ + [super startWithTarget:target]; + + CCGridBase *newgrid = [self grid]; + + CCNode *t = (CCNode*) target; + CCGridBase *targetGrid = [t grid]; + + if ( targetGrid && targetGrid.reuseGrid > 0 ) + { + if ( targetGrid.active && targetGrid.gridSize.width == _gridSize.width && targetGrid.gridSize.height == _gridSize.height && [targetGrid isKindOfClass:[newgrid class]] ) + [targetGrid reuse]; + else + [NSException raise:@"GridBase" format:@"Cannot reuse grid"]; + } + else + { + if ( targetGrid && targetGrid.active ) + targetGrid.active = NO; + + [t setGrid: newgrid]; + t.grid.active = YES; + } +} + +-(CCGridBase *)grid +{ + [NSException raise:@"GridBase" format:@"Abstract class needs implementation"]; + return nil; +} + +- (CCActionInterval*) reverse +{ + return [CCReverseTime actionWithAction:self]; +} + +-(id) copyWithZone: (NSZone*) zone +{ + CCGridAction *copy = [[[self class] allocWithZone:zone] initWithDuration:_duration size:_gridSize]; + return copy; +} +@end + +//////////////////////////////////////////////////////////// + +#pragma mark - +#pragma mark Grid3DAction + +@implementation CCGrid3DAction + +-(CCGridBase *)grid +{ + return [CCGrid3D gridWithSize:_gridSize]; +} + +-(ccVertex3F)vertex:(CGPoint)pos +{ + CCGrid3D *g = (CCGrid3D *)[_target grid]; + return [g vertex:pos]; +} + +-(ccVertex3F)originalVertex:(CGPoint)pos +{ + CCGrid3D *g = (CCGrid3D *)[_target grid]; + return [g originalVertex:pos]; +} + +-(void)setVertex:(CGPoint)pos vertex:(ccVertex3F)vertex +{ + CCGrid3D *g = (CCGrid3D *)[_target grid]; + [g setVertex:pos vertex:vertex]; +} +@end + +//////////////////////////////////////////////////////////// + +#pragma mark - +#pragma mark TiledGrid3DAction + +@implementation CCTiledGrid3DAction + +-(CCGridBase *)grid +{ + return [CCTiledGrid3D gridWithSize:_gridSize]; +} + +-(ccQuad3)tile:(CGPoint)pos +{ + CCTiledGrid3D *g = (CCTiledGrid3D *)[_target grid]; + return [g tile:pos]; +} + +-(ccQuad3)originalTile:(CGPoint)pos +{ + CCTiledGrid3D *g = (CCTiledGrid3D *)[_target grid]; + return [g originalTile:pos]; +} + +-(void)setTile:(CGPoint)pos coords:(ccQuad3)coords +{ + CCTiledGrid3D *g = (CCTiledGrid3D *)[_target grid]; + [g setTile:pos coords:coords]; +} + +@end + +//////////////////////////////////////////////////////////// + +@interface CCActionInterval (Amplitude) +-(void)setAmplitudeRate:(CGFloat)amp; +-(CGFloat)getAmplitudeRate; +@end + +@implementation CCActionInterval (Amplitude) +-(void)setAmplitudeRate:(CGFloat)amp +{ + [NSException raise:@"IntervalAction (Amplitude)" format:@"Abstract class needs implementation"]; +} + +-(CGFloat)getAmplitudeRate +{ + [NSException raise:@"IntervalAction (Amplitude)" format:@"Abstract class needs implementation"]; + return 0; +} +@end + +//////////////////////////////////////////////////////////// + +#pragma mark - +#pragma mark AccelDeccelAmplitude + +@implementation CCAccelDeccelAmplitude + +@synthesize rate=_rate; + ++(id)actionWithAction:(CCAction*)action duration:(ccTime)d +{ + return [[[self alloc] initWithAction:action duration:d ] autorelease]; +} + +-(id)initWithAction:(CCAction *)action duration:(ccTime)d +{ + if ( (self = [super initWithDuration:d]) ) + { + _rate = 1.0f; + _other = (CCActionInterval*)[action retain]; + } + + return self; +} + +-(void)dealloc +{ + [_other release]; + [super dealloc]; +} + +-(void)startWithTarget:(id)aTarget +{ + [super startWithTarget:aTarget]; + [_other startWithTarget:_target]; +} + +-(void) update: (ccTime) time +{ + float f = time*2; + + if (f > 1) + { + f -= 1; + f = 1 - f; + } + + [_other setAmplitudeRate:powf(f, _rate)]; + [_other update:time]; +} + +- (CCActionInterval*) reverse +{ + return [CCAccelDeccelAmplitude actionWithAction:[_other reverse] duration:_duration]; +} + +@end + +//////////////////////////////////////////////////////////// + +#pragma mark - +#pragma mark AccelAmplitude + +@implementation CCAccelAmplitude + +@synthesize rate=_rate; + ++(id)actionWithAction:(CCAction*)action duration:(ccTime)d +{ + return [[[self alloc] initWithAction:action duration:d ] autorelease]; +} + +-(id)initWithAction:(CCAction *)action duration:(ccTime)d +{ + if ( (self = [super initWithDuration:d]) ) + { + _rate = 1.0f; + _other = (CCActionInterval*)[action retain]; + } + + return self; +} + +-(void)dealloc +{ + [_other release]; + [super dealloc]; +} + +-(void)startWithTarget:(id)aTarget +{ + [super startWithTarget:aTarget]; + [_other startWithTarget:_target]; +} + +-(void) update: (ccTime) time +{ + [_other setAmplitudeRate:powf(time, _rate)]; + [_other update:time]; +} + +- (CCActionInterval*) reverse +{ + return [CCAccelAmplitude actionWithAction:[_other reverse] duration:self.duration]; +} + +@end + +//////////////////////////////////////////////////////////// + +#pragma mark - +#pragma mark DeccelAmplitude + +@implementation CCDeccelAmplitude + +@synthesize rate=_rate; + ++(id)actionWithAction:(CCAction*)action duration:(ccTime)d +{ + return [[[self alloc] initWithAction:action duration:d ] autorelease]; +} + +-(id)initWithAction:(CCAction *)action duration:(ccTime)d +{ + if ( (self = [super initWithDuration:d]) ) + { + _rate = 1.0f; + _other = (CCActionInterval*)[action retain]; + } + + return self; +} + +-(void)dealloc +{ + [_other release]; + [super dealloc]; +} + +-(void)startWithTarget:(id)aTarget +{ + [super startWithTarget:aTarget]; + [_other startWithTarget:_target]; +} + +-(void) update: (ccTime) time +{ + [_other setAmplitudeRate:powf((1-time), _rate)]; + [_other update:time]; +} + +- (CCActionInterval*) reverse +{ + return [CCDeccelAmplitude actionWithAction:[_other reverse] duration:self.duration]; +} + +@end + +//////////////////////////////////////////////////////////// + +#pragma mark - +#pragma mark StopGrid + +@implementation CCStopGrid + +-(void)startWithTarget:(id)aTarget +{ + [super startWithTarget:aTarget]; + + if ( [[self target] grid] && [[[self target] grid] active] ) { + [[[self target] grid] setActive: NO]; + +// [[self target] setGrid: nil]; + } +} + +@end + +//////////////////////////////////////////////////////////// + +#pragma mark - +#pragma mark ReuseGrid + +@implementation CCReuseGrid + ++(id)actionWithTimes:(int)times +{ + return [[[self alloc] initWithTimes:times ] autorelease]; +} + +-(id)initWithTimes:(int)times +{ + if ( (self = [super init]) ) + _times = times; + + return self; +} + +-(void)startWithTarget:(id)aTarget +{ + [super startWithTarget:aTarget]; + + CCNode *myTarget = (CCNode*) [self target]; + if ( myTarget.grid && myTarget.grid.active ) + myTarget.grid.reuseGrid += _times; +} + +@end diff --git "a/21451198\345\215\242\350\266\205/project5/MyPlane/libs/cocos2d/CCActionGrid3D.h" "b/21451198\345\215\242\350\266\205/project5/MyPlane/libs/cocos2d/CCActionGrid3D.h" new file mode 100644 index 00000000..6c345127 --- /dev/null +++ "b/21451198\345\215\242\350\266\205/project5/MyPlane/libs/cocos2d/CCActionGrid3D.h" @@ -0,0 +1,208 @@ +/* + * cocos2d for iPhone: http://www.cocos2d-iphone.org + * + * Copyright (c) 2009 On-Core + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + * THE SOFTWARE. + * + */ + + +#import "CCActionGrid.h" + +/** CCWaves3D action */ +@interface CCWaves3D : CCGrid3DAction +{ + NSUInteger _waves; + float _amplitude; + float _amplitudeRate; +} + +/** amplitude of the wave */ +@property (nonatomic,readwrite) float amplitude; +/** amplitude rate of the wave */ +@property (nonatomic,readwrite) float amplitudeRate; + +/** creates an action with duration, grid size, waves and amplitud */ ++(id)actionWithDuration:(ccTime)duration size:(CGSize)gridSize waves:(NSUInteger)wav amplitude:(float)amp; +/** initializeds an action with duration, grid size, waves and amplitud */ +-(id)initWithDuration:(ccTime)duration size:(CGSize)gridSize waves:(NSUInteger)wav amplitude:(float)amp; + +@end + +//////////////////////////////////////////////////////////// + +/** CCFlipX3D action */ +@interface CCFlipX3D : CCGrid3DAction +{ +} + +/** creates the action with duration */ ++(id) actionWithDuration:(ccTime)d; +/** initializes the action with duration */ +-(id) initWithDuration:(ccTime)d; + +@end + +//////////////////////////////////////////////////////////// + +/** CCFlipY3D action */ +@interface CCFlipY3D : CCFlipX3D +{ +} +// Needed for bridge support +-(void)update:(ccTime)time; +@end + +//////////////////////////////////////////////////////////// + +/** CCLens3D action */ +@interface CCLens3D : CCGrid3DAction +{ + CGPoint _position; + float _radius; + float _lensEffect; + BOOL _dirty; +} + +/** lens effect. Defaults to 0.7 - 0 means no effect, 1 is very strong effect */ +@property (nonatomic,readwrite) float lensEffect; +/** lens center position in Points */ +@property (nonatomic,readwrite) CGPoint position; + +/** creates the action with center position in Points, radius, a grid size and duration */ ++(id)actionWithDuration:(ccTime)duration size:(CGSize)gridSize position:(CGPoint)pos radius:(float)radius; +/** initializes the action with center position in Points, radius, a grid size and duration */ +-(id)initWithDuration:(ccTime)duration size:(CGSize)gridSize position:(CGPoint)pos radius:(float)radius; + +@end + +//////////////////////////////////////////////////////////// + +/** CCRipple3D action */ +@interface CCRipple3D : CCGrid3DAction +{ + CGPoint _position; + float _radius; + NSUInteger _waves; + float _amplitude; + float _amplitudeRate; +} + +/** center position in Points */ +@property (nonatomic,readwrite) CGPoint position; +/** amplitude */ +@property (nonatomic,readwrite) float amplitude; +/** amplitude rate */ +@property (nonatomic,readwrite) float amplitudeRate; + +/** creates the action with a position in points, radius, number of waves, amplitude, a grid size and duration */ ++(id)actionWithDuration:(ccTime)d size:(CGSize)gridSize position:(CGPoint)pos radius:(float)r waves:(NSInteger)wav amplitude:(float)amp; +/** initializes the action with a position in points, radius, number of waves, amplitude, a grid size and duration */ +-(id)initWithDuration:(ccTime)d size:(CGSize)gridSize position:(CGPoint)pos radius:(float)r waves:(NSInteger)wav amplitude:(float)amp; + +@end + +//////////////////////////////////////////////////////////// + +/** CCShaky3D action */ +@interface CCShaky3D : CCGrid3DAction +{ + int _randrange; + BOOL _shakeZ; +} + +/** creates the action with a range, shake Z vertices, a grid and duration */ ++(id)actionWithDuration:(ccTime)duration size:(CGSize)gridSize range:(int)range shakeZ:(BOOL)shakeZ; +/** initializes the action with a range, shake Z vertices, a grid and duration */ +-(id)initWithDuration:(ccTime)duration size:(CGSize)gridSize range:(int)range shakeZ:(BOOL)shakeZ; + +@end + +//////////////////////////////////////////////////////////// + +/** CCLiquid action */ +@interface CCLiquid : CCGrid3DAction +{ + NSUInteger _waves; + float _amplitude; + float _amplitudeRate; + +} + +/** amplitude */ +@property (nonatomic,readwrite) float amplitude; +/** amplitude rate */ +@property (nonatomic,readwrite) float amplitudeRate; + +/** creates the action with amplitude, a grid and duration */ ++(id)actionWithDuration:(ccTime)duration size:(CGSize)gridSize waves:(NSUInteger)wav amplitude:(float)amp; +/** initializes the action with amplitude, a grid and duration */ +-(id)initWithDuration:(ccTime)duration size:(CGSize)gridSize waves:(NSUInteger)wav amplitude:(float)amp; + +@end + +//////////////////////////////////////////////////////////// + +/** CCWaves action */ +@interface CCWaves : CCGrid3DAction +{ + NSUInteger _waves; + float _amplitude; + float _amplitudeRate; + BOOL _vertical; + BOOL _horizontal; +} + +/** amplitude */ +@property (nonatomic,readwrite) float amplitude; +/** amplitude rate */ +@property (nonatomic,readwrite) float amplitudeRate; + +/** initializes the action with amplitude, horizontal sin, vertical sin, a grid and duration */ ++(id)actionWithDuration:(ccTime)duration size:(CGSize)gridSize waves:(NSUInteger)wav amplitude:(float)amp horizontal:(BOOL)h vertical:(BOOL)v; +/** creates the action with amplitude, horizontal sin, vertical sin, a grid and duration */ +-(id)initWithDuration:(ccTime)duration size:(CGSize)gridSize waves:(NSUInteger)wav amplitude:(float)amp horizontal:(BOOL)h vertical:(BOOL)v; + +@end + +//////////////////////////////////////////////////////////// + +/** CCTwirl action */ +@interface CCTwirl : CCGrid3DAction +{ + CGPoint _position; + NSUInteger _twirls; + float _amplitude; + float _amplitudeRate; +} + +/** twirl center */ +@property (nonatomic,readwrite) CGPoint position; +/** amplitude */ +@property (nonatomic,readwrite) float amplitude; +/** amplitude rate */ +@property (nonatomic,readwrite) float amplitudeRate; + +/** creates the action with center position, number of twirls, amplitude, a grid size and duration */ ++(id)actionWithDuration:(ccTime)duration size:(CGSize)gridSize position:(CGPoint)pos twirls:(NSUInteger)t amplitude:(float)amp; +/** initializes the action with center position, number of twirls, amplitude, a grid size and duration */ +-(id)initWithDuration:(ccTime)duration size:(CGSize)gridSize position:(CGPoint)pos twirls:(NSUInteger)t amplitude:(float)amp; + +@end diff --git "a/21451198\345\215\242\350\266\205/project5/MyPlane/libs/cocos2d/CCActionGrid3D.m" "b/21451198\345\215\242\350\266\205/project5/MyPlane/libs/cocos2d/CCActionGrid3D.m" new file mode 100644 index 00000000..3aa8dcf1 --- /dev/null +++ "b/21451198\345\215\242\350\266\205/project5/MyPlane/libs/cocos2d/CCActionGrid3D.m" @@ -0,0 +1,642 @@ +/* + * cocos2d for iPhone: http://www.cocos2d-iphone.org + * + * Copyright (c) 2009 On-Core + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + * THE SOFTWARE. + * + */ + + +#import "CCActionGrid3D.h" +#import "ccMacros.h" +#import "Support/CGPointExtension.h" + +#pragma mark - +#pragma mark Waves3D + +@implementation CCWaves3D + +@synthesize amplitude=_amplitude; +@synthesize amplitudeRate=_amplitudeRate; + ++(id)actionWithDuration:(ccTime)duration size:(CGSize)gridSize waves:(NSUInteger)wav amplitude:(float)amp +{ + return [[[self alloc] initWithDuration:duration size:gridSize waves:wav amplitude:amp] autorelease]; +} + +-(id)initWithDuration:(ccTime)duration size:(CGSize)gridSize waves:(NSUInteger)wav amplitude:(float)amp +{ + if ( (self = [super initWithDuration:duration size:gridSize]) ) + { + _waves = wav; + _amplitude = amp; + _amplitudeRate = 1.0f; + } + + return self; +} + +-(id) copyWithZone: (NSZone*) zone +{ + return [[[self class] allocWithZone:zone] initWithDuration:_duration size:_gridSize waves:_waves amplitude:_amplitude]; +} + + +-(void)update:(ccTime)time +{ + int i, j; + + for( i = 0; i < (_gridSize.width+1); i++ ) + { + for( j = 0; j < (_gridSize.height+1); j++ ) + { + ccVertex3F v = [self originalVertex:ccp(i,j)]; + v.z += (sinf((CGFloat)M_PI*time*_waves*2 + (v.y+v.x) * .01f) * _amplitude * _amplitudeRate); + [self setVertex:ccp(i,j) vertex:v]; + } + } +} +@end + +//////////////////////////////////////////////////////////// + +#pragma mark - +#pragma mark FlipX3D + +@implementation CCFlipX3D + ++(id) actionWithDuration:(ccTime)d +{ + return [[[self alloc] initWithDuration:d size:CGSizeMake(1,1)] autorelease]; +} + +-(id) initWithDuration:(ccTime)d +{ + return [super initWithDuration:d size:CGSizeMake(1,1)]; +} + +-(id)initWithSize:(CGSize)gSize duration:(ccTime)d +{ + if ( gSize.width != 1 || gSize.height != 1 ) + { + [NSException raise:@"FlipX3D" format:@"Grid size must be (1,1)"]; + } + + return [super initWithDuration:d size:gSize]; +} + +-(id) copyWithZone: (NSZone*) zone +{ + CCGridAction *copy = [[[self class] allocWithZone:zone] initWithSize:_gridSize duration:_duration]; + return copy; +} + + +-(void)update:(ccTime)time +{ + CGFloat angle = (CGFloat)M_PI * time; // 180 degrees + CGFloat mz = sinf( angle ); + angle = angle / 2.0f; // x calculates degrees from 0 to 90 + CGFloat mx = cosf( angle ); + + ccVertex3F v0, v1, v, diff; + + v0 = [self originalVertex:ccp(1,1)]; + v1 = [self originalVertex:ccp(0,0)]; + + CGFloat x0 = v0.x; + CGFloat x1 = v1.x; + CGFloat x; + CGPoint a, b, c, d; + + if ( x0 > x1 ) + { + // Normal Grid + a = ccp(0,0); + b = ccp(0,1); + c = ccp(1,0); + d = ccp(1,1); + x = x0; + } + else + { + // Reversed Grid + c = ccp(0,0); + d = ccp(0,1); + a = ccp(1,0); + b = ccp(1,1); + x = x1; + } + + diff.x = ( x - x * mx ); + diff.z = fabsf( floorf( (x * mz) / 4.0f ) ); + +// bottom-left + v = [self originalVertex:a]; + v.x = diff.x; + v.z += diff.z; + [self setVertex:a vertex:v]; + +// upper-left + v = [self originalVertex:b]; + v.x = diff.x; + v.z += diff.z; + [self setVertex:b vertex:v]; + +// bottom-right + v = [self originalVertex:c]; + v.x -= diff.x; + v.z -= diff.z; + [self setVertex:c vertex:v]; + +// upper-right + v = [self originalVertex:d]; + v.x -= diff.x; + v.z -= diff.z; + [self setVertex:d vertex:v]; +} + +@end + +//////////////////////////////////////////////////////////// + +#pragma mark - +#pragma mark FlipY3D + +@implementation CCFlipY3D + +-(void)update:(ccTime)time +{ + CGFloat angle = (CGFloat)M_PI * time; // 180 degrees + CGFloat mz = sinf( angle ); + angle = angle / 2.0f; // x calculates degrees from 0 to 90 + CGFloat my = cosf( angle ); + + ccVertex3F v0, v1, v, diff; + + v0 = [self originalVertex:ccp(1,1)]; + v1 = [self originalVertex:ccp(0,0)]; + + CGFloat y0 = v0.y; + CGFloat y1 = v1.y; + CGFloat y; + CGPoint a, b, c, d; + + if ( y0 > y1 ) + { + // Normal Grid + a = ccp(0,0); + b = ccp(0,1); + c = ccp(1,0); + d = ccp(1,1); + y = y0; + } + else + { + // Reversed Grid + b = ccp(0,0); + a = ccp(0,1); + d = ccp(1,0); + c = ccp(1,1); + y = y1; + } + + diff.y = y - y * my; + diff.z = fabsf( floorf( (y * mz) / 4.0f ) ); + + // bottom-left + v = [self originalVertex:a]; + v.y = diff.y; + v.z += diff.z; + [self setVertex:a vertex:v]; + + // upper-left + v = [self originalVertex:b]; + v.y -= diff.y; + v.z -= diff.z; + [self setVertex:b vertex:v]; + + // bottom-right + v = [self originalVertex:c]; + v.y = diff.y; + v.z += diff.z; + [self setVertex:c vertex:v]; + + // upper-right + v = [self originalVertex:d]; + v.y -= diff.y; + v.z -= diff.z; + [self setVertex:d vertex:v]; +} + +@end + +//////////////////////////////////////////////////////////// + +#pragma mark - +#pragma mark Lens3D + +@implementation CCLens3D + +@synthesize lensEffect=_lensEffect; + ++(id)actionWithDuration:(ccTime)duration size:(CGSize)gridSize position:(CGPoint)pos radius:(float)radius +{ + return [[[self alloc] initWithDuration:duration size:gridSize position:pos radius:radius] autorelease]; +} + +-(id)initWithDuration:(ccTime)duration size:(CGSize)gridSize position:(CGPoint)pos radius:(float)radius +{ + if ( (self = [super initWithDuration:duration size:gridSize]) ) + { + _position = ccp(-1,-1); + self.position = pos; + _radius = radius; + _lensEffect = 0.7f; + _dirty = YES; + } + + return self; +} + +-(id) copyWithZone: (NSZone*) zone +{ + CCGridAction *copy = [[[self class] allocWithZone:zone] initWithDuration:_duration size:_gridSize position:_position radius:_radius]; + return copy; +} + +-(void) setPosition:(CGPoint)pos +{ + if( ! CGPointEqualToPoint(pos, _position) ) { + _position = pos; + _dirty = YES; + } +} + +-(CGPoint) position +{ + return _position; +} + +-(void)update:(ccTime)time +{ + if ( _dirty ) + { + int i, j; + + for( i = 0; i < _gridSize.width+1; i++ ) + { + for( j = 0; j < _gridSize.height+1; j++ ) + { + ccVertex3F v = [self originalVertex:ccp(i,j)]; + CGPoint vect = ccpSub(_position, ccp(v.x,v.y)); + CGFloat r = ccpLength(vect); + + if ( r < _radius ) + { + r = _radius - r; + CGFloat pre_log = r / _radius; + if ( pre_log == 0 ) pre_log = 0.001f; + float l = logf(pre_log) * _lensEffect; + float new_r = expf( l ) * _radius; + + if ( ccpLength(vect) > 0 ) + { + vect = ccpNormalize(vect); + CGPoint new_vect = ccpMult(vect, new_r); + v.z += ccpLength(new_vect) * _lensEffect; + } + } + + [self setVertex:ccp(i,j) vertex:v]; + } + } + + _dirty = NO; + } +} + +@end + +//////////////////////////////////////////////////////////// + +#pragma mark - +#pragma mark Ripple3D + +@implementation CCRipple3D + +@synthesize amplitude = _amplitude; +@synthesize amplitudeRate = _amplitudeRate; + + ++(id)actionWithDuration:(ccTime)d size:(CGSize)gridSize position:(CGPoint)pos radius:(float)r waves:(NSInteger)wav amplitude:(float)amp +{ + return [[[self alloc] initWithDuration:d size:gridSize position:pos radius:r waves:wav amplitude:amp] autorelease]; +} + +-(id)initWithDuration:(ccTime)d size:(CGSize)gridSize position:(CGPoint)pos radius:(float)r waves:(NSInteger)wav amplitude:(float)amp +{ + if ( (self = [super initWithDuration:d size:gridSize]) ) + { + self.position = pos; + _radius = r; + _waves = wav; + _amplitude = amp; + _amplitudeRate = 1.0f; + } + + return self; +} + +-(CGPoint) position +{ + return _position; +} + +-(void) setPosition:(CGPoint)pos +{ + _position = pos; +} + +-(id) copyWithZone: (NSZone*) zone +{ + return [[[self class] allocWithZone:zone] initWithDuration:_duration size:_gridSize position:_position radius:_radius waves:_waves amplitude:_amplitude]; +} + +-(void)update:(ccTime)time +{ + int i, j; + + for( i = 0; i < (_gridSize.width+1); i++ ) + { + for( j = 0; j < (_gridSize.height+1); j++ ) + { + ccVertex3F v = [self originalVertex:ccp(i,j)]; + CGPoint vect = ccpSub(_position, ccp(v.x,v.y)); + CGFloat r = ccpLength(vect); + + if ( r < _radius ) + { + r = _radius - r; + CGFloat rate = powf( r / _radius, 2); + v.z += (sinf( time*(CGFloat)M_PI*_waves*2 + r * 0.1f) * _amplitude * _amplitudeRate * rate ); + } + + [self setVertex:ccp(i,j) vertex:v]; + } + } +} + +@end + +//////////////////////////////////////////////////////////// + +#pragma mark - +#pragma mark Shaky3D + +@implementation CCShaky3D + ++(id)actionWithDuration:(ccTime)duration size:(CGSize)gridSize range:(int)range shakeZ:(BOOL)shakeZ +{ + return [[[self alloc] initWithDuration:duration size:gridSize range:range shakeZ:shakeZ] autorelease]; +} + +-(id)initWithDuration:(ccTime)duration size:(CGSize)gridSize range:(int)range shakeZ:(BOOL)shakeZ +{ + if ( (self = [super initWithDuration:duration size:gridSize]) ) + { + _randrange = range; + _shakeZ = shakeZ; + } + + return self; +} + +-(id) copyWithZone: (NSZone*) zone +{ + return [[[self class] allocWithZone:zone] initWithDuration:_duration size:_gridSize range:_randrange shakeZ:_shakeZ]; +} + +-(void)update:(ccTime)time +{ + int i, j; + + for( i = 0; i < (_gridSize.width+1); i++ ) + { + for( j = 0; j < (_gridSize.height+1); j++ ) + { + ccVertex3F v = [self originalVertex:ccp(i,j)]; + v.x += ( rand() % (_randrange*2) ) - _randrange; + v.y += ( rand() % (_randrange*2) ) - _randrange; + if( _shakeZ ) + v.z += ( rand() % (_randrange*2) ) - _randrange; + + [self setVertex:ccp(i,j) vertex:v]; + } + } +} + +@end + +//////////////////////////////////////////////////////////// + +#pragma mark - +#pragma mark Liquid + +@implementation CCLiquid + +@synthesize amplitude=_amplitude; +@synthesize amplitudeRate=_amplitudeRate; + ++(id)actionWithDuration:(ccTime)duration size:(CGSize)gridSize waves:(NSUInteger)wav amplitude:(float)amp +{ + return [[[self alloc] initWithDuration:duration size:gridSize waves:wav amplitude:amp] autorelease]; +} + +-(id)initWithDuration:(ccTime)duration size:(CGSize)gridSize waves:(NSUInteger)wav amplitude:(float)amp +{ + if ( (self = [super initWithDuration:duration size:gridSize]) ) + { + _waves = wav; + _amplitude = amp; + _amplitudeRate = 1.0f; + } + + return self; +} + +-(void)update:(ccTime)time +{ + int i, j; + + for( i = 1; i < _gridSize.width; i++ ) + { + for( j = 1; j < _gridSize.height; j++ ) + { + ccVertex3F v = [self originalVertex:ccp(i,j)]; + v.x = (v.x + (sinf(time*(CGFloat)M_PI*_waves*2 + v.x * .01f) * _amplitude * _amplitudeRate)); + v.y = (v.y + (sinf(time*(CGFloat)M_PI*_waves*2 + v.y * .01f) * _amplitude * _amplitudeRate)); + [self setVertex:ccp(i,j) vertex:v]; + } + } +} + +-(id) copyWithZone: (NSZone*) zone +{ + return [[[self class] allocWithZone:zone] initWithDuration:_duration size:_gridSize waves:_waves amplitude:_amplitude]; +} + +@end + +//////////////////////////////////////////////////////////// + +#pragma mark - +#pragma mark Waves + +@implementation CCWaves + +@synthesize amplitude=_amplitude; +@synthesize amplitudeRate=_amplitudeRate; + ++(id)actionWithDuration:(ccTime)duration size:(CGSize)gridSize waves:(NSUInteger)wav amplitude:(float)amp horizontal:(BOOL)h vertical:(BOOL)v +{ + return [[[self alloc] initWithDuration:duration size:gridSize waves:wav amplitude:amp horizontal:h vertical:v] autorelease]; +} + +-(id)initWithDuration:(ccTime)duration size:(CGSize)gridSize waves:(NSUInteger)wav amplitude:(float)amp horizontal:(BOOL)h vertical:(BOOL)v +{ + if ( (self = [super initWithDuration:duration size:gridSize]) ) + { + _waves = wav; + _amplitude = amp; + _amplitudeRate = 1.0f; + _horizontal = h; + _vertical = v; + } + + return self; +} + +-(void)update:(ccTime)time +{ + int i, j; + + for( i = 0; i < (_gridSize.width+1); i++ ) + { + for( j = 0; j < (_gridSize.height+1); j++ ) + { + ccVertex3F v = [self originalVertex:ccp(i,j)]; + + if ( _vertical ) + v.x = (v.x + (sinf(time*(CGFloat)M_PI*_waves*2 + v.y * .01f) * _amplitude * _amplitudeRate)); + + if ( _horizontal ) + v.y = (v.y + (sinf(time*(CGFloat)M_PI*_waves*2 + v.x * .01f) * _amplitude * _amplitudeRate)); + + [self setVertex:ccp(i,j) vertex:v]; + } + } +} + +-(id) copyWithZone: (NSZone*) zone +{ + return [[[self class] allocWithZone:zone] initWithDuration:_duration size:_gridSize waves:_waves amplitude:_amplitude horizontal:_horizontal vertical:_vertical]; +} + +@end + +//////////////////////////////////////////////////////////// + +#pragma mark - +#pragma mark Twirl + +@implementation CCTwirl + +@synthesize amplitude = _amplitude; +@synthesize amplitudeRate = _amplitudeRate; + ++(id)actionWithDuration:(ccTime)duration size:(CGSize)gridSize position:(CGPoint)pos twirls:(NSUInteger)t amplitude:(float)amp +{ + return [[[self alloc] initWithDuration:duration size:gridSize position:pos twirls:t amplitude:amp] autorelease]; +} + +-(id)initWithDuration:(ccTime)duration size:(CGSize)gridSize position:(CGPoint)pos twirls:(NSUInteger)t amplitude:(float)amp +{ + if ( (self = [super initWithDuration:duration size:gridSize]) ) + { + self.position = pos; + _twirls = t; + _amplitude = amp; + _amplitudeRate = 1.0f; + } + + return self; +} + +-(void) setPosition:(CGPoint)pos +{ + _position = pos; +} + +-(CGPoint) position +{ + return _position; +} + +-(void)update:(ccTime)time +{ + int i, j; + CGPoint c = _position; + + for( i = 0; i < (_gridSize.width+1); i++ ) + { + for( j = 0; j < (_gridSize.height+1); j++ ) + { + ccVertex3F v = [self originalVertex:ccp(i,j)]; + + CGPoint avg = ccp(i-(_gridSize.width/2.0f), j-(_gridSize.height/2.0f)); + CGFloat r = ccpLength( avg ); + + CGFloat amp = 0.1f * _amplitude * _amplitudeRate; + CGFloat a = r * cosf( (CGFloat)M_PI/2.0f + time * (CGFloat)M_PI * _twirls * 2 ) * amp; + + float cosA = cosf(a); + float sinA = sinf(a); + + CGPoint d = { + sinA * (v.y-c.y) + cosA * (v.x-c.x), + cosA * (v.y-c.y) - sinA * (v.x-c.x) + }; + + v.x = c.x + d.x; + v.y = c.y + d.y; + + [self setVertex:ccp(i,j) vertex:v]; + } + } +} + +-(id) copyWithZone: (NSZone*) zone +{ + return [[[self class] allocWithZone:zone] initWithDuration:_duration size:_gridSize position:_position twirls:_twirls amplitude:_amplitude]; +} + + +@end diff --git "a/21451198\345\215\242\350\266\205/project5/MyPlane/libs/cocos2d/CCActionInstant.h" "b/21451198\345\215\242\350\266\205/project5/MyPlane/libs/cocos2d/CCActionInstant.h" new file mode 100644 index 00000000..e554380c --- /dev/null +++ "b/21451198\345\215\242\350\266\205/project5/MyPlane/libs/cocos2d/CCActionInstant.h" @@ -0,0 +1,235 @@ +/* + * cocos2d for iPhone: http://www.cocos2d-iphone.org + * + * Copyright (c) 2008-2010 Ricardo Quesada + * Copyright (c) 2011 Zynga Inc. + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + * THE SOFTWARE. + * + */ + + +#import "CCAction.h" + +/** Instant actions are immediate actions. They don't have a duration like + the CCIntervalAction actions. +*/ +@interface CCActionInstant : CCFiniteTimeAction +{ +} +// XXX Needed for BridgeSupport +-(id) init; +@end + +/** Show the node + */ + @interface CCShow : CCActionInstant +{ +} +// XXX Needed for BridgeSupport +-(void) update:(ccTime)time; +@end + +/** Hide the node + */ +@interface CCHide : CCActionInstant +{ +} +-(void) update:(ccTime)time; +@end + +/** Toggles the visibility of a node + */ +@interface CCToggleVisibility : CCActionInstant +{ +} +-(void) update:(ccTime)time; +@end + +/** Flips the sprite horizontally + @since v0.99.0 + */ +@interface CCFlipX : CCActionInstant +{ + BOOL _flipX; +} ++(id) actionWithFlipX:(BOOL)x; +-(id) initWithFlipX:(BOOL)x; +@end + +/** Flips the sprite vertically + @since v0.99.0 + */ +@interface CCFlipY : CCActionInstant +{ + BOOL _flipY; +} ++(id) actionWithFlipY:(BOOL)y; +-(id) initWithFlipY:(BOOL)y; +@end + +/** Places the node in a certain position + */ +@interface CCPlace : CCActionInstant +{ + CGPoint _position; +} +/** creates a Place action with a position */ ++(id) actionWithPosition: (CGPoint) pos; +/** Initializes a Place action with a position */ +-(id) initWithPosition: (CGPoint) pos; +@end + +/** Calls a 'callback' + */ +@interface CCCallFunc : CCActionInstant +{ + id _targetCallback; + SEL _selector; +} + +/** Target that will be called */ +@property (nonatomic, readwrite, retain) id targetCallback; + +/** creates the action with the callback */ ++(id) actionWithTarget: (id) t selector:(SEL) s; +/** initializes the action with the callback */ +-(id) initWithTarget: (id) t selector:(SEL) s; +/** executes the callback */ +-(void) execute; +@end + +/** Calls a 'callback' with the node as the first argument. + N means Node + */ +@interface CCCallFuncN : CCCallFunc +{ +} +// XXX: Needed for BridgeSupport +-(void) execute; +@end + +typedef void (*CC_CALLBACK_ND)(id, SEL, id, void *); +/** Calls a 'callback' with the node as the first argument and the 2nd argument is data. + * ND means: Node and Data. Data is void *, so it could be anything. + */ +@interface CCCallFuncND : CCCallFuncN +{ + void *_data; + CC_CALLBACK_ND _callbackMethod; +} + +/** Invocation object that has the target#selector and the parameters */ +@property (nonatomic,readwrite) CC_CALLBACK_ND callbackMethod; + +/** creates the action with the callback and the data to pass as an argument */ ++(id) actionWithTarget: (id) t selector:(SEL) s data:(void*)d; +/** initializes the action with the callback and the data to pass as an argument */ +-(id) initWithTarget:(id) t selector:(SEL) s data:(void*) d; +@end + +/** Calls a 'callback' with an object as the first argument. + O means Object. + @since v0.99.5 + */ +@interface CCCallFuncO : CCCallFunc +{ + id _object; +} +/** object to be passed as argument */ +@property (nonatomic, readwrite, retain) id object; + +/** creates the action with the callback and the object to pass as an argument */ ++(id) actionWithTarget: (id) t selector:(SEL) s object:(id)object; +/** initializes the action with the callback and the object to pass as an argument */ +-(id) initWithTarget:(id) t selector:(SEL) s object:(id)object; + +@end + +#pragma mark Blocks Support + +/** Executes a callback using a block. + */ +@interface CCCallBlock : CCActionInstant +{ + void (^_block)(); +} + +/** creates the action with the specified block, to be used as a callback. + The block will be "copied". + */ ++(id) actionWithBlock:(void(^)())block; + +/** initialized the action with the specified block, to be used as a callback. + The block will be "copied". + */ +-(id) initWithBlock:(void(^)())block; + +/** executes the callback */ +-(void) execute; +@end + +@class CCNode; + +/** Executes a callback using a block with a single CCNode parameter. + */ +@interface CCCallBlockN : CCActionInstant +{ + void (^_block)(CCNode *); +} + +/** creates the action with the specified block, to be used as a callback. + The block will be "copied". + */ ++(id) actionWithBlock:(void(^)(CCNode *node))block; + +/** initialized the action with the specified block, to be used as a callback. + The block will be "copied". + */ +-(id) initWithBlock:(void(^)(CCNode *node))block; + +/** executes the callback */ +-(void) execute; +@end + +/** Executes a callback using a block with a single NSObject parameter. + @since v2.0 + */ +@interface CCCallBlockO : CCActionInstant +{ + void (^_block)(id object); + id _object; +} + +/** object to be passed to the block */ +@property (nonatomic,retain) id object; + +/** creates the action with the specified block, to be used as a callback. + The block will be "copied". + */ ++(id) actionWithBlock:(void(^)(id object))block object:(id)object; + +/** initialized the action with the specified block, to be used as a callback. + The block will be "copied". + */ +-(id) initWithBlock:(void(^)(id object))block object:(id)object; + +/** executes the callback */ +-(void) execute; +@end diff --git "a/21451198\345\215\242\350\266\205/project5/MyPlane/libs/cocos2d/CCActionInstant.m" "b/21451198\345\215\242\350\266\205/project5/MyPlane/libs/cocos2d/CCActionInstant.m" new file mode 100644 index 00000000..5275da38 --- /dev/null +++ "b/21451198\345\215\242\350\266\205/project5/MyPlane/libs/cocos2d/CCActionInstant.m" @@ -0,0 +1,509 @@ +/* + * cocos2d for iPhone: http://www.cocos2d-iphone.org + * + * Copyright (c) 2008-2010 Ricardo Quesada + * Copyright (c) 2011 Zynga Inc. + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + * THE SOFTWARE. + * + */ + + +#import "CCActionInstant.h" +#import "CCNode.h" +#import "CCSprite.h" + + +// +// InstantAction +// +#pragma mark CCActionInstant + +@implementation CCActionInstant + +-(id) init +{ + if( (self=[super init]) ) + _duration = 0; + + return self; +} + +-(id) copyWithZone: (NSZone*) zone +{ + CCActionInstant *copy = [[[self class] allocWithZone: zone] init]; + return copy; +} + +- (BOOL) isDone +{ + return YES; +} + +-(void) step: (ccTime) dt +{ + [self update: 1]; +} + +-(void) update: (ccTime) t +{ + // nothing +} + +-(CCFiniteTimeAction*) reverse +{ + return [[self copy] autorelease]; +} +@end + +// +// Show +// +#pragma mark CCShow + +@implementation CCShow +-(void) update:(ccTime)time +{ + ((CCNode *)_target).visible = YES; +} + +-(CCFiniteTimeAction*) reverse +{ + return [CCHide action]; +} +@end + +// +// Hide +// +#pragma mark CCHide + +@implementation CCHide +-(void) update:(ccTime)time +{ + ((CCNode *)_target).visible = NO; +} + +-(CCFiniteTimeAction*) reverse +{ + return [CCShow action]; +} +@end + +// +// ToggleVisibility +// +#pragma mark CCToggleVisibility + +@implementation CCToggleVisibility +-(void) update:(ccTime)time +{ + ((CCNode *)_target).visible = !((CCNode *)_target).visible; +} +@end + +// +// FlipX +// +#pragma mark CCFlipX + +@implementation CCFlipX ++(id) actionWithFlipX:(BOOL)x +{ + return [[[self alloc] initWithFlipX:x] autorelease]; +} + +-(id) initWithFlipX:(BOOL)x +{ + if(( self=[super init])) + _flipX = x; + + return self; +} + +-(void) update:(ccTime)time +{ + [(CCSprite*)_target setFlipX:_flipX]; +} + +-(CCFiniteTimeAction*) reverse +{ + return [CCFlipX actionWithFlipX:!_flipX]; +} + +-(id) copyWithZone: (NSZone*) zone +{ + CCActionInstant *copy = [[[self class] allocWithZone: zone] initWithFlipX:_flipX]; + return copy; +} +@end + +// +// FlipY +// +#pragma mark CCFlipY + +@implementation CCFlipY ++(id) actionWithFlipY:(BOOL)y +{ + return [[[self alloc] initWithFlipY:y] autorelease]; +} + +-(id) initWithFlipY:(BOOL)y +{ + if(( self=[super init])) + _flipY = y; + + return self; +} + +-(void) update:(ccTime)time +{ + [(CCSprite*)_target setFlipY:_flipY]; +} + +-(CCFiniteTimeAction*) reverse +{ + return [CCFlipY actionWithFlipY:!_flipY]; +} + +-(id) copyWithZone: (NSZone*) zone +{ + CCActionInstant *copy = [[[self class] allocWithZone: zone] initWithFlipY:_flipY]; + return copy; +} +@end + + +// +// Place +// +#pragma mark CCPlace + +@implementation CCPlace ++(id) actionWithPosition: (CGPoint) pos +{ + return [[[self alloc]initWithPosition:pos]autorelease]; +} + +-(id) initWithPosition: (CGPoint) pos +{ + if( (self=[super init]) ) + _position = pos; + + return self; +} + +-(id) copyWithZone: (NSZone*) zone +{ + CCActionInstant *copy = [[[self class] allocWithZone: zone] initWithPosition: _position]; + return copy; +} + +-(void) update:(ccTime)time +{ + ((CCNode *)_target).position = _position; +} + +@end + +// +// CallFunc +// +#pragma mark CCCallFunc + +@implementation CCCallFunc + +@synthesize targetCallback = _targetCallback; + ++(id) actionWithTarget: (id) t selector:(SEL) s +{ + return [[[self alloc] initWithTarget: t selector: s] autorelease]; +} + +-(id) initWithTarget: (id) t selector:(SEL) s +{ + if( (self=[super init]) ) { + self.targetCallback = t; + _selector = s; + } + return self; +} + +-(NSString*) description +{ + return [NSString stringWithFormat:@"<%@ = %p | Tag = %ld | selector = %@>", + [self class], + self, + (long)_tag, + NSStringFromSelector(_selector) + ]; +} + +-(void) dealloc +{ + [_targetCallback release]; + [super dealloc]; +} + +-(id) copyWithZone: (NSZone*) zone +{ + CCActionInstant *copy = [[[self class] allocWithZone: zone] initWithTarget:_targetCallback selector:_selector]; + return copy; +} + +-(void) update:(ccTime)time +{ + [self execute]; +} + +-(void) execute +{ + [_targetCallback performSelector:_selector]; +} +@end + +// +// CallFuncN +// +#pragma mark CCCallFuncN + +@implementation CCCallFuncN + +-(void) execute +{ + [_targetCallback performSelector:_selector withObject:_target]; +} +@end + +// +// CallFuncND +// +#pragma mark CCCallFuncND + +@implementation CCCallFuncND + +@synthesize callbackMethod = _callbackMethod; + ++(id) actionWithTarget:(id)t selector:(SEL)s data:(void*)d +{ + return [[[self alloc] initWithTarget:t selector:s data:d] autorelease]; +} + +-(id) initWithTarget:(id)t selector:(SEL)s data:(void*)d +{ + if( (self=[super initWithTarget:t selector:s]) ) { + _data = d; + +#if COCOS2D_DEBUG + NSMethodSignature * sig = [t methodSignatureForSelector:s]; // added + NSAssert(sig !=0 , @"Signature not found for selector - does it have the following form? -(void)name:(id)sender data:(void*)data"); +#endif + _callbackMethod = (CC_CALLBACK_ND) [t methodForSelector:s]; + } + return self; +} + +-(id) copyWithZone: (NSZone*) zone +{ + CCActionInstant *copy = [[[self class] allocWithZone: zone] initWithTarget:_targetCallback selector:_selector data:_data]; + return copy; +} + +-(void) dealloc +{ + // nothing to dealloc really. Everything is dealloc on super (CCCallFuncN) + [super dealloc]; +} + +-(void) execute +{ + _callbackMethod(_targetCallback,_selector,_target, _data); +} +@end + +@implementation CCCallFuncO +@synthesize object = _object; + ++(id) actionWithTarget: (id) t selector:(SEL) s object:(id)object +{ + return [[[self alloc] initWithTarget:t selector:s object:object] autorelease]; +} + +-(id) initWithTarget:(id) t selector:(SEL) s object:(id)object +{ + if( (self=[super initWithTarget:t selector:s] ) ) + self.object = object; + + return self; +} + +- (void) dealloc +{ + [_object release]; + [super dealloc]; +} + +-(id) copyWithZone: (NSZone*) zone +{ + CCActionInstant *copy = [[[self class] allocWithZone: zone] initWithTarget:_targetCallback selector:_selector object:_object]; + return copy; +} + + +-(void) execute +{ + [_targetCallback performSelector:_selector withObject:_object]; +} + +@end + + +#pragma mark - +#pragma mark Blocks + +#pragma mark CCCallBlock + +@implementation CCCallBlock + ++(id) actionWithBlock:(void(^)())block +{ + return [[[self alloc] initWithBlock:block] autorelease]; +} + +-(id) initWithBlock:(void(^)())block +{ + if ((self = [super init])) + _block = [block copy]; + + return self; +} + +-(id) copyWithZone: (NSZone*) zone +{ + CCActionInstant *copy = [[[self class] allocWithZone: zone] initWithBlock:_block]; + return copy; +} + +-(void) update:(ccTime)time +{ + [self execute]; +} + +-(void) execute +{ + _block(); +} + +-(void) dealloc +{ + [_block release]; + [super dealloc]; +} + +@end + +#pragma mark CCCallBlockN + +@implementation CCCallBlockN + ++(id) actionWithBlock:(void(^)(CCNode *node))block +{ + return [[[self alloc] initWithBlock:block] autorelease]; +} + +-(id) initWithBlock:(void(^)(CCNode *node))block +{ + if ((self = [super init])) + _block = [block copy]; + + return self; +} + +-(id) copyWithZone: (NSZone*) zone +{ + CCActionInstant *copy = [[[self class] allocWithZone: zone] initWithBlock:_block]; + return copy; +} + +-(void) update:(ccTime)time +{ + [self execute]; +} + +-(void) execute +{ + _block(_target); +} + +-(void) dealloc +{ + [_block release]; + [super dealloc]; +} + +@end + +#pragma mark CCCallBlockO + +@implementation CCCallBlockO + +@synthesize object=_object; + ++(id) actionWithBlock:(void(^)(id object))block object:(id)object +{ + return [[[self alloc] initWithBlock:block object:object] autorelease]; +} + +-(id) initWithBlock:(void(^)(id object))block object:(id)object +{ + if ((self = [super init])) { + _block = [block copy]; + _object = [object retain]; + } + + return self; +} + +-(id) copyWithZone: (NSZone*) zone +{ + CCActionInstant *copy = [[[self class] allocWithZone: zone] initWithBlock:_block]; + return copy; +} + +-(void) update:(ccTime)time +{ + [self execute]; +} + +-(void) execute +{ + _block(_object); +} + +-(void) dealloc +{ + [_object release]; + [_block release]; + + [super dealloc]; +} + +@end + diff --git "a/21451198\345\215\242\350\266\205/project5/MyPlane/libs/cocos2d/CCActionInterval.h" "b/21451198\345\215\242\350\266\205/project5/MyPlane/libs/cocos2d/CCActionInterval.h" new file mode 100644 index 00000000..d5d4ee35 --- /dev/null +++ "b/21451198\345\215\242\350\266\205/project5/MyPlane/libs/cocos2d/CCActionInterval.h" @@ -0,0 +1,473 @@ +/* + * cocos2d for iPhone: http://www.cocos2d-iphone.org + * + * Copyright (c) 2008-2011 Ricardo Quesada + * Copyright (c) 2011 Zynga Inc. + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + * THE SOFTWARE. + * + */ + + +#import "CCNode.h" +#import "CCAction.h" +#import "CCProtocols.h" + +#include + +/** An interval action is an action that takes place within a certain period of time. +It has an start time, and a finish time. The finish time is the parameter +duration plus the start time. + +These CCActionInterval actions have some interesting properties, like: + - They can run normally (default) + - They can run reversed with the reverse method + - They can run with the time altered with the Accelerate, AccelDeccel and Speed actions. + +For example, you can simulate a Ping Pong effect running the action normally and +then running it again in Reverse mode. + +Example: + + CCAction * pingPongAction = [CCSequence actions: action, [action reverse], nil]; +*/ +@interface CCActionInterval: CCFiniteTimeAction +{ + ccTime _elapsed; + BOOL _firstTick; +} + +/** how many seconds had elapsed since the actions started to run. */ +@property (nonatomic,readonly) ccTime elapsed; + +/** creates the action */ ++(id) actionWithDuration: (ccTime) d; +/** initializes the action */ +-(id) initWithDuration: (ccTime) d; +/** returns YES if the action has finished */ +-(BOOL) isDone; +/** returns a reversed action */ +- (CCActionInterval*) reverse; +@end + +/** Runs actions sequentially, one after another + */ +@interface CCSequence : CCActionInterval +{ + CCFiniteTimeAction *_actions[2]; + ccTime _split; + int _last; +} +/** helper constructor to create an array of sequence-able actions */ ++(id) actions: (CCFiniteTimeAction*) action1, ... NS_REQUIRES_NIL_TERMINATION; +/** helper constructor to create an array of sequence-able actions */ ++(id) actions: (CCFiniteTimeAction*) action1 vaList:(va_list) args; +/** helper constructor to create an array of sequence-able actions given an array */ ++(id) actionWithArray: (NSArray*) arrayOfActions; +/** creates the action */ ++(id) actionOne:(CCFiniteTimeAction*)actionOne two:(CCFiniteTimeAction*)actionTwo; +/** initializes the action */ +-(id) initOne:(CCFiniteTimeAction*)actionOne two:(CCFiniteTimeAction*)actionTwo; +@end + + +/** Repeats an action a number of times. + * To repeat an action forever use the CCRepeatForever action. + */ +@interface CCRepeat : CCActionInterval +{ + NSUInteger _times; + NSUInteger _total; + ccTime _nextDt; + BOOL _isActionInstant; + CCFiniteTimeAction *_innerAction; +} + +/** Inner action */ +@property (nonatomic,readwrite,retain) CCFiniteTimeAction *innerAction; + +/** creates a CCRepeat action. Times is an unsigned integer between 1 and MAX_UINT. + */ ++(id) actionWithAction:(CCFiniteTimeAction*)action times: (NSUInteger)times; +/** initializes a CCRepeat action. Times is an unsigned integer between 1 and MAX_UINT */ +-(id) initWithAction:(CCFiniteTimeAction*)action times: (NSUInteger)times; +@end + +/** Spawn a new action immediately + */ +@interface CCSpawn : CCActionInterval +{ + CCFiniteTimeAction *_one; + CCFiniteTimeAction *_two; +} +/** helper constructor to create an array of spawned actions */ ++(id) actions: (CCFiniteTimeAction*) action1, ... NS_REQUIRES_NIL_TERMINATION; +/** helper constructor to create an array of spawned actions */ ++(id) actions: (CCFiniteTimeAction*) action1 vaList:(va_list)args; +/** helper constructor to create an array of spawned actions given an array */ ++(id) actionWithArray: (NSArray*) arrayOfActions; +/** creates the Spawn action */ ++(id) actionOne: (CCFiniteTimeAction*) one two:(CCFiniteTimeAction*) two; +/** initializes the Spawn action with the 2 actions to spawn */ +-(id) initOne: (CCFiniteTimeAction*) one two:(CCFiniteTimeAction*) two; +@end + +/** Rotates a CCNode object to a certain angle by modifying it's + rotation attribute. + The direction will be decided by the shortest angle. +*/ +@interface CCRotateTo : CCActionInterval +{ + float _dstAngleX; + float _startAngleX; + float _diffAngleX; + + float _dstAngleY; + float _startAngleY; + float _diffAngleY; +} +/** creates the action */ ++(id) actionWithDuration:(ccTime)duration angle:(float)angle; +/** initializes the action */ +-(id) initWithDuration:(ccTime)duration angle:(float)angle; + +/** creates the action with separate rotation angles */ ++(id) actionWithDuration: (ccTime) t angleX:(float) aX angleY:(float) aY; +-(id) initWithDuration: (ccTime) t angleX:(float) aX angleY:(float) aY; +@end + +/** Rotates a CCNode object clockwise a number of degrees by modifying its rotation attribute. +*/ +@interface CCRotateBy : CCActionInterval +{ + float _angleX; + float _startAngleX; + float _angleY; + float _startAngleY; +} +/** creates the action */ ++(id) actionWithDuration:(ccTime)duration angle:(float)deltaAngle; +/** initializes the action */ +-(id) initWithDuration:(ccTime)duration angle:(float)deltaAngle; + +/** creates the action with separate rotation angles */ ++(id) actionWithDuration: (ccTime) t angleX:(float) aX angleY:(float) aY; +-(id) initWithDuration: (ccTime) t angleX:(float) aX angleY:(float) aY; +@end + +/** Moves a CCNode object x,y pixels by modifying it's position attribute. + x and y are relative to the position of the object. + Several CCMoveBy actions can be concurrently called, and the resulting + movement will be the sum of individual movements. + @since v2.1beta2-custom + */ +@interface CCMoveBy : CCActionInterval +{ + CGPoint _positionDelta; + CGPoint _startPos; + CGPoint _previousPos; +} +/** creates the action */ ++(id) actionWithDuration: (ccTime)duration position:(CGPoint)deltaPosition; +/** initializes the action */ +-(id) initWithDuration: (ccTime)duration position:(CGPoint)deltaPosition; +@end + +/** Moves a CCNode object to the position x,y. x and y are absolute coordinates by modifying it's position attribute. + Several CCMoveTo actions can be concurrently called, and the resulting + movement will be the sum of individual movements. + @since v2.1beta2-custom + */ +@interface CCMoveTo : CCMoveBy +{ + CGPoint _endPosition; +} +/** creates the action */ ++(id) actionWithDuration:(ccTime)duration position:(CGPoint)position; +/** initializes the action */ +-(id) initWithDuration:(ccTime)duration position:(CGPoint)position; +@end + +/** Skews a CCNode object to given angles by modifying its skewX and skewY attributes + @since v1.0 + */ +@interface CCSkewTo : CCActionInterval +{ + float _skewX; + float _skewY; + float _startSkewX; + float _startSkewY; + float _endSkewX; + float _endSkewY; + float _deltaX; + float _deltaY; +} +/** creates the action */ ++(id) actionWithDuration:(ccTime)t skewX:(float)sx skewY:(float)sy; +/** initializes the action with duration, skew X and skew Y */ +-(id) initWithDuration:(ccTime)t skewX:(float)sx skewY:(float)sy; +@end + +/** Skews a CCNode object by skewX and skewY degrees + @since v1.0 + */ +@interface CCSkewBy : CCSkewTo +{ +} +/** initializes the action with duration, skew X and skew Y */ +-(id) initWithDuration:(ccTime)t skewX:(float)sx skewY:(float)sy; +@end + +/** Moves a CCNode object simulating a parabolic jump movement by modifying its position attribute. +*/ +@interface CCJumpBy : CCActionInterval +{ + CGPoint _startPosition; + CGPoint _delta; + ccTime _height; + NSUInteger _jumps; + CGPoint _previousPos; +} +/** creates the action */ ++(id) actionWithDuration: (ccTime)duration position:(CGPoint)position height:(ccTime)height jumps:(NSUInteger)jumps; +/** initializes the action */ +-(id) initWithDuration: (ccTime)duration position:(CGPoint)position height:(ccTime)height jumps:(NSUInteger)jumps; +@end + +/** Moves a CCNode object to a parabolic position simulating a jump movement by modifying its position attribute. +*/ +@interface CCJumpTo : CCJumpBy +{ +} +// XXX: Added to prevent bug on BridgeSupport +-(void) startWithTarget:(CCNode *)aTarget; +@end + +/** bezier configuration structure + */ +typedef struct _ccBezierConfig { + //! end position of the bezier + CGPoint endPosition; + //! Bezier control point 1 + CGPoint controlPoint_1; + //! Bezier control point 2 + CGPoint controlPoint_2; +} ccBezierConfig; + +/** An action that moves the target with a cubic Bezier curve by a certain distance. + */ +@interface CCBezierBy : CCActionInterval +{ + ccBezierConfig _config; + CGPoint _startPosition; + CGPoint _previousPosition; +} + +/** creates the action with a duration and a bezier configuration */ ++(id) actionWithDuration: (ccTime) t bezier:(ccBezierConfig) c; + +/** initializes the action with a duration and a bezier configuration */ +-(id) initWithDuration: (ccTime) t bezier:(ccBezierConfig) c; +@end + +/** An action that moves the target with a cubic Bezier curve to a destination point. + @since v0.8.2 + */ +@interface CCBezierTo : CCBezierBy +{ + ccBezierConfig _toConfig; +} +// XXX: Added to prevent bug on BridgeSupport +-(void) startWithTarget:(CCNode *)aTarget; +@end + +/** Scales a CCNode object to a zoom factor by modifying its scale attribute. + @warning This action doesn't support "reverse" + */ +@interface CCScaleTo : CCActionInterval +{ + float _scaleX; + float _scaleY; + float _startScaleX; + float _startScaleY; + float _endScaleX; + float _endScaleY; + float _deltaX; + float _deltaY; +} +/** creates the action with the same scale factor for X and Y */ ++(id) actionWithDuration: (ccTime)duration scale:(float) s; +/** initializes the action with the same scale factor for X and Y */ +-(id) initWithDuration: (ccTime)duration scale:(float) s; +/** creates the action with and X factor and a Y factor */ ++(id) actionWithDuration: (ccTime)duration scaleX:(float) sx scaleY:(float)sy; +/** initializes the action with and X factor and a Y factor */ +-(id) initWithDuration: (ccTime)duration scaleX:(float) sx scaleY:(float)sy; +@end + +/** Scales a CCNode object a zoom factor by modifying its scale attribute. +*/ +@interface CCScaleBy : CCScaleTo +{ +} +// XXX: Added to prevent bug on BridgeSupport +-(void) startWithTarget:(CCNode *)aTarget; +@end + +/** Blinks a CCNode object by modifying its visible attribute +*/ +@interface CCBlink : CCActionInterval +{ + NSUInteger _times; + BOOL _originalState; +} +/** creates the action */ ++(id) actionWithDuration: (ccTime)duration blinks:(NSUInteger)blinks; +/** initializes the action */ +-(id) initWithDuration: (ccTime)duration blinks:(NSUInteger)blinks; +@end + +/** Fades In an object that implements the CCRGBAProtocol protocol. It modifies the opacity from 0 to 255. + The "reverse" of this action is FadeOut + */ +@interface CCFadeIn : CCActionInterval +{ +} +// XXX: Added to prevent bug on BridgeSupport +-(void) update:(ccTime)dt; +@end + +/** Fades Out an object that implements the CCRGBAProtocol protocol. It modifies the opacity from 255 to 0. + The "reverse" of this action is FadeIn +*/ +@interface CCFadeOut : CCActionInterval +{ +} +// XXX: Added to prevent bug on BridgeSupport +-(void) update:(ccTime)dt; +@end + +/** Fades an object that implements the CCRGBAProtocol protocol. It modifies the opacity from the current value to a custom one. + @warning This action doesn't support "reverse" + */ +@interface CCFadeTo : CCActionInterval +{ + GLubyte _toOpacity; + GLubyte _fromOpacity; +} +/** creates an action with duration and opacity */ ++(id) actionWithDuration:(ccTime)duration opacity:(GLubyte)opactiy; +/** initializes the action with duration and opacity */ +-(id) initWithDuration:(ccTime)duration opacity:(GLubyte)opacity; +@end + +/** Tints a CCNode that implements the CCNodeRGB protocol from current tint to a custom one. + @warning This action doesn't support "reverse" + @since v0.7.2 +*/ +@interface CCTintTo : CCActionInterval +{ + ccColor3B _to; + ccColor3B _from; +} +/** creates an action with duration and color */ ++(id) actionWithDuration:(ccTime)duration red:(GLubyte)red green:(GLubyte)green blue:(GLubyte)blue; +/** initializes the action with duration and color */ +-(id) initWithDuration:(ccTime)duration red:(GLubyte)red green:(GLubyte)green blue:(GLubyte)blue; +@end + +/** Tints a CCNode that implements the CCNodeRGB protocol from current tint to a custom one. + @since v0.7.2 + */ +@interface CCTintBy : CCActionInterval +{ + GLshort _deltaR, _deltaG, _deltaB; + GLshort _fromR, _fromG, _fromB; +} +/** creates an action with duration and color */ ++(id) actionWithDuration:(ccTime)duration red:(GLshort)deltaRed green:(GLshort)deltaGreen blue:(GLshort)deltaBlue; +/** initializes the action with duration and color */ +-(id) initWithDuration:(ccTime)duration red:(GLshort)deltaRed green:(GLshort)deltaGreen blue:(GLshort)deltaBlue; +@end + +/** Delays the action a certain amount of seconds +*/ +@interface CCDelayTime : CCActionInterval +{ +} +// XXX: Added to prevent bug on BridgeSupport +-(void) update:(ccTime)dt; +@end + +/** Executes an action in reverse order, from time=duration to time=0 + + @warning Use this action carefully. This action is not + sequence-able. Use it as the default "reversed" method + of your own actions, but using it outside the "reversed" + scope is not recommended. +*/ +@interface CCReverseTime : CCActionInterval +{ + CCFiniteTimeAction * _other; +} +/** creates the action */ ++(id) actionWithAction: (CCFiniteTimeAction*) action; +/** initializes the action */ +-(id) initWithAction: (CCFiniteTimeAction*) action; +@end + + +@class CCAnimation; +@class CCTexture2D; +/** Animates a sprite given the name of an Animation */ +@interface CCAnimate : CCActionInterval +{ + NSMutableArray *_splitTimes; + NSInteger _nextFrame; + CCAnimation *_animation; + id _origFrame; + NSUInteger _executedLoops; +} +/** animation used for the image */ +@property (readwrite,nonatomic,retain) CCAnimation * animation; + +/** creates the action with an Animation and will restore the original frame when the animation is over */ ++(id) actionWithAnimation:(CCAnimation*)animation; +/** initializes the action with an Animation and will restore the original frame when the animation is over */ +-(id) initWithAnimation:(CCAnimation*)animation; +@end + +/** Overrides the target of an action so that it always runs on the target + * specified at action creation rather than the one specified by runAction. + */ +@interface CCTargetedAction : CCActionInterval +{ + id _forcedTarget; + CCFiniteTimeAction* _action; +} +/** This is the target that the action will be forced to run with */ +@property(readwrite,nonatomic,retain) id forcedTarget; + +/** Create an action with the specified action and forced target */ ++ (id) actionWithTarget:(id) target action:(CCFiniteTimeAction*) action; + +/** Init an action with the specified action and forced target */ +- (id) initWithTarget:(id) target action:(CCFiniteTimeAction*) action; + +@end diff --git "a/21451198\345\215\242\350\266\205/project5/MyPlane/libs/cocos2d/CCActionInterval.m" "b/21451198\345\215\242\350\266\205/project5/MyPlane/libs/cocos2d/CCActionInterval.m" new file mode 100644 index 00000000..503ddd27 --- /dev/null +++ "b/21451198\345\215\242\350\266\205/project5/MyPlane/libs/cocos2d/CCActionInterval.m" @@ -0,0 +1,1585 @@ +/* + * cocos2d for iPhone: http://www.cocos2d-iphone.org + * + * Copyright (c) 2008-2011 Ricardo Quesada + * Copyright (c) 2011 Zynga Inc. + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + * THE SOFTWARE. + * + */ + + + +#import "CCActionInterval.h" +#import "CCActionInstant.h" +#import "CCSprite.h" +#import "CCSpriteFrame.h" +#import "CCAnimation.h" +#import "CCNode.h" +#import "Support/CGPointExtension.h" + +// +// IntervalAction +// +#pragma mark - CCIntervalAction +@implementation CCActionInterval + +@synthesize elapsed = _elapsed; + +-(id) init +{ + NSAssert(NO, @"IntervalActionInit: Init not supported. Use InitWithDuration"); + [self release]; + return nil; +} + ++(id) actionWithDuration: (ccTime) d +{ + return [[[self alloc] initWithDuration:d ] autorelease]; +} + +-(id) initWithDuration: (ccTime) d +{ + if( (self=[super init]) ) { + _duration = d; + + // prevent division by 0 + // This comparison could be in step:, but it might decrease the performance + // by 3% in heavy based action games. + if( _duration == 0 ) + _duration = FLT_EPSILON; + _elapsed = 0; + _firstTick = YES; + } + return self; +} + +-(id) copyWithZone: (NSZone*) zone +{ + CCAction *copy = [[[self class] allocWithZone: zone] initWithDuration: [self duration] ]; + return copy; +} + +- (BOOL) isDone +{ + return (_elapsed >= _duration); +} + +-(void) step: (ccTime) dt +{ + if( _firstTick ) { + _firstTick = NO; + _elapsed = 0; + } else + _elapsed += dt; + + + [self update: MAX(0, // needed for rewind. elapsed could be negative + MIN(1, _elapsed/ + MAX(_duration,FLT_EPSILON) // division by 0 + ) + ) + ]; +} + +-(void) startWithTarget:(id)aTarget +{ + [super startWithTarget:aTarget]; + _elapsed = 0.0f; + _firstTick = YES; +} + +- (CCActionInterval*) reverse +{ + NSAssert(NO, @"CCIntervalAction: reverse not implemented."); + return nil; +} +@end + +// +// Sequence +// +#pragma mark - CCSequence +@implementation CCSequence ++(id) actions: (CCFiniteTimeAction*) action1, ... +{ + va_list args; + va_start(args, action1); + + id ret = [self actions:action1 vaList:args]; + + va_end(args); + + return ret; +} + ++(id) actions: (CCFiniteTimeAction*) action1 vaList:(va_list)args +{ + CCFiniteTimeAction *now; + CCFiniteTimeAction *prev = action1; + + while( action1 ) { + now = va_arg(args,CCFiniteTimeAction*); + if ( now ) + prev = [self actionOne: prev two: now]; + else + break; + } + + return prev; +} + + ++(id) actionWithArray: (NSArray*) actions +{ + CCFiniteTimeAction *prev = [actions objectAtIndex:0]; + + for (NSUInteger i = 1; i < [actions count]; i++) + prev = [self actionOne:prev two:[actions objectAtIndex:i]]; + + return prev; +} + ++(id) actionOne: (CCFiniteTimeAction*) one two: (CCFiniteTimeAction*) two +{ + return [[[self alloc] initOne:one two:two ] autorelease]; +} + +-(id) initOne: (CCFiniteTimeAction*) one two: (CCFiniteTimeAction*) two +{ + NSAssert( one!=nil && two!=nil, @"Sequence: arguments must be non-nil"); + NSAssert( one!=_actions[0] && one!=_actions[1], @"Sequence: re-init using the same parameters is not supported"); + NSAssert( two!=_actions[1] && two!=_actions[0], @"Sequence: re-init using the same parameters is not supported"); + + ccTime d = [one duration] + [two duration]; + + if( (self=[super initWithDuration: d]) ) { + + // XXX: Supports re-init without leaking. Fails if one==_one || two==_two + [_actions[0] release]; + [_actions[1] release]; + + _actions[0] = [one retain]; + _actions[1] = [two retain]; + } + + return self; +} + +-(id) copyWithZone: (NSZone*) zone +{ + CCAction *copy = [[[self class] allocWithZone:zone] initOne:[[_actions[0] copy] autorelease] two:[[_actions[1] copy] autorelease] ]; + return copy; +} + +-(void) dealloc +{ + [_actions[0] release]; + [_actions[1] release]; + [super dealloc]; +} + +-(void) startWithTarget:(id)aTarget +{ + [super startWithTarget:aTarget]; + _split = [_actions[0] duration] / MAX(_duration, FLT_EPSILON); + _last = -1; +} + +-(void) stop +{ + // Issue #1305 + if( _last != - 1) + [_actions[_last] stop]; + + [super stop]; +} + +-(void) update: (ccTime) t +{ + + int found = 0; + ccTime new_t = 0.0f; + + if( t < _split ) { + // action[0] + found = 0; + if( _split != 0 ) + new_t = t / _split; + else + new_t = 1; + + } else { + // action[1] + found = 1; + if ( _split == 1 ) + new_t = 1; + else + new_t = (t-_split) / (1 - _split ); + } + + if ( found==1 ) { + + if( _last == -1 ) { + // action[0] was skipped, execute it. + [_actions[0] startWithTarget:_target]; + [_actions[0] update:1.0f]; + [_actions[0] stop]; + } + else if( _last == 0 ) + { + // switching to action 1. stop action 0. + [_actions[0] update: 1.0f]; + [_actions[0] stop]; + } + } + else if(found==0 && _last==1 ) + { + // Reverse mode ? + // XXX: Bug. this case doesn't contemplate when _last==-1, found=0 and in "reverse mode" + // since it will require a hack to know if an action is on reverse mode or not. + // "step" should be overriden, and the "reverseMode" value propagated to inner Sequences. + [_actions[1] update:0]; + [_actions[1] stop]; + } + + // Last action found and it is done. + if( found == _last && [_actions[found] isDone] ) { + return; + } + + // New action. Start it. + if( found != _last ) + [_actions[found] startWithTarget:_target]; + + [_actions[found] update: new_t]; + _last = found; +} + +- (CCActionInterval *) reverse +{ + return [[self class] actionOne: [_actions[1] reverse] two: [_actions[0] reverse ] ]; +} +@end + +// +// Repeat +// +#pragma mark - CCRepeat +@implementation CCRepeat +@synthesize innerAction=_innerAction; + ++(id) actionWithAction:(CCFiniteTimeAction*)action times:(NSUInteger)times +{ + return [[[self alloc] initWithAction:action times:times] autorelease]; +} + +-(id) initWithAction:(CCFiniteTimeAction*)action times:(NSUInteger)times +{ + ccTime d = [action duration] * times; + + if( (self=[super initWithDuration: d ]) ) { + _times = times; + self.innerAction = action; + _isActionInstant = ([action isKindOfClass:[CCActionInstant class]]) ? YES : NO; + + //a instant action needs to be executed one time less in the update method since it uses startWithTarget to execute the action + if (_isActionInstant) _times -=1; + _total = 0; + } + return self; +} + +-(id) copyWithZone: (NSZone*) zone +{ + CCAction *copy = [[[self class] allocWithZone:zone] initWithAction:[[_innerAction copy] autorelease] times:_times]; + return copy; +} + +-(void) dealloc +{ + [_innerAction release]; + [super dealloc]; +} + +-(void) startWithTarget:(id)aTarget +{ + _total = 0; + _nextDt = [_innerAction duration]/_duration; + [super startWithTarget:aTarget]; + [_innerAction startWithTarget:aTarget]; +} + +-(void) stop +{ + [_innerAction stop]; + [super stop]; +} + + +// issue #80. Instead of hooking step:, hook update: since it can be called by any +// container action like CCRepeat, CCSequence, CCEase, etc.. +-(void) update:(ccTime) dt +{ + if (dt >= _nextDt) + { + while (dt > _nextDt && _total < _times) + { + + [_innerAction update:1.0f]; + _total++; + + [_innerAction stop]; + [_innerAction startWithTarget:_target]; + _nextDt += [_innerAction duration]/_duration; + } + + // fix for issue #1288, incorrect end value of repeat + if(dt >= 1.0f && _total < _times) + { + _total++; + } + + // don't set a instantaction back or update it, it has no use because it has no duration + if (!_isActionInstant) + { + if (_total == _times) + { + [_innerAction update:1]; + [_innerAction stop]; + } + else + { + // issue #390 prevent jerk, use right update + [_innerAction update:dt - (_nextDt - _innerAction.duration/_duration)]; + } + } + } + else + { + [_innerAction update:fmodf(dt * _times,1.0f)]; + } +} + +-(BOOL) isDone +{ + return ( _total == _times ); +} + +- (CCActionInterval *) reverse +{ + return [[self class] actionWithAction:[_innerAction reverse] times:_times]; +} +@end + +// +// Spawn +// +#pragma mark - CCSpawn + +@implementation CCSpawn ++(id) actions: (CCFiniteTimeAction*) action1, ... +{ + va_list args; + va_start(args, action1); + + id ret = [self actions:action1 vaList:args]; + + va_end(args); + return ret; +} + ++(id) actions: (CCFiniteTimeAction*) action1 vaList:(va_list)args +{ + CCFiniteTimeAction *now; + CCFiniteTimeAction *prev = action1; + + while( action1 ) { + now = va_arg(args,CCFiniteTimeAction*); + if ( now ) + prev = [self actionOne: prev two: now]; + else + break; + } + + return prev; +} + + ++(id) actionWithArray: (NSArray*) actions +{ + CCFiniteTimeAction *prev = [actions objectAtIndex:0]; + + for (NSUInteger i = 1; i < [actions count]; i++) + prev = [self actionOne:prev two:[actions objectAtIndex:i]]; + + return prev; +} + ++(id) actionOne: (CCFiniteTimeAction*) one two: (CCFiniteTimeAction*) two +{ + return [[[self alloc] initOne:one two:two ] autorelease]; +} + +-(id) initOne: (CCFiniteTimeAction*) one two: (CCFiniteTimeAction*) two +{ + NSAssert( one!=nil && two!=nil, @"Spawn: arguments must be non-nil"); + NSAssert( one!=_one && one!=_two, @"Spawn: reinit using same parameters is not supported"); + NSAssert( two!=_two && two!=_one, @"Spawn: reinit using same parameters is not supported"); + + ccTime d1 = [one duration]; + ccTime d2 = [two duration]; + + if( (self=[super initWithDuration: MAX(d1,d2)] ) ) { + + // XXX: Supports re-init without leaking. Fails if one==_one || two==_two + [_one release]; + [_two release]; + + _one = one; + _two = two; + + if( d1 > d2 ) + _two = [CCSequence actionOne:two two:[CCDelayTime actionWithDuration: (d1-d2)] ]; + else if( d1 < d2) + _one = [CCSequence actionOne:one two: [CCDelayTime actionWithDuration: (d2-d1)] ]; + + [_one retain]; + [_two retain]; + } + return self; +} + +-(id) copyWithZone: (NSZone*) zone +{ + CCAction *copy = [[[self class] allocWithZone: zone] initOne: [[_one copy] autorelease] two: [[_two copy] autorelease] ]; + return copy; +} + +-(void) dealloc +{ + [_one release]; + [_two release]; + [super dealloc]; +} + +-(void) startWithTarget:(id)aTarget +{ + [super startWithTarget:aTarget]; + [_one startWithTarget:_target]; + [_two startWithTarget:_target]; +} + +-(void) stop +{ + [_one stop]; + [_two stop]; + [super stop]; +} + +-(void) update: (ccTime) t +{ + [_one update:t]; + [_two update:t]; +} + +- (CCActionInterval *) reverse +{ + return [[self class] actionOne: [_one reverse] two: [_two reverse ] ]; +} +@end + +// +// RotateTo +// +#pragma mark - CCRotateTo + +@implementation CCRotateTo ++(id) actionWithDuration: (ccTime) t angle:(float) a +{ + return [[[self alloc] initWithDuration:t angle:a ] autorelease]; +} + +-(id) initWithDuration: (ccTime) t angle:(float) a +{ + if( (self=[super initWithDuration: t]) ) + _dstAngleX = _dstAngleY = a; + + return self; +} + ++(id) actionWithDuration: (ccTime) t angleX:(float) aX angleY:(float) aY +{ + return [[[self alloc] initWithDuration:t angleX:aX angleY:aY ] autorelease]; +} + +-(id) initWithDuration: (ccTime) t angleX:(float) aX angleY:(float) aY +{ + if( (self=[super initWithDuration: t]) ){ + _dstAngleX = aX; + _dstAngleY = aY; + } + return self; +} + +-(id) copyWithZone: (NSZone*) zone +{ + CCAction *copy = [[[self class] allocWithZone: zone] initWithDuration:[self duration] angleX:_dstAngleX angleY:_dstAngleY]; + return copy; +} + +-(void) startWithTarget:(CCNode *)aTarget +{ + [super startWithTarget:aTarget]; + + //Calculate X + _startAngleX = [_target rotationX]; + if (_startAngleX > 0) + _startAngleX = fmodf(_startAngleX, 360.0f); + else + _startAngleX = fmodf(_startAngleX, -360.0f); + + _diffAngleX = _dstAngleX - _startAngleX; + if (_diffAngleX > 180) + _diffAngleX -= 360; + if (_diffAngleX < -180) + _diffAngleX += 360; + + + //Calculate Y: It's duplicated from calculating X since the rotation wrap should be the same + _startAngleY = [_target rotationY]; + if (_startAngleY > 0) + _startAngleY = fmodf(_startAngleY, 360.0f); + else + _startAngleY = fmodf(_startAngleY, -360.0f); + + _diffAngleY = _dstAngleY - _startAngleY; + if (_diffAngleY > 180) + _diffAngleY -= 360; + if (_diffAngleY < -180) + _diffAngleY += 360; +} +-(void) update: (ccTime) t +{ + [_target setRotationX: _startAngleX + _diffAngleX * t]; + [_target setRotationY: _startAngleY + _diffAngleY * t]; +} +@end + + +// +// RotateBy +// +#pragma mark - RotateBy + +@implementation CCRotateBy ++(id) actionWithDuration: (ccTime) t angle:(float) a +{ + return [[[self alloc] initWithDuration:t angle:a ] autorelease]; +} + +-(id) initWithDuration: (ccTime) t angle:(float) a +{ + if( (self=[super initWithDuration: t]) ) + _angleX = _angleY = a; + + return self; +} + ++(id) actionWithDuration: (ccTime) t angleX:(float) aX angleY:(float) aY +{ + return [[[self alloc] initWithDuration:t angleX:aX angleY:aY ] autorelease]; +} + +-(id) initWithDuration: (ccTime) t angleX:(float) aX angleY:(float) aY +{ + if( (self=[super initWithDuration: t]) ){ + _angleX = aX; + _angleY = aY; + } + return self; +} + +-(id) copyWithZone: (NSZone*) zone +{ + CCAction *copy = [[[self class] allocWithZone: zone] initWithDuration: [self duration] angleX: _angleX angleY:_angleY]; + return copy; +} + +-(void) startWithTarget:(id)aTarget +{ + [super startWithTarget:aTarget]; + _startAngleX = [_target rotationX]; + _startAngleY = [_target rotationY]; +} + +-(void) update: (ccTime) t +{ + // XXX: shall I add % 360 + [_target setRotationX: (_startAngleX + _angleX * t )]; + [_target setRotationY: (_startAngleY + _angleY * t )]; +} + +-(CCActionInterval*) reverse +{ + return [[self class] actionWithDuration:_duration angleX:-_angleX angleY:-_angleY]; +} + +@end + +// +// MoveBy +// +#pragma mark - MoveBy + +@implementation CCMoveBy ++(id) actionWithDuration: (ccTime) t position: (CGPoint) p +{ + return [[[self alloc] initWithDuration:t position:p ] autorelease]; +} + +-(id) initWithDuration: (ccTime) t position: (CGPoint) p +{ + if( (self=[super initWithDuration: t]) ) + _positionDelta = p; + return self; +} + +-(id) copyWithZone: (NSZone*) zone +{ + return [[[self class] allocWithZone: zone] initWithDuration:[self duration] position:_positionDelta]; +} + +-(void) startWithTarget:(CCNode *)target +{ + [super startWithTarget:target]; + _previousPos = _startPos = [target position]; +} + +-(CCActionInterval*) reverse +{ + return [[self class] actionWithDuration:_duration position:ccp( -_positionDelta.x, -_positionDelta.y)]; +} + +-(void) update: (ccTime) t +{ + + CCNode *node = (CCNode*)_target; + +#if CC_ENABLE_STACKABLE_ACTIONS + CGPoint currentPos = [node position]; + CGPoint diff = ccpSub(currentPos, _previousPos); + _startPos = ccpAdd( _startPos, diff); + CGPoint newPos = ccpAdd( _startPos, ccpMult(_positionDelta, t) ); + [_target setPosition: newPos]; + _previousPos = newPos; +#else + [node setPosition: ccpAdd( _startPos, ccpMult(_positionDelta, t))]; +#endif // CC_ENABLE_STACKABLE_ACTIONS +} +@end + +// +// MoveTo +// +#pragma mark - +#pragma mark MoveTo + +@implementation CCMoveTo ++(id) actionWithDuration: (ccTime) t position: (CGPoint) p +{ + return [[[self alloc] initWithDuration:t position:p ] autorelease]; +} + +-(id) initWithDuration: (ccTime) t position: (CGPoint) p +{ + if( (self=[super initWithDuration: t]) ) { + _endPosition = p; + } + + return self; +} + +-(id) copyWithZone: (NSZone*) zone +{ + CCAction *copy = [[[self class] allocWithZone: zone] initWithDuration: [self duration] position: _endPosition]; + return copy; +} + +-(void) startWithTarget:(CCNode *)aTarget +{ + [super startWithTarget:aTarget]; + _positionDelta = ccpSub( _endPosition, [(CCNode*)_target position] ); +} + +@end + +// +// SkewTo +// +#pragma mark - CCSkewTo + +@implementation CCSkewTo ++(id) actionWithDuration:(ccTime)t skewX:(float)sx skewY:(float)sy +{ + return [[[self alloc] initWithDuration: t skewX:sx skewY:sy] autorelease]; +} + +-(id) initWithDuration:(ccTime)t skewX:(float)sx skewY:(float)sy +{ + if( (self=[super initWithDuration:t]) ) { + _endSkewX = sx; + _endSkewY = sy; + } + return self; +} + +-(id) copyWithZone: (NSZone*) zone +{ + CCAction *copy = [[[self class] allocWithZone: zone] initWithDuration:[self duration] skewX:_endSkewX skewY:_endSkewY]; + return copy; +} + +-(void) startWithTarget:(CCNode *)aTarget +{ + [super startWithTarget:aTarget]; + + _startSkewX = [_target skewX]; + + if (_startSkewX > 0) + _startSkewX = fmodf(_startSkewX, 180.0f); + else + _startSkewX = fmodf(_startSkewX, -180.0f); + + _deltaX = _endSkewX - _startSkewX; + + if ( _deltaX > 180 ) { + _deltaX -= 360; + } + if ( _deltaX < -180 ) { + _deltaX += 360; + } + + _startSkewY = [_target skewY]; + + if (_startSkewY > 0) + _startSkewY = fmodf(_startSkewY, 360.0f); + else + _startSkewY = fmodf(_startSkewY, -360.0f); + + _deltaY = _endSkewY - _startSkewY; + + if ( _deltaY > 180 ) { + _deltaY -= 360; + } + if ( _deltaY < -180 ) { + _deltaY += 360; + } +} + +-(void) update: (ccTime) t +{ + [_target setSkewX: (_startSkewX + _deltaX * t ) ]; + [_target setSkewY: (_startSkewY + _deltaY * t ) ]; +} + +@end + +// +// CCSkewBy +// +#pragma mark - CCSkewBy + +@implementation CCSkewBy + +-(id) initWithDuration:(ccTime)t skewX:(float)deltaSkewX skewY:(float)deltaSkewY +{ + if( (self=[super initWithDuration:t skewX:deltaSkewX skewY:deltaSkewY]) ) { + _skewX = deltaSkewX; + _skewY = deltaSkewY; + } + return self; +} + +-(void) startWithTarget:(CCNode *)aTarget +{ + [super startWithTarget:aTarget]; + _deltaX = _skewX; + _deltaY = _skewY; + _endSkewX = _startSkewX + _deltaX; + _endSkewY = _startSkewY + _deltaY; +} + +-(CCActionInterval*) reverse +{ + return [[self class] actionWithDuration:_duration skewX:-_skewX skewY:-_skewY]; +} +@end + + +// +// JumpBy +// +#pragma mark - CCJumpBy + +@implementation CCJumpBy ++(id) actionWithDuration: (ccTime) t position: (CGPoint) pos height: (ccTime) h jumps:(NSUInteger)j +{ + return [[[self alloc] initWithDuration: t position: pos height: h jumps:j] autorelease]; +} + +-(id) initWithDuration: (ccTime) t position: (CGPoint) pos height: (ccTime) h jumps:(NSUInteger)j +{ + if( (self=[super initWithDuration:t]) ) { + _delta = pos; + _height = h; + _jumps = j; + } + return self; +} + +-(id) copyWithZone: (NSZone*) zone +{ + CCAction *copy = [[[self class] allocWithZone: zone] initWithDuration:[self duration] position:_delta height:_height jumps:_jumps]; + return copy; +} + +-(void) startWithTarget:(id)target +{ + [super startWithTarget:target]; + _previousPos = _startPosition = [(CCNode*)_target position]; +} + +-(void) update: (ccTime) t +{ + // Sin jump. Less realistic +// ccTime y = _height * fabsf( sinf(t * (CGFloat)M_PI * _jumps ) ); +// y += _delta.y * dt; + +// // parabolic jump (since v0.8.2) + CGFloat frac = fmodf( t * _jumps, 1.0f ); + CGFloat y = _height * 4 * frac * (1 - frac); + y += _delta.y * t; + + CGFloat x = _delta.x * t; + + CCNode *node = (CCNode*)_target; + +#if CC_ENABLE_STACKABLE_ACTIONS + CGPoint currentPos = [node position]; + + CGPoint diff = ccpSub( currentPos, _previousPos ); + _startPosition = ccpAdd( diff, _startPosition); + + CGPoint newPos = ccpAdd( _startPosition, ccp(x,y)); + [node setPosition:newPos]; + + _previousPos = newPos; +#else + [node setPosition: ccpAdd( _startPosition, ccp(x,y))]; +#endif // !CC_ENABLE_STACKABLE_ACTIONS +} + +-(CCActionInterval*) reverse +{ + return [[self class] actionWithDuration:_duration position: ccp(-_delta.x,-_delta.y) height:_height jumps:_jumps]; +} +@end + +// +// JumpTo +// +#pragma mark - CCJumpTo + +@implementation CCJumpTo +-(void) startWithTarget:(CCNode *)aTarget +{ + [super startWithTarget:aTarget]; + _delta = ccp( _delta.x - _startPosition.x, _delta.y - _startPosition.y ); +} +@end + + +#pragma mark - CCBezierBy + +// Bezier cubic formula: +// ((1 - t) + t)3 = 1 +// Expands to… +// (1 - t)3 + 3t(1-t)2 + 3t2(1 - t) + t3 = 1 +static inline CGFloat bezierat( float a, float b, float c, float d, ccTime t ) +{ + return (powf(1-t,3) * a + + 3*t*(powf(1-t,2))*b + + 3*powf(t,2)*(1-t)*c + + powf(t,3)*d ); +} + +// +// BezierBy +// +@implementation CCBezierBy ++(id) actionWithDuration: (ccTime) t bezier:(ccBezierConfig) c +{ + return [[[self alloc] initWithDuration:t bezier:c ] autorelease]; +} + +-(id) initWithDuration: (ccTime) t bezier:(ccBezierConfig) c +{ + if( (self=[super initWithDuration: t]) ) { + _config = c; + } + return self; +} + +-(id) copyWithZone: (NSZone*) zone +{ + return [[[self class] allocWithZone: zone] initWithDuration:[self duration] bezier:_config]; +} + +-(void) startWithTarget:(id)aTarget +{ + [super startWithTarget:aTarget]; + _previousPosition = _startPosition = [(CCNode*)_target position]; +} + +-(void) update: (ccTime) t +{ + CGFloat xa = 0; + CGFloat xb = _config.controlPoint_1.x; + CGFloat xc = _config.controlPoint_2.x; + CGFloat xd = _config.endPosition.x; + + CGFloat ya = 0; + CGFloat yb = _config.controlPoint_1.y; + CGFloat yc = _config.controlPoint_2.y; + CGFloat yd = _config.endPosition.y; + + CGFloat x = bezierat(xa, xb, xc, xd, t); + CGFloat y = bezierat(ya, yb, yc, yd, t); + + CCNode *node = (CCNode*)_target; + +#if CC_ENABLE_STACKABLE_ACTIONS + CGPoint currentPos = [node position]; + CGPoint diff = ccpSub(currentPos, _previousPosition); + _startPosition = ccpAdd( _startPosition, diff); + + CGPoint newPos = ccpAdd( _startPosition, ccp(x,y)); + [node setPosition: newPos]; + + _previousPosition = newPos; +#else + [node setPosition: ccpAdd( _startPosition, ccp(x,y))]; +#endif // !CC_ENABLE_STACKABLE_ACTIONS +} + +- (CCActionInterval*) reverse +{ + ccBezierConfig r; + + r.endPosition = ccpNeg(_config.endPosition); + r.controlPoint_1 = ccpAdd(_config.controlPoint_2, ccpNeg(_config.endPosition)); + r.controlPoint_2 = ccpAdd(_config.controlPoint_1, ccpNeg(_config.endPosition)); + + CCBezierBy *action = [[self class] actionWithDuration:[self duration] bezier:r]; + return action; +} +@end + +// +// BezierTo +// +#pragma mark - CCBezierTo +@implementation CCBezierTo +-(id) initWithDuration: (ccTime) t bezier:(ccBezierConfig) c +{ + if( (self=[super initWithDuration: t]) ) { + _toConfig = c; + } + return self; +} + +-(void) startWithTarget:(id)aTarget +{ + [super startWithTarget:aTarget]; + _config.controlPoint_1 = ccpSub(_toConfig.controlPoint_1, _startPosition); + _config.controlPoint_2 = ccpSub(_toConfig.controlPoint_2, _startPosition); + _config.endPosition = ccpSub(_toConfig.endPosition, _startPosition); +} + +-(id) copyWithZone: (NSZone*) zone +{ + return [[[self class] allocWithZone: zone] initWithDuration:[self duration] bezier:_toConfig]; +} + +@end + + +// +// ScaleTo +// +#pragma mark - CCScaleTo +@implementation CCScaleTo ++(id) actionWithDuration: (ccTime) t scale:(float) s +{ + return [[[self alloc] initWithDuration: t scale:s] autorelease]; +} + +-(id) initWithDuration: (ccTime) t scale:(float) s +{ + if( (self=[super initWithDuration: t]) ) { + _endScaleX = s; + _endScaleY = s; + } + return self; +} + ++(id) actionWithDuration: (ccTime) t scaleX:(float)sx scaleY:(float)sy +{ + return [[[self alloc] initWithDuration: t scaleX:sx scaleY:sy] autorelease]; +} + +-(id) initWithDuration: (ccTime) t scaleX:(float)sx scaleY:(float)sy +{ + if( (self=[super initWithDuration: t]) ) { + _endScaleX = sx; + _endScaleY = sy; + } + return self; +} + +-(id) copyWithZone: (NSZone*) zone +{ + CCAction *copy = [[[self class] allocWithZone: zone] initWithDuration:[self duration] scaleX:_endScaleX scaleY:_endScaleY]; + return copy; +} + +-(void) startWithTarget:(CCNode *)aTarget +{ + [super startWithTarget:aTarget]; + _startScaleX = [_target scaleX]; + _startScaleY = [_target scaleY]; + _deltaX = _endScaleX - _startScaleX; + _deltaY = _endScaleY - _startScaleY; +} + +-(void) update: (ccTime) t +{ + [_target setScaleX: (_startScaleX + _deltaX * t ) ]; + [_target setScaleY: (_startScaleY + _deltaY * t ) ]; +} +@end + +// +// ScaleBy +// +#pragma mark - CCScaleBy +@implementation CCScaleBy +-(void) startWithTarget:(CCNode *)aTarget +{ + [super startWithTarget:aTarget]; + _deltaX = _startScaleX * _endScaleX - _startScaleX; + _deltaY = _startScaleY * _endScaleY - _startScaleY; +} + +-(CCActionInterval*) reverse +{ + return [[self class] actionWithDuration:_duration scaleX:1/_endScaleX scaleY:1/_endScaleY]; +} +@end + +// +// Blink +// +#pragma mark - CCBlink +@implementation CCBlink ++(id) actionWithDuration: (ccTime) t blinks: (NSUInteger) b +{ + return [[[ self alloc] initWithDuration: t blinks: b] autorelease]; +} + +-(id) initWithDuration: (ccTime) t blinks: (NSUInteger) b +{ + if( (self=[super initWithDuration: t] ) ) + _times = b; + + return self; +} + +-(id) copyWithZone: (NSZone*) zone +{ + CCAction *copy = [[[self class] allocWithZone: zone] initWithDuration: [self duration] blinks: _times]; + return copy; +} + +-(void) startWithTarget:(id)target +{ + [super startWithTarget:target]; + _originalState = [target visible]; +} + +-(void) update: (ccTime) t +{ + if( ! [self isDone] ) { + ccTime slice = 1.0f / _times; + ccTime m = fmodf(t, slice); + [_target setVisible: (m > slice/2) ? YES : NO]; + } +} + +-(void) stop +{ + [_target setVisible:_originalState]; + [super stop]; +} + +-(CCActionInterval*) reverse +{ + // return 'self' + return [[self class] actionWithDuration:_duration blinks: _times]; +} +@end + +// +// FadeIn +// +#pragma mark - CCFadeIn +@implementation CCFadeIn +-(void) update: (ccTime) t +{ + [(id) _target setOpacity: 255 *t]; +} + +-(CCActionInterval*) reverse +{ + return [CCFadeOut actionWithDuration:_duration]; +} +@end + +// +// FadeOut +// +#pragma mark - CCFadeOut +@implementation CCFadeOut +-(void) update: (ccTime) t +{ + [(id) _target setOpacity: 255 *(1-t)]; +} + +-(CCActionInterval*) reverse +{ + return [CCFadeIn actionWithDuration:_duration]; +} +@end + +// +// FadeTo +// +#pragma mark - CCFadeTo +@implementation CCFadeTo ++(id) actionWithDuration: (ccTime) t opacity: (GLubyte) o +{ + return [[[ self alloc] initWithDuration: t opacity: o] autorelease]; +} + +-(id) initWithDuration: (ccTime) t opacity: (GLubyte) o +{ + if( (self=[super initWithDuration: t] ) ) + _toOpacity = o; + + return self; +} + +-(id) copyWithZone: (NSZone*) zone +{ + CCAction *copy = [[[self class] allocWithZone: zone] initWithDuration:[self duration] opacity:_toOpacity]; + return copy; +} + +-(void) startWithTarget:(CCNode *)aTarget +{ + [super startWithTarget:aTarget]; + _fromOpacity = [(id)_target opacity]; +} + +-(void) update: (ccTime) t +{ + [(id)_target setOpacity:_fromOpacity + ( _toOpacity - _fromOpacity ) * t]; +} +@end + +// +// TintTo +// +#pragma mark - CCTintTo +@implementation CCTintTo ++(id) actionWithDuration:(ccTime)t red:(GLubyte)r green:(GLubyte)g blue:(GLubyte)b +{ + return [[(CCTintTo*)[ self alloc] initWithDuration:t red:r green:g blue:b] autorelease]; +} + +-(id) initWithDuration: (ccTime) t red:(GLubyte)r green:(GLubyte)g blue:(GLubyte)b +{ + if( (self=[super initWithDuration:t] ) ) + _to = ccc3(r,g,b); + + return self; +} + +-(id) copyWithZone: (NSZone*) zone +{ + CCAction *copy = [(CCTintTo*)[[self class] allocWithZone: zone] initWithDuration:[self duration] red:_to.r green:_to.g blue:_to.b]; + return copy; +} + +-(void) startWithTarget:(id)aTarget +{ + [super startWithTarget:aTarget]; + + id tn = (id) _target; + _from = [tn color]; +} + +-(void) update: (ccTime) t +{ + id tn = (id) _target; + [tn setColor:ccc3(_from.r + (_to.r - _from.r) * t, _from.g + (_to.g - _from.g) * t, _from.b + (_to.b - _from.b) * t)]; +} +@end + +// +// TintBy +// +#pragma mark - CCTintBy +@implementation CCTintBy ++(id) actionWithDuration:(ccTime)t red:(GLshort)r green:(GLshort)g blue:(GLshort)b +{ + return [[(CCTintBy*)[ self alloc] initWithDuration:t red:r green:g blue:b] autorelease]; +} + +-(id) initWithDuration:(ccTime)t red:(GLshort)r green:(GLshort)g blue:(GLshort)b +{ + if( (self=[super initWithDuration: t] ) ) { + _deltaR = r; + _deltaG = g; + _deltaB = b; + } + return self; +} + +-(id) copyWithZone: (NSZone*) zone +{ + return[(CCTintBy*)[[self class] allocWithZone: zone] initWithDuration: [self duration] red:_deltaR green:_deltaG blue:_deltaB]; +} + +-(void) startWithTarget:(id)aTarget +{ + [super startWithTarget:aTarget]; + + id tn = (id) _target; + ccColor3B color = [tn color]; + _fromR = color.r; + _fromG = color.g; + _fromB = color.b; +} + +-(void) update: (ccTime) t +{ + id tn = (id) _target; + [tn setColor:ccc3( _fromR + _deltaR * t, _fromG + _deltaG * t, _fromB + _deltaB * t)]; +} + +- (CCActionInterval*) reverse +{ + return [CCTintBy actionWithDuration:_duration red:-_deltaR green:-_deltaG blue:-_deltaB]; +} +@end + +// +// DelayTime +// +#pragma mark - CCDelayTime +@implementation CCDelayTime +-(void) update: (ccTime) t +{ + return; +} + +-(id)reverse +{ + return [[self class] actionWithDuration:_duration]; +} +@end + +// +// ReverseTime +// +#pragma mark - CCReverseTime +@implementation CCReverseTime ++(id) actionWithAction: (CCFiniteTimeAction*) action +{ + // casting to prevent warnings + CCReverseTime *a = [self alloc]; + return [[a initWithAction:action] autorelease]; +} + +-(id) initWithAction: (CCFiniteTimeAction*) action +{ + NSAssert(action != nil, @"CCReverseTime: action should not be nil"); + NSAssert(action != _other, @"CCReverseTime: re-init doesn't support using the same arguments"); + + if( (self=[super initWithDuration: [action duration]]) ) { + // Don't leak if action is reused + [_other release]; + _other = [action retain]; + } + + return self; +} + +-(id) copyWithZone: (NSZone*) zone +{ + return [[[self class] allocWithZone: zone] initWithAction:[[_other copy] autorelease] ]; +} + +-(void) dealloc +{ + [_other release]; + [super dealloc]; +} + +-(void) startWithTarget:(id)aTarget +{ + [super startWithTarget:aTarget]; + [_other startWithTarget:_target]; +} + +-(void) stop +{ + [_other stop]; + [super stop]; +} + +-(void) update:(ccTime)t +{ + [_other update:1-t]; +} + +-(CCActionInterval*) reverse +{ + return [[_other copy] autorelease]; +} +@end + +// +// Animate +// + +#pragma mark - CCAnimate +@implementation CCAnimate + +@synthesize animation = _animation; + ++(id) actionWithAnimation: (CCAnimation*)anim +{ + return [[[self alloc] initWithAnimation:anim] autorelease]; +} + +// delegate initializer +-(id) initWithAnimation:(CCAnimation*)anim +{ + NSAssert( anim!=nil, @"Animate: argument Animation must be non-nil"); + + float singleDuration = anim.duration; + + if( (self=[super initWithDuration:singleDuration * anim.loops] ) ) { + + _nextFrame = 0; + self.animation = anim; + _origFrame = nil; + _executedLoops = 0; + + _splitTimes = [[NSMutableArray alloc] initWithCapacity:anim.frames.count]; + + float accumUnitsOfTime = 0; + float newUnitOfTimeValue = singleDuration / anim.totalDelayUnits; + + for( CCAnimationFrame *frame in anim.frames ) { + + NSNumber *value = [NSNumber numberWithFloat: (accumUnitsOfTime * newUnitOfTimeValue) / singleDuration]; + accumUnitsOfTime += frame.delayUnits; + + [_splitTimes addObject:value]; + } + } + return self; +} + + +-(id) copyWithZone: (NSZone*) zone +{ + return [[[self class] allocWithZone: zone] initWithAnimation:[[_animation copy]autorelease] ]; +} + +-(void) dealloc +{ + [_splitTimes release]; + [_animation release]; + [_origFrame release]; + [super dealloc]; +} + +-(void) startWithTarget:(id)aTarget +{ + [super startWithTarget:aTarget]; + CCSprite *sprite = _target; + + [_origFrame release]; + + if( _animation.restoreOriginalFrame ) + _origFrame = [[sprite displayFrame] retain]; + + _nextFrame = 0; + _executedLoops = 0; +} + +-(void) stop +{ + if( _animation.restoreOriginalFrame ) { + CCSprite *sprite = _target; + [sprite setDisplayFrame:_origFrame]; + } + + [super stop]; +} + +-(void) update: (ccTime) t +{ + + // if t==1, ignore. Animation should finish with t==1 + if( t < 1.0f ) { + t *= _animation.loops; + + // new loop? If so, reset frame counter + NSUInteger loopNumber = (NSUInteger)t; + if( loopNumber > _executedLoops ) { + _nextFrame = 0; + _executedLoops++; + } + + // new t for animations + t = fmodf(t, 1.0f); + } + + NSArray *frames = [_animation frames]; + NSUInteger numberOfFrames = [frames count]; + CCSpriteFrame *frameToDisplay = nil; + + for( NSUInteger i=_nextFrame; i < numberOfFrames; i++ ) { + NSNumber *splitTime = [_splitTimes objectAtIndex:i]; + + if( [splitTime floatValue] <= t ) { + CCAnimationFrame *frame = [frames objectAtIndex:i]; + frameToDisplay = [frame spriteFrame]; + [(CCSprite*)_target setDisplayFrame: frameToDisplay]; + + NSDictionary *dict = [frame userInfo]; + if( dict ) + [[NSNotificationCenter defaultCenter] postNotificationName:CCAnimationFrameDisplayedNotification object:_target userInfo:dict]; + + _nextFrame = i+1; + } + // Issue 1438. Could be more than one frame per tick, due to low frame rate or frame delta < 1/FPS + else + break; + } +} + +- (CCActionInterval *) reverse +{ + NSArray *oldArray = [_animation frames]; + NSMutableArray *newArray = [NSMutableArray arrayWithCapacity:[oldArray count]]; + NSEnumerator *enumerator = [oldArray reverseObjectEnumerator]; + for (id element in enumerator) + [newArray addObject:[[element copy] autorelease]]; + + CCAnimation *newAnim = [CCAnimation animationWithAnimationFrames:newArray delayPerUnit:_animation.delayPerUnit loops:_animation.loops]; + newAnim.restoreOriginalFrame = _animation.restoreOriginalFrame; + return [[self class] actionWithAnimation:newAnim]; +} +@end + + +#pragma mark - CCTargetedAction + +@implementation CCTargetedAction + +@synthesize forcedTarget = _forcedTarget; + ++ (id) actionWithTarget:(id) target action:(CCFiniteTimeAction*) action +{ + return [[ (CCTargetedAction*)[self alloc] initWithTarget:target action:action] autorelease]; +} + +- (id) initWithTarget:(id) targetIn action:(CCFiniteTimeAction*) actionIn +{ + if((self = [super initWithDuration:actionIn.duration])) + { + _forcedTarget = [targetIn retain]; + _action = [actionIn retain]; + } + return self; +} + +-(id) copyWithZone: (NSZone*) zone +{ + CCAction *copy = [ (CCTargetedAction*) [[self class] allocWithZone: zone] initWithTarget:_forcedTarget action:[[_action copy] autorelease]]; + return copy; +} + +- (void) dealloc +{ + [_forcedTarget release]; + [_action release]; + [super dealloc]; +} + +//- (void) updateDuration:(id)aTarget +//{ +// [action updateDuration:forcedTarget]; +// _duration = action.duration; +//} + +- (void) startWithTarget:(id)aTarget +{ + [super startWithTarget:aTarget]; + [_action startWithTarget:_forcedTarget]; +} + +- (void) stop +{ + [_action stop]; +} + +- (void) update:(ccTime) time +{ + [_action update:time]; +} + +@end diff --git "a/21451198\345\215\242\350\266\205/project5/MyPlane/libs/cocos2d/CCActionManager.h" "b/21451198\345\215\242\350\266\205/project5/MyPlane/libs/cocos2d/CCActionManager.h" new file mode 100644 index 00000000..4a1bc2ef --- /dev/null +++ "b/21451198\345\215\242\350\266\205/project5/MyPlane/libs/cocos2d/CCActionManager.h" @@ -0,0 +1,113 @@ +/* + * cocos2d for iPhone: http://www.cocos2d-iphone.org + * + * Copyright (c) 2009 Valentin Milea + * + * Copyright (c) 2008-2010 Ricardo Quesada + * Copyright (c) 2011 Zynga Inc. + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + * THE SOFTWARE. + * + */ + + +#import "CCAction.h" +#import "ccMacros.h" +#import "Support/ccCArray.h" +#import "Support/uthash.h" + +typedef struct _hashElement +{ + struct ccArray *actions; + NSUInteger actionIndex; + BOOL currentActionSalvaged; + BOOL paused; + UT_hash_handle hh; + + CC_ARC_UNSAFE_RETAINED id target; + CC_ARC_UNSAFE_RETAINED CCAction *currentAction; +} tHashElement; + + +/** CCActionManager the object that manages all the actions. + Normally you won't need to use this API directly. 99% of the cases you will use the CCNode interface, which uses this object. + But there are some cases where you might need to use this API directly: + Examples: + - When you want to run an action where the target is different from a CCNode. + - When you want to pause / resume the actions + + @since v0.8 + */ +@interface CCActionManager : NSObject +{ + tHashElement *targets; + tHashElement *currentTarget; + BOOL currentTargetSalvaged; +} + + +// actions + +/** Adds an action with a target. + If the target is already present, then the action will be added to the existing target. + If the target is not present, a new instance of this target will be created either paused or paused, and the action will be added to the newly created target. + When the target is paused, the queued actions won't be 'ticked'. + */ +-(void) addAction: (CCAction*) action target:(id)target paused:(BOOL)paused; +/** Removes all actions from all the targets. + */ +-(void) removeAllActions; + +/** Removes all actions from a certain target. + All the actions that belongs to the target will be removed. + */ +-(void) removeAllActionsFromTarget:(id)target; +/** Removes an action given an action reference. + */ +-(void) removeAction: (CCAction*) action; +/** Removes an action given its tag and the target */ +-(void) removeActionByTag:(NSInteger)tag target:(id)target; +/** Gets an action given its tag an a target + @return the Action the with the given tag + */ +-(CCAction*) getActionByTag:(NSInteger) tag target:(id)target; +/** Returns the numbers of actions that are running in a certain target + * Composable actions are counted as 1 action. Example: + * If you are running 1 Sequence of 7 actions, it will return 1. + * If you are running 7 Sequences of 2 actions, it will return 7. + */ +-(NSUInteger) numberOfRunningActionsInTarget:(id)target; + +/** Pauses the target: all running actions and newly added actions will be paused. + */ +-(void) pauseTarget:(id)target; +/** Resumes the target. All queued actions will be resumed. + */ +-(void) resumeTarget:(id)target; + +/** Pauses all running actions, returning a list of targets whose actions were paused. + */ +-(NSSet *) pauseAllRunningActions; + +/** Resume a set of targets (convenience function to reverse a pauseAllRunningActions call) + */ +-(void) resumeTargets:(NSSet *)targetsToResume; + +@end + diff --git "a/21451198\345\215\242\350\266\205/project5/MyPlane/libs/cocos2d/CCActionManager.m" "b/21451198\345\215\242\350\266\205/project5/MyPlane/libs/cocos2d/CCActionManager.m" new file mode 100644 index 00000000..8941be5d --- /dev/null +++ "b/21451198\345\215\242\350\266\205/project5/MyPlane/libs/cocos2d/CCActionManager.m" @@ -0,0 +1,338 @@ +/* + * cocos2d for iPhone: http://www.cocos2d-iphone.org + * + * Copyright (c) 2009 Valentin Milea + * + * Copyright (c) 2008-2010 Ricardo Quesada + * Copyright (c) 2011 Zynga Inc. + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + * THE SOFTWARE. + * + */ + + +#import "CCActionManager.h" +#import "ccMacros.h" + +@interface CCActionManager (Private) +-(void) removeActionAtIndex:(NSUInteger)index hashElement:(tHashElement*)element; +-(void) deleteHashElement:(tHashElement*)element; +-(void) actionAllocWithHashElement:(tHashElement*)element; +@end + + +@implementation CCActionManager + +-(id) init +{ + if ((self=[super init]) ) { + targets = NULL; + } + + return self; +} + +- (NSString*) description +{ + return [NSString stringWithFormat:@"<%@ = %p>", [self class], self]; +} + +- (void) dealloc +{ + CCLOGINFO( @"cocos2d: deallocing %@", self); + + [self removeAllActions]; + + [super dealloc]; +} + +#pragma mark ActionManager - Private + +-(void) deleteHashElement:(tHashElement*)element +{ + ccArrayFree(element->actions); + HASH_DEL(targets, element); +// CCLOG(@"cocos2d: ---- buckets: %d/%d - %@", targets->entries, targets->size, element->target); + [element->target release]; + free(element); +} + +-(void) actionAllocWithHashElement:(tHashElement*)element +{ + // 4 actions per Node by default + if( element->actions == nil ) + element->actions = ccArrayNew(4); + else if( element->actions->num == element->actions->max ) + ccArrayDoubleCapacity(element->actions); +} + +-(void) removeActionAtIndex:(NSUInteger)index hashElement:(tHashElement*)element +{ + id action = element->actions->arr[index]; + + if( action == element->currentAction && !element->currentActionSalvaged ) { + [element->currentAction retain]; + element->currentActionSalvaged = YES; + } + + ccArrayRemoveObjectAtIndex(element->actions, index); + + // update actionIndex in case we are in tick:, looping over the actions + if( element->actionIndex >= index ) + element->actionIndex--; + + if( element->actions->num == 0 ) { + if( currentTarget == element ) + currentTargetSalvaged = YES; + else + [self deleteHashElement: element]; + } +} + +#pragma mark ActionManager - Pause / Resume + +-(void) pauseTarget:(id)target +{ + tHashElement *element = NULL; + HASH_FIND_INT(targets, &target, element); + if( element ) + element->paused = YES; +// else +// CCLOG(@"cocos2d: pauseAllActions: Target not found"); +} + +-(void) resumeTarget:(id)target +{ + tHashElement *element = NULL; + HASH_FIND_INT(targets, &target, element); + if( element ) + element->paused = NO; +// else +// CCLOG(@"cocos2d: resumeAllActions: Target not found"); +} + +-(NSSet *) pauseAllRunningActions +{ + NSMutableSet* idsWithActions = [NSMutableSet setWithCapacity:50]; + + for(tHashElement *element=targets; element != NULL; element=element->hh.next) { + if( !element->paused ) { + element->paused = YES; + [idsWithActions addObject:element->target]; + } + } + return idsWithActions; +} + +-(void) resumeTargets:(NSSet *)targetsToResume +{ + for(id target in targetsToResume) { + [self resumeTarget:target]; + } +} + +#pragma mark ActionManager - run + +-(void) addAction:(CCAction*)action target:(id)target paused:(BOOL)paused +{ + NSAssert( action != nil, @"Argument action must be non-nil"); + NSAssert( target != nil, @"Argument target must be non-nil"); + + tHashElement *element = NULL; + HASH_FIND_INT(targets, &target, element); + if( ! element ) { + element = calloc( sizeof( *element ), 1 ); + element->paused = paused; + element->target = [target retain]; + HASH_ADD_INT(targets, target, element); +// CCLOG(@"cocos2d: ---- buckets: %d/%d - %@", targets->entries, targets->size, element->target); + + } + + [self actionAllocWithHashElement:element]; + + NSAssert( !ccArrayContainsObject(element->actions, action), @"runAction: Action already running"); + ccArrayAppendObject(element->actions, action); + + [action startWithTarget:target]; +} + +#pragma mark ActionManager - remove + +-(void) removeAllActions +{ + for(tHashElement *element=targets; element != NULL; ) { + id target = element->target; + element = element->hh.next; + [self removeAllActionsFromTarget:target]; + } +} +-(void) removeAllActionsFromTarget:(id)target +{ + // explicit nil handling + if( target == nil ) + return; + + tHashElement *element = NULL; + HASH_FIND_INT(targets, &target, element); + if( element ) { + if( ccArrayContainsObject(element->actions, element->currentAction) && !element->currentActionSalvaged ) { + [element->currentAction retain]; + element->currentActionSalvaged = YES; + } + ccArrayRemoveAllObjects(element->actions); + if( currentTarget == element ) + currentTargetSalvaged = YES; + else + [self deleteHashElement:element]; + } +// else { +// CCLOG(@"cocos2d: removeAllActionsFromTarget: Target not found"); +// } +} + +-(void) removeAction: (CCAction*) action +{ + // explicit nil handling + if (action == nil) + return; + + tHashElement *element = NULL; + id target = [action originalTarget]; + HASH_FIND_INT(targets, &target, element ); + if( element ) { + NSUInteger i = ccArrayGetIndexOfObject(element->actions, action); + if( i != NSNotFound ) + [self removeActionAtIndex:i hashElement:element]; + } +// else { +// CCLOG(@"cocos2d: removeAction: Target not found"); +// } +} + +-(void) removeActionByTag:(NSInteger)aTag target:(id)target +{ + NSAssert( aTag != kCCActionTagInvalid, @"Invalid tag"); + NSAssert( target != nil, @"Target should be ! nil"); + + tHashElement *element = NULL; + HASH_FIND_INT(targets, &target, element); + + if( element ) { + NSUInteger limit = element->actions->num; + for( NSUInteger i = 0; i < limit; i++) { + CCAction *a = element->actions->arr[i]; + + if( a.tag == aTag && [a originalTarget]==target) { + [self removeActionAtIndex:i hashElement:element]; + break; + } + } + + } +} + +#pragma mark ActionManager - get + +-(CCAction*) getActionByTag:(NSInteger)aTag target:(id)target +{ + NSAssert( aTag != kCCActionTagInvalid, @"Invalid tag"); + + tHashElement *element = NULL; + HASH_FIND_INT(targets, &target, element); + + if( element ) { + if( element->actions != nil ) { + NSUInteger limit = element->actions->num; + for( NSUInteger i = 0; i < limit; i++) { + CCAction *a = element->actions->arr[i]; + + if( a.tag == aTag ) + return a; + } + } +// CCLOG(@"cocos2d: getActionByTag: Action not found"); + } +// else { +// CCLOG(@"cocos2d: getActionByTag: Target not found"); +// } + return nil; +} + +-(NSUInteger) numberOfRunningActionsInTarget:(id) target +{ + tHashElement *element = NULL; + HASH_FIND_INT(targets, &target, element); + if( element ) + return element->actions ? element->actions->num : 0; + +// CCLOG(@"cocos2d: numberOfRunningActionsInTarget: Target not found"); + return 0; +} + +#pragma mark ActionManager - main loop + +-(void) update: (ccTime) dt +{ + for(tHashElement *elt = targets; elt != NULL; ) { + + currentTarget = elt; + currentTargetSalvaged = NO; + + if( ! currentTarget->paused ) { + + // The 'actions' ccArray may change while inside this loop. + for( currentTarget->actionIndex = 0; currentTarget->actionIndex < currentTarget->actions->num; currentTarget->actionIndex++) { + currentTarget->currentAction = currentTarget->actions->arr[currentTarget->actionIndex]; + currentTarget->currentActionSalvaged = NO; + + [currentTarget->currentAction step: dt]; + + if( currentTarget->currentActionSalvaged ) { + // The currentAction told the node to remove it. To prevent the action from + // accidentally deallocating itself before finishing its step, we retained + // it. Now that step is done, it's safe to release it. + [currentTarget->currentAction release]; + + } else if( [currentTarget->currentAction isDone] ) { + [currentTarget->currentAction stop]; + + CCAction *a = currentTarget->currentAction; + // Make currentAction nil to prevent removeAction from salvaging it. + currentTarget->currentAction = nil; + [self removeAction:a]; + } + + currentTarget->currentAction = nil; + } + } + + // elt, at this moment, is still valid + // so it is safe to ask this here (issue #490) + elt = elt->hh.next; + + // only delete currentTarget if no actions were scheduled during the cycle (issue #481) + if( currentTargetSalvaged && currentTarget->actions->num == 0 ) + [self deleteHashElement:currentTarget]; + } + + // issue #635 + currentTarget = nil; +} +@end diff --git "a/21451198\345\215\242\350\266\205/project5/MyPlane/libs/cocos2d/CCActionPageTurn3D.h" "b/21451198\345\215\242\350\266\205/project5/MyPlane/libs/cocos2d/CCActionPageTurn3D.h" new file mode 100644 index 00000000..7afa3e19 --- /dev/null +++ "b/21451198\345\215\242\350\266\205/project5/MyPlane/libs/cocos2d/CCActionPageTurn3D.h" @@ -0,0 +1,43 @@ +/* + * cocos2d for iPhone: http://www.cocos2d-iphone.org + * + * Copyright (c) 2009 Sindesso Pty Ltd http://www.sindesso.com/ + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + * THE SOFTWARE. + * + */ + + +#import "CCActionGrid3D.h" + +/** + * This action simulates a page turn from the bottom right hand corner of the screen + * It's not much use by itself but is used by the PageTurnTransition. + * + * Based on an original paper by L Hong et al. + * http://www.parc.com/publication/1638/turning-pages-of-3d-electronic-books.html + * + * @since v0.8.2 + */ +@interface CCPageTurn3D : CCGrid3DAction +{ +} +// XXX: To make BridgeSupport happy +-(void)update:(ccTime)time; +@end diff --git "a/21451198\345\215\242\350\266\205/project5/MyPlane/libs/cocos2d/CCActionPageTurn3D.m" "b/21451198\345\215\242\350\266\205/project5/MyPlane/libs/cocos2d/CCActionPageTurn3D.m" new file mode 100644 index 00000000..6cc19913 --- /dev/null +++ "b/21451198\345\215\242\350\266\205/project5/MyPlane/libs/cocos2d/CCActionPageTurn3D.m" @@ -0,0 +1,87 @@ +/* + * cocos2d for iPhone: http://www.cocos2d-iphone.org + * + * Copyright (c) 2009 Sindesso Pty Ltd http://www.sindesso.com/ + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + * THE SOFTWARE. + * + */ + +#import "CCActionPageTurn3D.h" +#import "Support/CGPointExtension.h" + +@implementation CCPageTurn3D + +/* + * Update each tick + * Time is the percentage of the way through the duration + */ +-(void)update:(ccTime)time +{ + float tt = MAX( 0, time - 0.25f ); + float deltaAy = ( tt * tt * 500); + float ay = -100 - deltaAy; + + float deltaTheta = - (float) M_PI_2 * sqrtf( time) ; + float theta = /*0.01f*/ + (float) M_PI_2 +deltaTheta; + + float sinTheta = sinf(theta); + float cosTheta = cosf(theta); + + for( int i = 0; i <=_gridSize.width; i++ ) + { + for( int j = 0; j <= _gridSize.height; j++ ) + { + // Get original vertex + ccVertex3F p = [self originalVertex:ccp(i,j)]; + + float R = sqrtf(p.x*p.x + (p.y - ay) * (p.y - ay)); + float r = R * sinTheta; + float alpha = asinf( p.x / R ); + float beta = alpha / sinTheta; + float cosBeta = cosf( beta ); + + // If beta > PI then we've wrapped around the cone + // Reduce the radius to stop these points interfering with others + if( beta <= M_PI) + p.x = ( r * sinf(beta)); + else + { + // Force X = 0 to stop wrapped + // points + p.x = 0; + } + + p.y = ( R + ay - ( r*(1 - cosBeta)*sinTheta)); + + // We scale z here to avoid the animation being + // too much bigger than the screen due to perspectve transform + p.z = (r * ( 1 - cosBeta ) * cosTheta) / 7; // "100" didn't work for + + // Stop z coord from dropping beneath underlying page in a transition + // issue #751 + if( p.z<0.5f ) + p.z = 0.5f; + + // Set new coords + [self setVertex:ccp(i,j) vertex:p]; + } + } +} +@end diff --git "a/21451198\345\215\242\350\266\205/project5/MyPlane/libs/cocos2d/CCActionProgressTimer.h" "b/21451198\345\215\242\350\266\205/project5/MyPlane/libs/cocos2d/CCActionProgressTimer.h" new file mode 100644 index 00000000..1e1dc62d --- /dev/null +++ "b/21451198\345\215\242\350\266\205/project5/MyPlane/libs/cocos2d/CCActionProgressTimer.h" @@ -0,0 +1,59 @@ +/* + * cocos2d for iPhone: http://www.cocos2d-iphone.org + * + * Copyright (C) 2010 Lam Pham + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + * THE SOFTWARE. + * + */ + + +#import +#import "CCProgressTimer.h" +#import "CCActionInterval.h" + +/** + Progress to percentage +@since v0.99.1 +*/ +@interface CCProgressTo : CCActionInterval +{ + float _to; + float _from; +} +/** Creates and initializes with a duration and a percent */ ++(id) actionWithDuration:(ccTime)duration percent:(float)percent; +/** Initializes with a duration and a percent */ +-(id) initWithDuration:(ccTime)duration percent:(float)percent; +@end + +/** + Progress from a percentage to another percentage + @since v0.99.1 + */ +@interface CCProgressFromTo : CCActionInterval +{ + float _to; + float _from; +} +/** Creates and initializes the action with a duration, a "from" percentage and a "to" percentage */ ++(id) actionWithDuration:(ccTime)duration from:(float)fromPercentage to:(float) toPercentage; +/** Initializes the action with a duration, a "from" percentage and a "to" percentage */ +-(id) initWithDuration:(ccTime)duration from:(float)fromPercentage to:(float) toPercentage; +@end diff --git "a/21451198\345\215\242\350\266\205/project5/MyPlane/libs/cocos2d/CCActionProgressTimer.m" "b/21451198\345\215\242\350\266\205/project5/MyPlane/libs/cocos2d/CCActionProgressTimer.m" new file mode 100644 index 00000000..011559e0 --- /dev/null +++ "b/21451198\345\215\242\350\266\205/project5/MyPlane/libs/cocos2d/CCActionProgressTimer.m" @@ -0,0 +1,103 @@ +/* + * cocos2d for iPhone: http://www.cocos2d-iphone.org + * + * Copyright (C) 2010 Lam Pham + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + * THE SOFTWARE. + * + */ + + +#import "CCActionProgressTimer.h" + +#define kProgressTimerCast CCProgressTimer* + +@implementation CCProgressTo ++(id) actionWithDuration: (ccTime) t percent: (float) v +{ + return [[[ self alloc] initWithDuration: t percent: v] autorelease]; +} + +-(id) initWithDuration: (ccTime) t percent: (float) v +{ + if( (self=[super initWithDuration: t] ) ) + _to = v; + + return self; +} + +-(id) copyWithZone: (NSZone*) zone +{ + CCAction *copy = [[[self class] allocWithZone: zone] initWithDuration:_duration percent:_to]; + return copy; +} + +-(void) startWithTarget:(id) aTarget; +{ + [super startWithTarget:aTarget]; + _from = [(kProgressTimerCast)_target percentage]; + + // XXX: Is this correct ? + // Adding it to support CCRepeat + if( _from == 100) + _from = 0; +} + +-(void) update: (ccTime) t +{ + [(kProgressTimerCast)_target setPercentage: _from + ( _to - _from ) * t]; +} +@end + +@implementation CCProgressFromTo ++(id) actionWithDuration: (ccTime) t from:(float)fromPercentage to:(float) toPercentage +{ + return [[[self alloc] initWithDuration: t from: fromPercentage to: toPercentage] autorelease]; +} + +-(id) initWithDuration: (ccTime) t from:(float)fromPercentage to:(float) toPercentage +{ + if( (self=[super initWithDuration: t] ) ){ + _to = toPercentage; + _from = fromPercentage; + } + return self; +} + +-(id) copyWithZone: (NSZone*) zone +{ + CCAction *copy = [[[self class] allocWithZone: zone] initWithDuration:_duration from:_from to:_to]; + return copy; +} + +- (CCActionInterval *) reverse +{ + return [[self class] actionWithDuration:_duration from:_to to:_from]; +} + +-(void) startWithTarget:(id) aTarget; +{ + [super startWithTarget:aTarget]; +} + +-(void) update: (ccTime) t +{ + [(kProgressTimerCast)_target setPercentage: _from + ( _to - _from ) * t]; +} +@end diff --git "a/21451198\345\215\242\350\266\205/project5/MyPlane/libs/cocos2d/CCActionTiledGrid.h" "b/21451198\345\215\242\350\266\205/project5/MyPlane/libs/cocos2d/CCActionTiledGrid.h" new file mode 100644 index 00000000..f40f5ba7 --- /dev/null +++ "b/21451198\345\215\242\350\266\205/project5/MyPlane/libs/cocos2d/CCActionTiledGrid.h" @@ -0,0 +1,219 @@ +/* + * cocos2d for iPhone: http://www.cocos2d-iphone.org + * + * Copyright (c) 2009 On-Core + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + * THE SOFTWARE. + * + */ + +#import "CCActionGrid.h" + +/** CCShakyTiles3D action */ +@interface CCShakyTiles3D : CCTiledGrid3DAction +{ + int _randrange; + BOOL _shakeZ; +} + +/** creates the action with a range, whether or not to shake Z vertices, a grid size, and duration */ ++(id)actionWithDuration:(ccTime)duration size:(CGSize)gridSize range:(int)range shakeZ:(BOOL)shakeZ; +/** initializes the action with a range, whether or not to shake Z vertices, a grid size, and duration */ +-(id)initWithDuration:(ccTime)duration size:(CGSize)gridSize range:(int)range shakeZ:(BOOL)shakeZ; + +@end + +//////////////////////////////////////////////////////////// + +/** CCShatteredTiles3D action */ +@interface CCShatteredTiles3D : CCTiledGrid3DAction +{ + int _randrange; + BOOL _once; + BOOL _shatterZ; +} + +/** creates the action with a range, whether of not to shatter Z vertices, a grid size and duration */ ++(id)actionWithDuration:(ccTime)duration size:(CGSize)gridSize range:(int)range shatterZ:(BOOL)shatterZ; +/** initializes the action with a range, whether or not to shatter Z vertices, a grid size and duration */ +-(id)initWithDuration:(ccTime)duration size:(CGSize)gridSize range:(int)range shatterZ:(BOOL)shatterZ; + +@end + +//////////////////////////////////////////////////////////// + +/** CCShuffleTiles action + Shuffle the tiles in random order + */ +@interface CCShuffleTiles : CCTiledGrid3DAction +{ + unsigned _seed; + NSUInteger _tilesCount; + NSUInteger *_tilesOrder; + void *_tiles; +} + +/** creates the action with a random seed, the grid size and the duration */ ++(id)actionWithDuration:(ccTime)duration size:(CGSize)gridSize seed:(unsigned)seed; +/** initializes the action with a random seed, the grid size and the duration */ +-(id)initWithDuration:(ccTime)duration size:(CGSize)gridSize seed:(unsigned)seed; + +@end + +//////////////////////////////////////////////////////////// + +/** CCFadeOutTRTiles action + Fades out the tiles in a Top-Right direction + */ +@interface CCFadeOutTRTiles : CCTiledGrid3DAction +{ +} +// XXX: private, but added to make BridgeSupport happy +-(float)testFunc:(CGSize)pos time:(ccTime)time; +@end + +//////////////////////////////////////////////////////////// + +/** CCFadeOutBLTiles action. + Fades out the tiles in a Bottom-Left direction + */ +@interface CCFadeOutBLTiles : CCFadeOutTRTiles +{ +} +// XXX: private, but added to make BridgeSupport happy +-(float)testFunc:(CGSize)pos time:(ccTime)time; +@end + +//////////////////////////////////////////////////////////// + +/** CCFadeOutUpTiles action. + Fades out the tiles in upwards direction + */ +@interface CCFadeOutUpTiles : CCFadeOutTRTiles +{ +} +// XXX: private, but added to make BridgeSupport happy +-(float)testFunc:(CGSize)pos time:(ccTime)time; +@end + +//////////////////////////////////////////////////////////// + +/** CCFadeOutDownTiles action. + Fades out the tiles in downwards direction + */ +@interface CCFadeOutDownTiles : CCFadeOutUpTiles +{ +} +// XXX: private, but added to make BridgeSupport happy +-(float)testFunc:(CGSize)pos time:(ccTime)time; +@end + +//////////////////////////////////////////////////////////// + +/** CCTurnOffTiles action. + Turn off the files in random order + */ +@interface CCTurnOffTiles : CCTiledGrid3DAction +{ + unsigned _seed; + NSUInteger _tilesCount; + NSUInteger *_tilesOrder; +} + +/** creates the action with a random seed, the grid size and the duration */ ++(id)actionWithDuration:(ccTime)duration size:(CGSize)gridSize seed:(unsigned)seed; +/** initializes the action with a random seed, the grid size and the duration */ +-(id)initWithDuration:(ccTime)duration size:(CGSize)gridSize seed:(unsigned)seed; +@end + +//////////////////////////////////////////////////////////// + +/** CCWavesTiles3D action. */ +@interface CCWavesTiles3D : CCTiledGrid3DAction +{ + NSUInteger _waves; + float _amplitude; + float _amplitudeRate; +} + +/** waves amplitude */ +@property (nonatomic,readwrite) float amplitude; +/** waves amplitude rate */ +@property (nonatomic,readwrite) float amplitudeRate; + +/** creates the action with a number of waves, the waves amplitude, the grid size and the duration */ ++(id)actionWithDuration:(ccTime)duration size:(CGSize)gridSize waves:(NSUInteger)wav amplitude:(float)amp; +/** initializes the action with a number of waves, the waves amplitude, the grid size and the duration */ +-(id)initWithDuration:(ccTime)duration size:(CGSize)gridSize waves:(NSUInteger)wav amplitude:(float)amp; + +@end + +//////////////////////////////////////////////////////////// + +/** CCJumpTiles3D action. + A sin function is executed to move the tiles across the Z axis + */ +@interface CCJumpTiles3D : CCTiledGrid3DAction +{ + NSUInteger _jumps; + float _amplitude; + float _amplitudeRate; +} + +/** amplitude of the sin*/ +@property (nonatomic,readwrite) float amplitude; +/** amplitude rate */ +@property (nonatomic,readwrite) float amplitudeRate; + +/** creates the action with the number of jumps, the sin amplitude, the grid size and the duration */ ++(id)actionWithDuration:(ccTime)duration size:(CGSize)gridSize jumps:(NSUInteger)numberOfJumps amplitude:(float)amplitude; +/** initializes the action with the number of jumps, the sin amplitude, the grid size and the duration */ +-(id)initWithDuration:(ccTime)duration size:(CGSize)gridSize jumps:(NSUInteger)numberOfJumps amplitude:(float)amplitude; + +@end + +//////////////////////////////////////////////////////////// + +/** CCSplitRows action */ +@interface CCSplitRows : CCTiledGrid3DAction +{ + NSUInteger _rows; + CGSize _winSize; +} +/** creates the action with the number of rows to split and the duration */ ++(id)actionWithDuration:(ccTime)duration rows:(NSUInteger)rows; +/** initializes the action with the number of rows to split and the duration */ +-(id)initWithDuration:(ccTime)duration rows:(NSUInteger)rows; + +@end + +//////////////////////////////////////////////////////////// + +/** CCSplitCols action */ +@interface CCSplitCols : CCTiledGrid3DAction +{ + NSUInteger _cols; + CGSize _winSize; +} +/** creates the action with the number of columns to split and the duration */ ++(id)actionWithDuration:(ccTime)duration cols:(NSUInteger)cols; +/** initializes the action with the number of columns to split and the duration */ +-(id)initWithDuration:(ccTime)duration cols:(NSUInteger)cols; + +@end diff --git "a/21451198\345\215\242\350\266\205/project5/MyPlane/libs/cocos2d/CCActionTiledGrid.m" "b/21451198\345\215\242\350\266\205/project5/MyPlane/libs/cocos2d/CCActionTiledGrid.m" new file mode 100644 index 00000000..0f9bfb83 --- /dev/null +++ "b/21451198\345\215\242\350\266\205/project5/MyPlane/libs/cocos2d/CCActionTiledGrid.m" @@ -0,0 +1,770 @@ +/* + * cocos2d for iPhone: http://www.cocos2d-iphone.org + * + * Copyright (c) 2009 On-Core + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + * THE SOFTWARE. + * + */ + + +#import "CCActionTiledGrid.h" +#import "CCDirector.h" +#import "ccMacros.h" +#import "Support/CGPointExtension.h" + +typedef struct +{ + CGPoint position; + CGPoint startPosition; + CGSize delta; +} Tile; + +#pragma mark - +#pragma mark ShakyTiles3D + +@implementation CCShakyTiles3D + ++(id)actionWithDuration:(ccTime)duration size:(CGSize)gridSize range:(int)range shakeZ:(BOOL)shakeZ +{ + return [[[self alloc] initWithDuration:duration size:gridSize range:range shakeZ:shakeZ] autorelease]; +} + +-(id)initWithDuration:(ccTime)duration size:(CGSize)gridSize range:(int)range shakeZ:(BOOL)shakeZ +{ + if ( (self = [super initWithDuration:duration size:gridSize]) ) + { + _randrange = range; + _shakeZ = shakeZ; + } + + return self; +} + +-(id) copyWithZone: (NSZone*) zone +{ + return [[[self class] allocWithZone:zone] initWithDuration:_duration size:_gridSize range:_randrange shakeZ:_shakeZ]; +} + + +-(void)update:(ccTime)time +{ + int i, j; + + for( i = 0; i < _gridSize.width; i++ ) + { + for( j = 0; j < _gridSize.height; j++ ) + { + ccQuad3 coords = [self originalTile:ccp(i,j)]; + + // X + coords.bl.x += ( rand() % (_randrange*2) ) - _randrange; + coords.br.x += ( rand() % (_randrange*2) ) - _randrange; + coords.tl.x += ( rand() % (_randrange*2) ) - _randrange; + coords.tr.x += ( rand() % (_randrange*2) ) - _randrange; + + // Y + coords.bl.y += ( rand() % (_randrange*2) ) - _randrange; + coords.br.y += ( rand() % (_randrange*2) ) - _randrange; + coords.tl.y += ( rand() % (_randrange*2) ) - _randrange; + coords.tr.y += ( rand() % (_randrange*2) ) - _randrange; + + if( _shakeZ ) { + coords.bl.z += ( rand() % (_randrange*2) ) - _randrange; + coords.br.z += ( rand() % (_randrange*2) ) - _randrange; + coords.tl.z += ( rand() % (_randrange*2) ) - _randrange; + coords.tr.z += ( rand() % (_randrange*2) ) - _randrange; + } + + [self setTile:ccp(i,j) coords:coords]; + } + } +} + +@end + +//////////////////////////////////////////////////////////// + +#pragma mark - +#pragma mark CCShatteredTiles3D + +@implementation CCShatteredTiles3D + ++(id)actionWithDuration:(ccTime)duration size:(CGSize)gridSize range:(int)range shatterZ:(BOOL)shatterZ +{ + return [[[self alloc] initWithDuration:duration size:gridSize range:range shatterZ:shatterZ] autorelease]; +} + +-(id)initWithDuration:(ccTime)duration size:(CGSize)gridSize range:(int)range shatterZ:(BOOL)shatterZ + +{ + if ( (self = [super initWithDuration:duration size:gridSize]) ) + { + _once = NO; + _randrange = range; + _shatterZ = shatterZ; + } + + return self; +} + +-(id) copyWithZone: (NSZone*) zone +{ + return [[[self class] allocWithZone:zone] initWithDuration:_duration size:_gridSize range:_randrange shatterZ:_shatterZ]; +} + + +-(void)update:(ccTime)time +{ + int i, j; + + if ( _once == NO ) + { + for( i = 0; i < _gridSize.width; i++ ) + { + for( j = 0; j < _gridSize.height; j++ ) + { + ccQuad3 coords = [self originalTile:ccp(i,j)]; + + // X + coords.bl.x += ( rand() % (_randrange*2) ) - _randrange; + coords.br.x += ( rand() % (_randrange*2) ) - _randrange; + coords.tl.x += ( rand() % (_randrange*2) ) - _randrange; + coords.tr.x += ( rand() % (_randrange*2) ) - _randrange; + + // Y + coords.bl.y += ( rand() % (_randrange*2) ) - _randrange; + coords.br.y += ( rand() % (_randrange*2) ) - _randrange; + coords.tl.y += ( rand() % (_randrange*2) ) - _randrange; + coords.tr.y += ( rand() % (_randrange*2) ) - _randrange; + + if( _shatterZ ) { + coords.bl.z += ( rand() % (_randrange*2) ) - _randrange; + coords.br.z += ( rand() % (_randrange*2) ) - _randrange; + coords.tl.z += ( rand() % (_randrange*2) ) - _randrange; + coords.tr.z += ( rand() % (_randrange*2) ) - _randrange; + } + + [self setTile:ccp(i,j) coords:coords]; + } + } + + _once = YES; + } +} + +@end + +//////////////////////////////////////////////////////////// + +#pragma mark - +#pragma mark CCShuffleTiles + +@implementation CCShuffleTiles + ++(id)actionWithDuration:(ccTime)duration size:(CGSize)gridSize seed:(unsigned)seed +{ + return [[[self alloc] initWithDuration:duration size:gridSize seed:seed] autorelease]; +} + +-(id)initWithDuration:(ccTime)duration size:(CGSize)gridSize seed:(unsigned)seed +{ + if ( (self = [super initWithDuration:duration size:gridSize]) ) + { + _seed = seed; + _tilesOrder = nil; + _tiles = nil; + } + + return self; +} + +-(id) copyWithZone: (NSZone*) zone +{ + return [[[self class] allocWithZone:zone] initWithDuration:_duration size:_gridSize seed:_seed]; +} + + +-(void)dealloc +{ + if(_tilesOrder) + free(_tilesOrder); + if(_tiles) + free(_tiles); + [super dealloc]; +} + +-(void)shuffle:(NSUInteger*)array count:(NSUInteger)len +{ + NSInteger i; + for( i = len - 1; i >= 0; i-- ) + { + NSInteger j = rand() % (i+1); + NSUInteger v = array[i]; + array[i] = array[j]; + array[j] = v; + } +} + +-(CGSize)getDelta:(CGSize)pos +{ + CGPoint pos2; + + NSUInteger idx = pos.width * _gridSize.height + pos.height; + + pos2.x = _tilesOrder[idx] / (NSUInteger)_gridSize.height; + pos2.y = _tilesOrder[idx] % (NSUInteger)_gridSize.height; + + return CGSizeMake(pos2.x - pos.width, pos2.y - pos.height); +} + +-(void)placeTile:(CGPoint)pos tile:(Tile)t +{ + ccQuad3 coords = [self originalTile:pos]; + + CGPoint step = [[_target grid] step]; + coords.bl.x += (int)(t.position.x * step.x); + coords.bl.y += (int)(t.position.y * step.y); + + coords.br.x += (int)(t.position.x * step.x); + coords.br.y += (int)(t.position.y * step.y); + + coords.tl.x += (int)(t.position.x * step.x); + coords.tl.y += (int)(t.position.y * step.y); + + coords.tr.x += (int)(t.position.x * step.x); + coords.tr.y += (int)(t.position.y * step.y); + + [self setTile:pos coords:coords]; +} + +-(void)startWithTarget:(id)aTarget +{ + [super startWithTarget:aTarget]; + + if ( _seed != -1 ) + srand(_seed); + + _tilesCount = _gridSize.width * _gridSize.height; + _tilesOrder = (NSUInteger*)malloc(_tilesCount*sizeof(NSUInteger)); + int i, j; + + for( i = 0; i < _tilesCount; i++ ) + _tilesOrder[i] = i; + + [self shuffle:_tilesOrder count:_tilesCount]; + + _tiles = malloc(_tilesCount*sizeof(Tile)); + Tile *tileArray = (Tile*)_tiles; + + for( i = 0; i < _gridSize.width; i++ ) + { + for( j = 0; j < _gridSize.height; j++ ) + { + tileArray->position = ccp(i,j); + tileArray->startPosition = ccp(i,j); + tileArray->delta = [self getDelta:CGSizeMake(i,j)]; + tileArray++; + } + } +} + +-(void)update:(ccTime)time +{ + int i, j; + + Tile *tileArray = (Tile*)_tiles; + + for( i = 0; i < _gridSize.width; i++ ) + { + for( j = 0; j < _gridSize.height; j++ ) + { + tileArray->position = ccpMult( ccp(tileArray->delta.width, tileArray->delta.height), time); + [self placeTile:ccp(i,j) tile:*tileArray]; + tileArray++; + } + } +} + +@end + +//////////////////////////////////////////////////////////// + +#pragma mark - +#pragma mark CCFadeOutTRTiles + +@implementation CCFadeOutTRTiles + +-(float)testFunc:(CGSize)pos time:(ccTime)time +{ + CGPoint n = ccpMult( ccp(_gridSize.width,_gridSize.height), time); + if ( (n.x+n.y) == 0.0f ) + return 1.0f; + + return powf( (pos.width+pos.height) / (n.x+n.y), 6 ); +} + +-(void)turnOnTile:(CGPoint)pos +{ + [self setTile:pos coords:[self originalTile:pos]]; +} + +-(void)turnOffTile:(CGPoint)pos +{ + ccQuad3 coords; + bzero(&coords, sizeof(ccQuad3)); + [self setTile:pos coords:coords]; +} + +-(void)transformTile:(CGPoint)pos distance:(float)distance +{ + ccQuad3 coords = [self originalTile:pos]; + CGPoint step = [[_target grid] step]; + + coords.bl.x += (step.x / 2) * (1.0f - distance); + coords.bl.y += (step.y / 2) * (1.0f - distance); + + coords.br.x -= (step.x / 2) * (1.0f - distance); + coords.br.y += (step.y / 2) * (1.0f - distance); + + coords.tl.x += (step.x / 2) * (1.0f - distance); + coords.tl.y -= (step.y / 2) * (1.0f - distance); + + coords.tr.x -= (step.x / 2) * (1.0f - distance); + coords.tr.y -= (step.y / 2) * (1.0f - distance); + + [self setTile:pos coords:coords]; +} + +-(void)update:(ccTime)time +{ + int i, j; + + for( i = 0; i < _gridSize.width; i++ ) + { + for( j = 0; j < _gridSize.height; j++ ) + { + float distance = [self testFunc:CGSizeMake(i,j) time:time]; + if ( distance == 0 ) + [self turnOffTile:ccp(i,j)]; + else if ( distance < 1 ) + [self transformTile:ccp(i,j) distance:distance]; + else + [self turnOnTile:ccp(i,j)]; + } + } +} + +@end + +//////////////////////////////////////////////////////////// + +#pragma mark - +#pragma mark CCFadeOutBLTiles + +@implementation CCFadeOutBLTiles + +-(float)testFunc:(CGSize)pos time:(ccTime)time +{ + CGPoint n = ccpMult(ccp(_gridSize.width, _gridSize.height), (1.0f-time)); + if ( (pos.width+pos.height) == 0 ) + return 1.0f; + + return powf( (n.x+n.y) / (pos.width+pos.height), 6 ); +} + +@end + +//////////////////////////////////////////////////////////// + +#pragma mark - +#pragma mark CCFadeOutUpTiles + +@implementation CCFadeOutUpTiles + +-(float)testFunc:(CGSize)pos time:(ccTime)time +{ + CGPoint n = ccpMult(ccp(_gridSize.width, _gridSize.height), time); + if ( n.y == 0 ) + return 1.0f; + + return powf( pos.height / n.y, 6 ); +} + +-(void)transformTile:(CGPoint)pos distance:(float)distance +{ + ccQuad3 coords = [self originalTile:pos]; + CGPoint step = [[_target grid] step]; + + coords.bl.y += (step.y / 2) * (1.0f - distance); + coords.br.y += (step.y / 2) * (1.0f - distance); + coords.tl.y -= (step.y / 2) * (1.0f - distance); + coords.tr.y -= (step.y / 2) * (1.0f - distance); + + [self setTile:pos coords:coords]; +} + +@end + +//////////////////////////////////////////////////////////// + +#pragma mark - +#pragma mark CCFadeOutDownTiles + +@implementation CCFadeOutDownTiles + +-(float)testFunc:(CGSize)pos time:(ccTime)time +{ + CGPoint n = ccpMult(ccp(_gridSize.width,_gridSize.height), (1.0f - time)); + if ( pos.height == 0 ) + return 1.0f; + + return powf( n.y / pos.height, 6 ); +} + +@end + +//////////////////////////////////////////////////////////// + +#pragma mark - +#pragma mark TurnOffTiles + +@implementation CCTurnOffTiles + ++(id)actionWithDuration:(ccTime)duration size:(CGSize)gridSize seed:(unsigned)seed +{ + return [[[self alloc] initWithDuration:duration size:gridSize seed:seed] autorelease]; +} + +-(id)initWithDuration:(ccTime)duration size:(CGSize)gridSize seed:(unsigned)seed +{ + if ( (self = [super initWithDuration:duration size:gridSize]) ) + { + _seed = seed; + _tilesOrder = nil; + } + + return self; +} + +-(id) copyWithZone: (NSZone*) zone +{ + return [[[self class] allocWithZone:zone] initWithDuration:_duration size:_gridSize seed:_seed]; +} + +-(void)dealloc +{ + if(_tilesOrder) + free(_tilesOrder); + [super dealloc]; +} + +-(void)shuffle:(NSUInteger*)array count:(NSUInteger)len +{ + NSInteger i; + for( i = len - 1; i >= 0; i-- ) + { + NSUInteger j = rand() % (i+1); + NSUInteger v = array[i]; + array[i] = array[j]; + array[j] = v; + } +} + +-(void)turnOnTile:(CGPoint)pos +{ + [self setTile:pos coords:[self originalTile:pos]]; +} + +-(void)turnOffTile:(CGPoint)pos +{ + ccQuad3 coords; + + bzero(&coords, sizeof(ccQuad3)); + [self setTile:pos coords:coords]; +} + +-(void)startWithTarget:(id)aTarget +{ + NSUInteger i; + + [super startWithTarget:aTarget]; + + if ( _seed != -1 ) + srand(_seed); + + _tilesCount = _gridSize.width * _gridSize.height; + _tilesOrder = (NSUInteger*)malloc(_tilesCount*sizeof(NSUInteger)); + + for( i = 0; i < _tilesCount; i++ ) + _tilesOrder[i] = i; + + [self shuffle:_tilesOrder count:_tilesCount]; +} + +-(void)update:(ccTime)time +{ + NSUInteger i, l, t; + + l = (NSUInteger)(time * (float)_tilesCount); + + for( i = 0; i < _tilesCount; i++ ) + { + t = _tilesOrder[i]; + CGPoint tilePos = ccp( (NSUInteger)(t / _gridSize.height), + t % (NSUInteger)_gridSize.height ); + + if ( i < l ) + [self turnOffTile:tilePos]; + else + [self turnOnTile:tilePos]; + } +} + +@end + +//////////////////////////////////////////////////////////// + +#pragma mark - +#pragma mark CCWavesTiles3D + +@implementation CCWavesTiles3D + +@synthesize amplitude = _amplitude; +@synthesize amplitudeRate = _amplitudeRate; + ++(id)actionWithDuration:(ccTime)duration size:(CGSize)gridSize waves:(NSUInteger)wav amplitude:(float)amp +{ + return [[[self alloc] initWithDuration:duration size:gridSize waves:wav amplitude:amp] autorelease]; +} + +-(id)initWithDuration:(ccTime)duration size:(CGSize)gridSize waves:(NSUInteger)wav amplitude:(float)amp +{ + if ( (self = [super initWithDuration:duration size:gridSize]) ) + { + _waves = wav; + _amplitude = amp; + _amplitudeRate = 1.0f; + } + + return self; +} + +-(id) copyWithZone: (NSZone*) zone +{ + CCGridAction *copy = [[[self class] allocWithZone:zone] initWithDuration:_duration size:_gridSize waves:_waves amplitude:_amplitude]; + return copy; +} + + +-(void)update:(ccTime)time +{ + int i, j; + + for( i = 0; i < _gridSize.width; i++ ) + { + for( j = 0; j < _gridSize.height; j++ ) + { + ccQuad3 coords = [self originalTile:ccp(i,j)]; + + coords.bl.z = (sinf(time*(CGFloat)M_PI*_waves*2 + (coords.bl.y+coords.bl.x) * .01f) * _amplitude * _amplitudeRate ); + coords.br.z = coords.bl.z; + coords.tl.z = coords.bl.z; + coords.tr.z = coords.bl.z; + + [self setTile:ccp(i,j) coords:coords]; + } + } +} +@end + +//////////////////////////////////////////////////////////// + +#pragma mark - +#pragma mark CCJumpTiles3D + +@implementation CCJumpTiles3D + +@synthesize amplitude = _amplitude; +@synthesize amplitudeRate = _amplitudeRate; + ++(id)actionWithDuration:(ccTime)duration size:(CGSize)gridSize jumps:(NSUInteger)numberOfJumps amplitude:(float)amplitude +{ + return [[[self alloc] initWithDuration:duration size:gridSize jumps:numberOfJumps amplitude:amplitude] autorelease]; +} + +-(id)initWithDuration:(ccTime)duration size:(CGSize)gridSize jumps:(NSUInteger)numberOfJumps amplitude:(float)amplitude +{ + if ( (self = [super initWithDuration:duration size:gridSize]) ) + { + _jumps = numberOfJumps; + _amplitude = amplitude; + _amplitudeRate = 1.0f; + } + + return self; +} + +-(id) copyWithZone: (NSZone*) zone +{ + CCGridAction *copy = [[[self class] allocWithZone:zone] initWithDuration:_duration size:_gridSize jumps:_jumps amplitude:_amplitude]; + return copy; +} + + +-(void)update:(ccTime)time +{ + int i, j; + + float sinz = (sinf((CGFloat)M_PI*time*_jumps*2) * _amplitude * _amplitudeRate ); + float sinz2 = (sinf((CGFloat)M_PI*(time*_jumps*2 + 1)) * _amplitude * _amplitudeRate ); + + for( i = 0; i < _gridSize.width; i++ ) + { + for( j = 0; j < _gridSize.height; j++ ) + { + ccQuad3 coords = [self originalTile:ccp(i,j)]; + + if ( ((i+j) % 2) == 0 ) + { + coords.bl.z += sinz; + coords.br.z += sinz; + coords.tl.z += sinz; + coords.tr.z += sinz; + } + else + { + coords.bl.z += sinz2; + coords.br.z += sinz2; + coords.tl.z += sinz2; + coords.tr.z += sinz2; + } + + [self setTile:ccp(i,j) coords:coords]; + } + } +} +@end + +//////////////////////////////////////////////////////////// + +#pragma mark - +#pragma mark SplitRows + +@implementation CCSplitRows + ++(id)actionWithDuration:(ccTime)duration rows:(NSUInteger)rows +{ + return [[[self alloc] initWithDuration:duration rows:rows] autorelease]; +} + +-(id)initWithDuration:(ccTime)duration rows:(NSUInteger)rows +{ + if( (self=[super initWithDuration:duration size:CGSizeMake(1,rows)]) ) + _rows = rows; + + return self; +} + +-(id) copyWithZone: (NSZone*) zone +{ + return [[[self class] allocWithZone:zone] initWithDuration:_duration rows:_rows]; +} + +-(void)startWithTarget:(id)aTarget +{ + [super startWithTarget:aTarget]; + _winSize = [[CCDirector sharedDirector] winSizeInPixels]; +} + +-(void)update:(ccTime)time +{ + NSUInteger j; + + for( j = 0; j < _gridSize.height; j++ ) + { + ccQuad3 coords = [self originalTile:ccp(0,j)]; + float direction = 1; + + if ( (j % 2 ) == 0 ) + direction = -1; + + coords.bl.x += direction * _winSize.width * time; + coords.br.x += direction * _winSize.width * time; + coords.tl.x += direction * _winSize.width * time; + coords.tr.x += direction * _winSize.width * time; + + [self setTile:ccp(0,j) coords:coords]; + } +} + +@end + +//////////////////////////////////////////////////////////// + +#pragma mark - +#pragma mark CCSplitCols + +@implementation CCSplitCols + ++(id)actionWithDuration:(ccTime)duration cols:(NSUInteger)cols +{ + return [[[self alloc] initWithDuration:duration cols:cols] autorelease]; +} + +-(id)initWithDuration:(ccTime)duration cols:(NSUInteger)cols +{ + if( (self=[super initWithDuration:duration size:CGSizeMake(cols,1)]) ) + _cols = cols; + return self; +} + +-(id) copyWithZone: (NSZone*) zone +{ + return [[[self class] allocWithZone:zone] initWithDuration:_duration cols:_cols]; +} + +-(void)startWithTarget:(id)aTarget +{ + [super startWithTarget:aTarget]; + _winSize = [[CCDirector sharedDirector] winSizeInPixels]; +} + +-(void)update:(ccTime)time +{ + NSUInteger i; + + for( i = 0; i < _gridSize.width; i++ ) + { + ccQuad3 coords = [self originalTile:ccp(i,0)]; + float direction = 1; + + if ( (i % 2 ) == 0 ) + direction = -1; + + coords.bl.y += direction * _winSize.height * time; + coords.br.y += direction * _winSize.height * time; + coords.tl.y += direction * _winSize.height * time; + coords.tr.y += direction * _winSize.height * time; + + [self setTile:ccp(i,0) coords:coords]; + } +} + +@end diff --git "a/21451198\345\215\242\350\266\205/project5/MyPlane/libs/cocos2d/CCActionTween.h" "b/21451198\345\215\242\350\266\205/project5/MyPlane/libs/cocos2d/CCActionTween.h" new file mode 100644 index 00000000..3186e95f --- /dev/null +++ "b/21451198\345\215\242\350\266\205/project5/MyPlane/libs/cocos2d/CCActionTween.h" @@ -0,0 +1,62 @@ +/* + * cocos2d for iPhone: http://www.cocos2d-iphone.org + * + * Copyright 2009 lhunath (Maarten Billemont) + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + * THE SOFTWARE. + * + */ + + +#import +#import "CCActionInterval.h" + +/** CCActionTween + + CCActionTween is an action that lets you update any property of an object. + For example, if you want to modify the "width" property of a target from 200 to 300 in 2 seconds, then: + + id modifyWidth = [CCActionTween actionWithDuration:2 key:@"width" from:200 to:300]; + [target runAction:modifyWidth]; + + + Another example: CCScaleTo action could be rewriten using CCPropertyAction: + + // scaleA and scaleB are equivalents + id scaleA = [CCScaleTo actionWithDuration:2 scale:3]; + id scaleB = [CCActionTween actionWithDuration:2 key:@"scale" from:1 to:3]; + + + @since v0.99.2 + */ +@interface CCActionTween : CCActionInterval +{ + NSString *_key; + + float _from, _to; + float _delta; +} + +/** creates an initializes the action with the property name (key), and the from and to parameters. */ ++ (id)actionWithDuration:(ccTime)aDuration key:(NSString *)key from:(float)from to:(float)to; + +/** initializes the action with the property name (key), and the from and to parameters. */ +- (id)initWithDuration:(ccTime)aDuration key:(NSString *)key from:(float)from to:(float)to; + +@end diff --git "a/21451198\345\215\242\350\266\205/project5/MyPlane/libs/cocos2d/CCActionTween.m" "b/21451198\345\215\242\350\266\205/project5/MyPlane/libs/cocos2d/CCActionTween.m" new file mode 100644 index 00000000..ba2cb803 --- /dev/null +++ "b/21451198\345\215\242\350\266\205/project5/MyPlane/libs/cocos2d/CCActionTween.m" @@ -0,0 +1,72 @@ +/* + * cocos2d for iPhone: http://www.cocos2d-iphone.org + * + * Copyright 2009 lhunath (Maarten Billemont) + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + * THE SOFTWARE. + * + */ + +#import "CCActionTween.h" + + +@implementation CCActionTween + ++ (id)actionWithDuration:(ccTime)aDuration key:(NSString *)aKey from:(float)aFrom to:(float)aTo { + + return [[[[self class] alloc] initWithDuration:aDuration key:aKey from:aFrom to:aTo] autorelease]; +} + +- (id)initWithDuration:(ccTime)aDuration key:(NSString *)key from:(float)from to:(float)to { + + if ((self = [super initWithDuration:aDuration])) { + + _key = [key copy]; + _to = to; + _from = from; + + } + + return self; +} + +- (void) dealloc +{ + [_key release]; + [super dealloc]; +} + +- (void)startWithTarget:aTarget +{ + [super startWithTarget:aTarget]; + _delta = _to - _from; +} + +- (void) update:(ccTime) dt +{ + [_target setValue:[NSNumber numberWithFloat:_to - _delta * (1 - dt)] forKey:_key]; +} + +- (CCActionInterval *) reverse +{ + return [[self class] actionWithDuration:_duration key:_key from:_to to:_from]; +} + + +@end diff --git "a/21451198\345\215\242\350\266\205/project5/MyPlane/libs/cocos2d/CCAnimation.h" "b/21451198\345\215\242\350\266\205/project5/MyPlane/libs/cocos2d/CCAnimation.h" new file mode 100644 index 00000000..4f74018a --- /dev/null +++ "b/21451198\345\215\242\350\266\205/project5/MyPlane/libs/cocos2d/CCAnimation.h" @@ -0,0 +1,150 @@ +/* + * cocos2d for iPhone: http://www.cocos2d-iphone.org + * + * Copyright (c) 2008-2010 Ricardo Quesada + * Copyright (c) 2011 Zynga Inc. + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + * THE SOFTWARE. + * + */ + +#import +#ifdef __CC_PLATFORM_IOS +#import +#endif // IPHONE + +@class CCSpriteFrame; +@class CCTexture2D; +@class CCSpriteFrame; + +/** CCAnimationFrame + A frame of the animation. It contains information like: + - sprite frame name + - # of delay units. + - offset + + @since v2.0 + */ +@interface CCAnimationFrame : NSObject +{ + CCSpriteFrame* _spriteFrame; + float _delayUnits; + NSDictionary *_userInfo; +} +/** CCSpriteFrameName to be used */ +@property (nonatomic, readwrite, retain) CCSpriteFrame* spriteFrame; + +/** how many units of time the frame takes */ +@property (nonatomic, readwrite) float delayUnits; + +/** A CCAnimationFrameDisplayedNotification notification will be broadcasted when the frame is displayed with this dictionary as UserInfo. If UserInfo is nil, then no notification will be broadcasted. */ +@property (nonatomic, readwrite, retain) NSDictionary *userInfo; + +/** initializes the animation frame with a spriteframe, number of delay units and a notification user info */ +-(id) initWithSpriteFrame:(CCSpriteFrame*)spriteFrame delayUnits:(float)delayUnits userInfo:(NSDictionary*)userInfo; +@end + +/** A CCAnimation object is used to perform animations on the CCSprite objects. + + The CCAnimation object contains CCAnimationFrame objects, and a possible delay between the frames. + You can animate a CCAnimation object by using the CCAnimate action. Example: + + [sprite runAction:[CCAnimate actionWithAnimation:animation]]; + + */ +@interface CCAnimation : NSObject +{ + NSMutableArray *_frames; + float _totalDelayUnits; + float _delayPerUnit; + BOOL _restoreOriginalFrame; + NSUInteger _loops; +} + +/** total Delay units of the CCAnimation. */ +@property (nonatomic, readonly) float totalDelayUnits; +/** Delay in seconds of the "delay unit" */ +@property (nonatomic, readwrite) float delayPerUnit; +/** duration in seconds of the whole animation. It is the result of totalDelayUnits * delayPerUnit */ +@property (nonatomic,readonly) float duration; +/** array of CCAnimationFrames */ +@property (nonatomic,readwrite,retain) NSMutableArray *frames; +/** whether or not it shall restore the original frame when the animation finishes */ +@property (nonatomic,readwrite) BOOL restoreOriginalFrame; +/** how many times the animation is going to loop. 0 means animation is not animated. 1, animation is executed one time, ... */ +@property (nonatomic, readwrite) NSUInteger loops; + +/** Creates an animation + @since v0.99.5 + */ ++(id) animation; + +/** Creates an animation with an array of CCSpriteFrame. + The frames will be created with one "delay unit". + @since v0.99.5 + */ ++(id) animationWithSpriteFrames:(NSArray*)arrayOfSpriteFrameNames; + +/* Creates an animation with an array of CCSpriteFrame and a delay between frames in seconds. + The frames will be added with one "delay unit". + @since v0.99.5 + */ ++(id) animationWithSpriteFrames:(NSArray*)arrayOfSpriteFrameNames delay:(float)delay; + +/* Creates an animation with an array of CCAnimationFrame, the delay per units in seconds and and how many times it should be executed. + @since v2.0 + */ ++(id) animationWithAnimationFrames:(NSArray*)arrayOfAnimationFrames delayPerUnit:(float)delayPerUnit loops:(NSUInteger)loops; + + +/** Initializes a CCAnimation with an array of CCSpriteFrame. + The frames will be added with one "delay unit". + @since v0.99.5 +*/ +-(id) initWithSpriteFrames:(NSArray*)arrayOfSpriteFrameNames; + +/** Initializes a CCAnimation with an array of CCSpriteFrames and a delay between frames in seconds. + The frames will be added with one "delay unit". + @since v0.99.5 + */ +-(id) initWithSpriteFrames:(NSArray *)arrayOfSpriteFrameNames delay:(float)delay; + +/* Initializes an animation with an array of CCAnimationFrame and the delay per units in seconds. + @since v2.0 + */ +-(id) initWithAnimationFrames:(NSArray*)arrayOfAnimationFrames delayPerUnit:(float)delayPerUnit loops:(NSUInteger)loops; + +/** Adds a CCSpriteFrame to a CCAnimation. + The frame will be added with one "delay unit". +*/ +-(void) addSpriteFrame:(CCSpriteFrame*)frame; + +/** Adds a frame with an image filename. Internally it will create a CCSpriteFrame and it will add it. + The frame will be added with one "delay unit". + Added to facilitate the migration from v0.8 to v0.9. + */ +-(void) addSpriteFrameWithFilename:(NSString*)filename; + +/** Adds a frame with a texture and a rect. Internally it will create a CCSpriteFrame and it will add it. + The frame will be added with one "delay unit". + Added to facilitate the migration from v0.8 to v0.9. + */ +-(void) addSpriteFrameWithTexture:(CCTexture2D*)texture rect:(CGRect)rect; + +@end diff --git "a/21451198\345\215\242\350\266\205/project5/MyPlane/libs/cocos2d/CCAnimation.m" "b/21451198\345\215\242\350\266\205/project5/MyPlane/libs/cocos2d/CCAnimation.m" new file mode 100644 index 00000000..f1f4b7d7 --- /dev/null +++ "b/21451198\345\215\242\350\266\205/project5/MyPlane/libs/cocos2d/CCAnimation.m" @@ -0,0 +1,200 @@ +/* + * cocos2d for iPhone: http://www.cocos2d-iphone.org + * + * Copyright (c) 2008-2010 Ricardo Quesada + * Copyright (c) 2011 Zynga Inc. + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + * THE SOFTWARE. + * + */ + +#import "ccMacros.h" +#import "CCAnimation.h" +#import "CCSpriteFrame.h" +#import "CCTexture2D.h" +#import "CCTextureCache.h" + +#pragma mark - CCAnimationFrame +@implementation CCAnimationFrame + +@synthesize spriteFrame = _spriteFrame, delayUnits = _delayUnits, userInfo=_userInfo; + +-(id) initWithSpriteFrame:(CCSpriteFrame *)spriteFrame delayUnits:(float)delayUnits userInfo:(NSDictionary*)userInfo +{ + if( (self=[super init]) ) { + self.spriteFrame = spriteFrame; + self.delayUnits = delayUnits; + self.userInfo = userInfo; + } + + return self; +} + +-(void) dealloc +{ + CCLOGINFO( @"cocos2d: deallocing %@", self); + + [_spriteFrame release]; + [_userInfo release]; + + [super dealloc]; +} + +-(id) copyWithZone: (NSZone*) zone +{ + CCAnimationFrame *copy = [[[self class] allocWithZone: zone] initWithSpriteFrame:[[_spriteFrame copy] autorelease] delayUnits:_delayUnits userInfo:[[_userInfo copy] autorelease] ]; + return copy; +} + +-(NSString*) description +{ + return [NSString stringWithFormat:@"<%@ = %p | SpriteFrame = %p, delayUnits = %0.2f >", [self class], self, _spriteFrame, _delayUnits ]; +} +@end + + +#pragma mark - CCAnimation + +@implementation CCAnimation +@synthesize frames = _frames, totalDelayUnits=_totalDelayUnits, delayPerUnit=_delayPerUnit, restoreOriginalFrame=_restoreOriginalFrame, loops=_loops; + ++(id) animation +{ + return [[[self alloc] init] autorelease]; +} + ++(id) animationWithSpriteFrames:(NSArray*)frames +{ + return [[[self alloc] initWithSpriteFrames:frames] autorelease]; +} + ++(id) animationWithSpriteFrames:(NSArray*)frames delay:(float)delay +{ + return [[[self alloc] initWithSpriteFrames:frames delay:delay] autorelease]; +} + ++(id) animationWithAnimationFrames:(NSArray*)arrayOfAnimationFrames delayPerUnit:(float)delayPerUnit loops:(NSUInteger)loops +{ + return [[[self alloc] initWithAnimationFrames:arrayOfAnimationFrames delayPerUnit:delayPerUnit loops:loops] autorelease]; +} + +-(id) init +{ + return [self initWithSpriteFrames:nil delay:0]; +} + +-(id) initWithSpriteFrames:(NSArray*)frames +{ + return [self initWithSpriteFrames:frames delay:0]; +} + +-(id) initWithSpriteFrames:(NSArray*)array delay:(float)delay +{ + if( (self=[super init]) ) + { + _loops = 1; + _delayPerUnit = delay; + + self.frames = [NSMutableArray arrayWithCapacity:[array count]]; + + for( CCSpriteFrame *frame in array ) { + CCAnimationFrame *animFrame = [[CCAnimationFrame alloc] initWithSpriteFrame:frame delayUnits:1 userInfo:nil]; + + [self.frames addObject:animFrame]; + [animFrame release]; + _totalDelayUnits++; + } + + } + return self; +} + +-(id) initWithAnimationFrames:(NSArray*)arrayOfAnimationFrames delayPerUnit:(float)delayPerUnit loops:(NSUInteger)loops +{ + if( ( self=[super init]) ) + { + _delayPerUnit = delayPerUnit; + _loops = loops; + + self.frames = [NSMutableArray arrayWithArray:arrayOfAnimationFrames]; + + for( CCAnimationFrame *animFrame in _frames ) + _totalDelayUnits += animFrame.delayUnits; + } + return self; +} + +- (NSString*) description +{ + return [NSString stringWithFormat:@"<%@ = %p | frames=%lu, totalDelayUnits=%f, delayPerUnit=%f, loops=%lu>", [self class], self, + (unsigned long)[_frames count], + _totalDelayUnits, + _delayPerUnit, + (unsigned long)_loops + ]; +} + +-(float) duration +{ + return _totalDelayUnits * _delayPerUnit; +} + +- (id)copyWithZone:(NSZone *)zone +{ + CCAnimation *animation = [[[self class] allocWithZone: zone] initWithAnimationFrames:_frames delayPerUnit:_delayPerUnit loops:_loops]; + animation.restoreOriginalFrame = _restoreOriginalFrame; + + return animation; +} + +-(void) dealloc +{ + CCLOGINFO( @"cocos2d: deallocing %@",self); + + [_frames release]; + [super dealloc]; +} + +-(void) addSpriteFrame:(CCSpriteFrame*)frame +{ + CCAnimationFrame *animFrame = [[CCAnimationFrame alloc] initWithSpriteFrame:frame delayUnits:1 userInfo:nil]; + [_frames addObject:animFrame]; + [animFrame release]; + + // update duration + _totalDelayUnits++; +} + +-(void) addSpriteFrameWithFilename:(NSString*)filename +{ + CCTexture2D *texture = [[CCTextureCache sharedTextureCache] addImage:filename]; + CGRect rect = CGRectZero; + rect.size = texture.contentSize; + CCSpriteFrame *spriteFrame = [CCSpriteFrame frameWithTexture:texture rect:rect]; + + [self addSpriteFrame:spriteFrame]; +} + +-(void) addSpriteFrameWithTexture:(CCTexture2D*)texture rect:(CGRect)rect +{ + CCSpriteFrame *frame = [CCSpriteFrame frameWithTexture:texture rect:rect]; + [self addSpriteFrame:frame]; +} + +@end diff --git "a/21451198\345\215\242\350\266\205/project5/MyPlane/libs/cocos2d/CCAnimationCache.h" "b/21451198\345\215\242\350\266\205/project5/MyPlane/libs/cocos2d/CCAnimationCache.h" new file mode 100644 index 00000000..2684a863 --- /dev/null +++ "b/21451198\345\215\242\350\266\205/project5/MyPlane/libs/cocos2d/CCAnimationCache.h" @@ -0,0 +1,74 @@ +/* + * cocos2d for iPhone: http://www.cocos2d-iphone.org + * + * Copyright (c) 2010 Ricardo Quesada + * Copyright (c) 2011 Zynga Inc. + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + * THE SOFTWARE. + * + */ + +#import + +@class CCAnimation; + +/** Singleton that manages the CCAnimation objects. + It saves in a cache the animations. You should use this class if you want to save your animations in a cache. + + @since v0.99.5 + */ +@interface CCAnimationCache : NSObject +{ + NSMutableDictionary *_animations; +} + +/** Returns the shared instance of the Animation cache */ ++ (CCAnimationCache *) sharedAnimationCache; + +/** Purges the cache. It releases all the CCAnimation objects and the shared instance. + */ ++(void)purgeSharedAnimationCache; + +/** Adds a CCAnimation with a name. + */ +-(void) addAnimation:(CCAnimation*)animation name:(NSString*)name; + +/** Deletes a CCAnimation from the cache. + */ +-(void) removeAnimationByName:(NSString*)name; + +/** Returns a CCAnimation that was previously added. + If the name is not found it will return nil. + You should retain the returned copy if you are going to use it. + */ +-(CCAnimation*) animationByName:(NSString*)name; + +/** Adds an animation from an NSDictionary + Make sure that the frames were previously loaded in the CCSpriteFrameCache. + @since v1.1 + */ +-(void)addAnimationsWithDictionary:(NSDictionary *)dictionary; + +/** Adds an animation from a plist file. + Make sure that the frames were previously loaded in the CCSpriteFrameCache. + @since v1.1 + */ +-(void)addAnimationsWithFile:(NSString *)plist; + +@end diff --git "a/21451198\345\215\242\350\266\205/project5/MyPlane/libs/cocos2d/CCAnimationCache.m" "b/21451198\345\215\242\350\266\205/project5/MyPlane/libs/cocos2d/CCAnimationCache.m" new file mode 100644 index 00000000..ac5ae50b --- /dev/null +++ "b/21451198\345\215\242\350\266\205/project5/MyPlane/libs/cocos2d/CCAnimationCache.m" @@ -0,0 +1,250 @@ +/* + * cocos2d for iPhone: http://www.cocos2d-iphone.org + * + * Copyright (c) 2010 Ricardo Quesada + * Copyright (c) 2011 Zynga Inc. + * + * Copyright (c) 2011 John Wordsworth + * + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + * THE SOFTWARE. + * + */ + +#import "CCAnimationCache.h" +#import "ccMacros.h" +#import "CCSpriteFrameCache.h" +#import "CCAnimation.h" +#import "CCSprite.h" +#import "Support/CCFileUtils.h" + + +@implementation CCAnimationCache + +#pragma mark CCAnimationCache - Alloc, Init & Dealloc + +static CCAnimationCache *_sharedAnimationCache=nil; + ++ (CCAnimationCache *)sharedAnimationCache +{ + if (!_sharedAnimationCache) + _sharedAnimationCache = [[CCAnimationCache alloc] init]; + + return _sharedAnimationCache; +} + ++(id)alloc +{ + NSAssert(_sharedAnimationCache == nil, @"Attempted to allocate a second instance of a singleton."); + return [super alloc]; +} + ++(void)purgeSharedAnimationCache +{ + [_sharedAnimationCache release]; + _sharedAnimationCache = nil; +} + +-(id) init +{ + if( (self=[super init]) ) { + _animations = [[NSMutableDictionary alloc] initWithCapacity: 20]; + } + + return self; +} + +- (NSString*) description +{ + return [NSString stringWithFormat:@"<%@ = %p | num of animations = %lu>", [self class], self, (unsigned long)[_animations count]]; +} + +-(void) dealloc +{ + CCLOGINFO(@"cocos2d: deallocing %@", self); + + [_animations release]; + [super dealloc]; +} + +#pragma mark CCAnimationCache - load/get/del + +-(void) addAnimation:(CCAnimation*)animation name:(NSString*)name +{ + [_animations setObject:animation forKey:name]; +} + +-(void) removeAnimationByName:(NSString*)name +{ + if( ! name ) + return; + + [_animations removeObjectForKey:name]; +} + +-(CCAnimation*) animationByName:(NSString*)name +{ + return [_animations objectForKey:name]; +} + +#pragma mark CCAnimationCache - from file + +-(void) parseVersion1:(NSDictionary*)animations +{ + NSArray* animationNames = [animations allKeys]; + CCSpriteFrameCache *frameCache = [CCSpriteFrameCache sharedSpriteFrameCache]; + + for( NSString *name in animationNames ) { + NSDictionary* animationDict = [animations objectForKey:name]; + NSArray *frameNames = [animationDict objectForKey:@"frames"]; + NSNumber *delay = [animationDict objectForKey:@"delay"]; + CCAnimation* animation = nil; + + if ( frameNames == nil ) { + CCLOG(@"cocos2d: CCAnimationCache: Animation '%@' found in dictionary without any frames - cannot add to animation cache.", name); + continue; + } + + NSMutableArray *frames = [NSMutableArray arrayWithCapacity:[frameNames count]]; + + for( NSString *frameName in frameNames ) { + CCSpriteFrame *spriteFrame = [frameCache spriteFrameByName:frameName]; + + if ( ! spriteFrame ) { + CCLOG(@"cocos2d: CCAnimationCache: Animation '%@' refers to frame '%@' which is not currently in the CCSpriteFrameCache. This frame will not be added to the animation.", name, frameName); + + continue; + } + + CCAnimationFrame *animFrame = [[CCAnimationFrame alloc] initWithSpriteFrame:spriteFrame delayUnits:1 userInfo:nil]; + [frames addObject:animFrame]; + [animFrame release]; + } + + if ( [frames count] == 0 ) { + CCLOG(@"cocos2d: CCAnimationCache: None of the frames for animation '%@' were found in the CCSpriteFrameCache. Animation is not being added to the Animation Cache.", name); + continue; + } else if ( [frames count] != [frameNames count] ) { + CCLOG(@"cocos2d: CCAnimationCache: An animation in your dictionary refers to a frame which is not in the CCSpriteFrameCache. Some or all of the frames for the animation '%@' may be missing.", name); + } + + animation = [CCAnimation animationWithAnimationFrames:frames delayPerUnit:[delay floatValue] loops:1 ]; + + [[CCAnimationCache sharedAnimationCache] addAnimation:animation name:name]; + } +} + +-(void) parseVersion2:(NSDictionary*)animations +{ + NSArray* animationNames = [animations allKeys]; + CCSpriteFrameCache *frameCache = [CCSpriteFrameCache sharedSpriteFrameCache]; + + for( NSString *name in animationNames ) + { + NSDictionary* animationDict = [animations objectForKey:name]; + + NSNumber *loops = [animationDict objectForKey:@"loops"]; + BOOL restoreOriginalFrame = [[animationDict objectForKey:@"restoreOriginalFrame"] boolValue]; + NSArray *frameArray = [animationDict objectForKey:@"frames"]; + + + if ( frameArray == nil ) { + CCLOG(@"cocos2d: CCAnimationCache: Animation '%@' found in dictionary without any frames - cannot add to animation cache.", name); + continue; + } + + // Array of AnimationFrames + NSMutableArray *array = [[NSMutableArray alloc] initWithCapacity:[frameArray count]]; + + for( NSDictionary *entry in frameArray ) { + NSString *spriteFrameName = [entry objectForKey:@"spriteframe"]; + CCSpriteFrame *spriteFrame = [frameCache spriteFrameByName:spriteFrameName]; + + if( ! spriteFrame ) { + CCLOG(@"cocos2d: CCAnimationCache: Animation '%@' refers to frame '%@' which is not currently in the CCSpriteFrameCache. This frame will not be added to the animation.", name, spriteFrameName); + + continue; + } + + float delayUnits = [[entry objectForKey:@"delayUnits"] floatValue]; + NSDictionary *userInfo = [entry objectForKey:@"notification"]; + + CCAnimationFrame *animFrame = [[CCAnimationFrame alloc] initWithSpriteFrame:spriteFrame delayUnits:delayUnits userInfo:userInfo]; + + [array addObject:animFrame]; + [animFrame release]; + } + + float delayPerUnit = [[animationDict objectForKey:@"delayPerUnit"] floatValue]; + CCAnimation *animation = [[CCAnimation alloc] initWithAnimationFrames:array delayPerUnit:delayPerUnit loops:(loops?[loops intValue]:1)]; + [array release]; + + [animation setRestoreOriginalFrame:restoreOriginalFrame]; + + [[CCAnimationCache sharedAnimationCache] addAnimation:animation name:name]; + [animation release]; + } +} + +-(void)addAnimationsWithDictionary:(NSDictionary *)dictionary +{ + NSDictionary *animations = [dictionary objectForKey:@"animations"]; + + if ( animations == nil ) { + CCLOG(@"cocos2d: CCAnimationCache: No animations were found in provided dictionary."); + return; + } + + NSUInteger version = 1; + NSDictionary *properties = [dictionary objectForKey:@"properties"]; + if( properties ) + version = [[properties objectForKey:@"format"] intValue]; + + NSArray *spritesheets = [properties objectForKey:@"spritesheets"]; + for( NSString *name in spritesheets ) + [[CCSpriteFrameCache sharedSpriteFrameCache] addSpriteFramesWithFile:name]; + + switch (version) { + case 1: + [self parseVersion1:animations]; + break; + case 2: + [self parseVersion2:animations]; + break; + default: + NSAssert(NO, @"Invalid animation format"); + } +} + + +/** Read an NSDictionary from a plist file and parse it automatically for animations */ +-(void)addAnimationsWithFile:(NSString *)plist +{ + NSAssert( plist, @"Invalid texture file name"); + + NSString *path = [[CCFileUtils sharedFileUtils] fullPathForFilename:plist]; + NSDictionary *dict = [NSDictionary dictionaryWithContentsOfFile:path]; + + NSAssert1( dict, @"CCAnimationCache: File could not be found: %@", plist); + + + [self addAnimationsWithDictionary:dict]; +} + +@end diff --git "a/21451198\345\215\242\350\266\205/project5/MyPlane/libs/cocos2d/CCAtlasNode.h" "b/21451198\345\215\242\350\266\205/project5/MyPlane/libs/cocos2d/CCAtlasNode.h" new file mode 100644 index 00000000..b97d8546 --- /dev/null +++ "b/21451198\345\215\242\350\266\205/project5/MyPlane/libs/cocos2d/CCAtlasNode.h" @@ -0,0 +1,98 @@ +/* + * cocos2d for iPhone: http://www.cocos2d-iphone.org + * + * Copyright (c) 2008-2010 Ricardo Quesada + * Copyright (c) 2011 Zynga Inc. + * + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + * THE SOFTWARE. + */ + + +#import "CCTextureAtlas.h" +#import "CCNode.h" +#import "CCProtocols.h" + +@class CCTexture2D; + +/** CCAtlasNode is a subclass of CCNode that implements the CCRGBAProtocol and + CCTextureProtocol protocol + + It knows how to render a TextureAtlas object. + If you are going to render a TextureAtlas consider sub-classing CCAtlasNode (or a subclass of CCAtlasNode) + + All features from CCNode are valid, plus the following features: + - opacity and RGB colors + */ +@interface CCAtlasNode : CCNodeRGBA +{ + // texture atlas + CCTextureAtlas *_textureAtlas; + + // chars per row + NSUInteger _itemsPerRow; + // chars per column + NSUInteger _itemsPerColumn; + + // width of each char + NSUInteger _itemWidth; + // height of each char + NSUInteger _itemHeight; + + // quads to draw + NSUInteger _quadsToDraw; + + // blend function + ccBlendFunc _blendFunc; + + // texture RGBA. + ccColor3B _colorUnmodified; + BOOL _opacityModifyRGB; + + // color uniform + GLint _uniformColor; +} + +/** conforms to CCTextureProtocol protocol */ +@property (nonatomic,readwrite,retain) CCTextureAtlas *textureAtlas; + +/** conforms to CCTextureProtocol protocol */ +@property (nonatomic,readwrite) ccBlendFunc blendFunc; + +/** conforms to CCRGBAProtocol protocol */ +@property (nonatomic,readwrite) ccColor3B color; + +/** how many quads to draw */ +@property (nonatomic,readwrite) NSUInteger quadsToDraw; + +/** creates a CCAtlasNode with an Atlas file the width and height of each item measured in points and the quantity of items to render*/ ++(id) atlasWithTileFile:(NSString*)tile tileWidth:(NSUInteger)w tileHeight:(NSUInteger)h itemsToRender: (NSUInteger) c; + +/** initializes an CCAtlasNode with an Atlas file the width and height of each item measured in points and the quantity of items to render*/ +-(id) initWithTileFile:(NSString*)tile tileWidth:(NSUInteger)w tileHeight:(NSUInteger)h itemsToRender: (NSUInteger) c; + +/** initializes an CCAtlasNode with a texture the width and height of each item measured in points and the quantity of items to render*/ +-(id) initWithTexture:(CCTexture2D*)texture tileWidth:(NSUInteger)w tileHeight:(NSUInteger)h itemsToRender: (NSUInteger) c; + + +/** updates the Atlas (indexed vertex array). + * Shall be overridden in subclasses + */ +-(void) updateAtlasValues; +@end diff --git "a/21451198\345\215\242\350\266\205/project5/MyPlane/libs/cocos2d/CCAtlasNode.m" "b/21451198\345\215\242\350\266\205/project5/MyPlane/libs/cocos2d/CCAtlasNode.m" new file mode 100644 index 00000000..4c340509 --- /dev/null +++ "b/21451198\345\215\242\350\266\205/project5/MyPlane/libs/cocos2d/CCAtlasNode.m" @@ -0,0 +1,212 @@ +/* + * cocos2d for iPhone: http://www.cocos2d-iphone.org + * + * Copyright (c) 2008-2010 Ricardo Quesada + * Copyright (c) 2011 Zynga Inc. + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + * THE SOFTWARE. + */ + + +#import "CCAtlasNode.h" +#import "ccMacros.h" +#import "CCGLProgram.h" +#import "CCTextureCache.h" +#import "CCShaderCache.h" +#import "ccGLStateCache.h" +#import "CCDirector.h" +#import "Support/TransformUtils.h" + +// external +#import "kazmath/GL/matrix.h" + + +@interface CCAtlasNode () +-(void) calculateMaxItems; +-(void) updateBlendFunc; +-(void) updateOpacityModifyRGB; +@end + +@implementation CCAtlasNode + +@synthesize textureAtlas = _textureAtlas; +@synthesize blendFunc = _blendFunc; +@synthesize quadsToDraw = _quadsToDraw; + +#pragma mark CCAtlasNode - Creation & Init +- (id) init +{ + NSAssert( NO, @"Not supported - Use initWtihTileFile instead"); + return self; +} + ++(id) atlasWithTileFile:(NSString*)tile tileWidth:(NSUInteger)w tileHeight:(NSUInteger)h itemsToRender: (NSUInteger) c +{ + return [[[self alloc] initWithTileFile:tile tileWidth:w tileHeight:h itemsToRender:c] autorelease]; +} + +-(id) initWithTileFile:(NSString*)filename tileWidth:(NSUInteger)w tileHeight:(NSUInteger)h itemsToRender: (NSUInteger) c +{ + CCTexture2D *texture = [[CCTextureCache sharedTextureCache] addImage:filename]; + return [self initWithTexture:texture tileWidth:w tileHeight:h itemsToRender:c]; +} + +-(id) initWithTexture:(CCTexture2D*)texture tileWidth:(NSUInteger)w tileHeight:(NSUInteger)h itemsToRender: (NSUInteger) c; +{ + if( (self=[super init]) ) { + + _itemWidth = w; + _itemHeight = h; + + _colorUnmodified = ccWHITE; + _opacityModifyRGB = YES; + + _blendFunc.src = CC_BLEND_SRC; + _blendFunc.dst = CC_BLEND_DST; + + _textureAtlas = [[CCTextureAtlas alloc] initWithTexture:texture capacity:c]; + + if( ! _textureAtlas ) { + CCLOG(@"cocos2d: Could not initialize CCAtlasNode. Invalid Texture"); + [self release]; + return nil; + } + + [self updateBlendFunc]; + [self updateOpacityModifyRGB]; + + [self calculateMaxItems]; + + self.quadsToDraw = c; + + // shader stuff + self.shaderProgram = [[CCShaderCache sharedShaderCache] programForKey:kCCShader_PositionTexture_uColor]; + _uniformColor = glGetUniformLocation( _shaderProgram.program, "u_color"); + } + return self; +} + +-(void) dealloc +{ + [_textureAtlas release]; + + [super dealloc]; +} + +#pragma mark CCAtlasNode - Atlas generation + +-(void) calculateMaxItems +{ + CGSize s = [[_textureAtlas texture] contentSize]; + _itemsPerColumn = s.height / _itemHeight; + _itemsPerRow = s.width / _itemWidth; +} + +-(void) updateAtlasValues +{ + [NSException raise:@"CCAtlasNode:Abstract" format:@"updateAtlasValue not overriden"]; +} + +#pragma mark CCAtlasNode - draw +- (void) draw +{ + CC_NODE_DRAW_SETUP(); + + ccGLBlendFunc( _blendFunc.src, _blendFunc.dst ); + + GLfloat colors[4] = { _displayedColor.r / 255.0f, + _displayedColor.g / 255.0f, + _displayedColor.b / 255.0f, + _displayedOpacity / 255.0f}; + [_shaderProgram setUniformLocation:_uniformColor with4fv:colors count:1]; + + [_textureAtlas drawNumberOfQuads:_quadsToDraw fromIndex:0]; +} + +#pragma mark CCAtlasNode - RGBA protocol + +- (ccColor3B) color +{ + if (_opacityModifyRGB) + return _colorUnmodified; + + return super.color; +} + +-(void) setColor:(ccColor3B)color3 +{ + _colorUnmodified = color3; + + if( _opacityModifyRGB ){ + color3.r = color3.r * _displayedOpacity/255; + color3.g = color3.g * _displayedOpacity/255; + color3.b = color3.b * _displayedOpacity/255; + } + [super setColor:color3]; +} + +-(void) setOpacity:(GLubyte) anOpacity +{ + [super setOpacity:anOpacity]; + + // special opacity for premultiplied textures + if( _opacityModifyRGB ) + [self setColor: _colorUnmodified]; +} + +-(void) setOpacityModifyRGB:(BOOL)modify +{ + ccColor3B oldColor = self.color; + _opacityModifyRGB = modify; + self.color = oldColor; +} + +-(BOOL) doesOpacityModifyRGB +{ + return _opacityModifyRGB; +} + +-(void) updateOpacityModifyRGB +{ + _opacityModifyRGB = [_textureAtlas.texture hasPremultipliedAlpha]; +} + +#pragma mark CCAtlasNode - CCNodeTexture protocol + +-(void) updateBlendFunc +{ + if( ! [_textureAtlas.texture hasPremultipliedAlpha] ) { + _blendFunc.src = GL_SRC_ALPHA; + _blendFunc.dst = GL_ONE_MINUS_SRC_ALPHA; + } +} + +-(void) setTexture:(CCTexture2D*)texture +{ + _textureAtlas.texture = texture; + [self updateBlendFunc]; + [self updateOpacityModifyRGB]; +} + +-(CCTexture2D*) texture +{ + return _textureAtlas.texture; +} + +@end diff --git "a/21451198\345\215\242\350\266\205/project5/MyPlane/libs/cocos2d/CCCamera.h" "b/21451198\345\215\242\350\266\205/project5/MyPlane/libs/cocos2d/CCCamera.h" new file mode 100644 index 00000000..d38767f7 --- /dev/null +++ "b/21451198\345\215\242\350\266\205/project5/MyPlane/libs/cocos2d/CCCamera.h" @@ -0,0 +1,98 @@ +/* + * cocos2d for iPhone: http://www.cocos2d-iphone.org + * + * Copyright (c) 2008-2010 Ricardo Quesada + * Copyright (c) 2011 Zynga Inc. + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + * THE SOFTWARE. + */ + + + +#import "CCNode.h" +#import "kazmath/mat4.h" + +/** + A CCCamera is used in every CCNode. + Useful to look at the object from different views. + The OpenGL gluLookAt() function is used to locate the + camera. + + If the object is transformed by any of the scale, rotation or + position attributes, then they will override the camera. + + IMPORTANT: Either your use the camera or the rotation/scale/position properties. You can't use both. + World coordinates won't work if you use the camera. + + Limitations: + + - Some nodes, like CCParallaxNode, CCParticle uses world node coordinates, and they won't work properly if you move them (or any of their ancestors) + using the camera. + + - It doesn't work on batched nodes like CCSprite objects when they are parented to a CCSpriteBatchNode object. + + - It is recommended to use it ONLY if you are going to create 3D effects. For 2D effects, use the action CCFollow or position/scale/rotate. + +*/ + +@interface CCCamera : NSObject +{ + float _eyeX; + float _eyeY; + float _eyeZ; + + float _centerX; + float _centerY; + float _centerZ; + + float _upX; + float _upY; + float _upZ; + + BOOL _dirty; + + kmMat4 _lookupMatrix; +} + +/** whether of not the camera is dirty */ +@property (nonatomic,readwrite) BOOL dirty; + +/** returns the Z eye */ ++(float) getZEye; + +/** sets the camera in the defaul position */ +-(void) restore; +/** Sets the camera using gluLookAt using its eye, center and up_vector */ +-(void) locate; +/** sets the eye values in points */ +-(void) setEyeX: (float)x eyeY:(float)y eyeZ:(float)z; +/** sets the center values in points */ +-(void) setCenterX: (float)x centerY:(float)y centerZ:(float)z; +/** sets the up values */ +-(void) setUpX: (float)x upY:(float)y upZ:(float)z; + +/** get the eye vector values in points */ +-(void) eyeX:(float*)x eyeY:(float*)y eyeZ:(float*)z; +/** get the center vector values in points */ +-(void) centerX:(float*)x centerY:(float*)y centerZ:(float*)z; +/** get the up vector values */ +-(void) upX:(float*)x upY:(float*)y upZ:(float*)z; + + +@end diff --git "a/21451198\345\215\242\350\266\205/project5/MyPlane/libs/cocos2d/CCCamera.m" "b/21451198\345\215\242\350\266\205/project5/MyPlane/libs/cocos2d/CCCamera.m" new file mode 100644 index 00000000..2ac60faa --- /dev/null +++ "b/21451198\345\215\242\350\266\205/project5/MyPlane/libs/cocos2d/CCCamera.m" @@ -0,0 +1,148 @@ +/* + * cocos2d for iPhone: http://www.cocos2d-iphone.org + * + * Copyright (c) 2008-2010 Ricardo Quesada + * Copyright (c) 2011 Zynga Inc. + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + * THE SOFTWARE. + */ + + +#import "Platforms/CCGL.h" +#import "CCCamera.h" +#import "ccMacros.h" +#import "CCDrawingPrimitives.h" +#import "kazmath/GL/matrix.h" + +@implementation CCCamera + +@synthesize dirty = _dirty; + +-(id) init +{ + if( (self=[super init]) ) + [self restore]; + + return self; +} + +- (NSString*) description +{ + return [NSString stringWithFormat:@"<%@ = %p | center = (%.2f,%.2f,%.2f)>", [self class], self, _centerX, _centerY, _centerZ]; +} + + +- (void) dealloc +{ + CCLOGINFO(@"cocos2d: deallocing %@", self); + [super dealloc]; +} + +-(void) restore +{ + _eyeX = _eyeY = 0; + _eyeZ = [CCCamera getZEye]; + + _centerX = _centerY = _centerZ = 0; + + _upX = 0.0f; + _upY = 1.0f; + _upZ = 0.0f; + + kmMat4Identity( &_lookupMatrix ); + + _dirty = NO; +} + +-(void) locate +{ + if( _dirty ) { + + kmVec3 eye, center, up; + + kmVec3Fill( &eye, _eyeX, _eyeY , _eyeZ ); + kmVec3Fill( ¢er, _centerX, _centerY, _centerZ ); + + kmVec3Fill( &up, _upX, _upY, _upZ); + kmMat4LookAt( &_lookupMatrix, &eye, ¢er, &up); + + _dirty = NO; + + } + + kmGLMultMatrix( &_lookupMatrix ); + +} + ++(float) getZEye +{ + return FLT_EPSILON; + // CGSize s = [[CCDirector sharedDirector] displaySize]; + // return ( s.height / 1.1566f ); +} + +-(void) setEyeX: (float)x eyeY:(float)y eyeZ:(float)z +{ + _eyeX = x; + _eyeY = y; + _eyeZ = z; + + _dirty = YES; +} + +-(void) setCenterX: (float)x centerY:(float)y centerZ:(float)z +{ + _centerX = x; + _centerY = y; + _centerZ = z; + + _dirty = YES; +} + +-(void) setUpX: (float)x upY:(float)y upZ:(float)z +{ + _upX = x; + _upY = y; + _upZ = z; + + _dirty = YES; +} + +-(void) eyeX: (float*)x eyeY:(float*)y eyeZ:(float*)z +{ + *x = _eyeX; + *y = _eyeY; + *z = _eyeZ; +} + +-(void) centerX: (float*)x centerY:(float*)y centerZ:(float*)z +{ + *x = _centerX; + *y = _centerY; + *z = _centerZ; +} + +-(void) upX: (float*)x upY:(float*)y upZ:(float*)z +{ + *x = _upX; + *y = _upY; + *z = _upZ; +} + +@end diff --git "a/21451198\345\215\242\350\266\205/project5/MyPlane/libs/cocos2d/CCClippingNode.h" "b/21451198\345\215\242\350\266\205/project5/MyPlane/libs/cocos2d/CCClippingNode.h" new file mode 100644 index 00000000..58222585 --- /dev/null +++ "b/21451198\345\215\242\350\266\205/project5/MyPlane/libs/cocos2d/CCClippingNode.h" @@ -0,0 +1,77 @@ +/* + * cocos2d for iPhone: http://www.cocos2d-iphone.org + * + * Copyright (c) 2012 Pierre-David Bélanger + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + * THE SOFTWARE. + * + */ + +#import "CCNode.h" + +/** CCClippingNode is a subclass of CCNode. + It draws its content (childs) clipped using a stencil. + The stencil is an other CCNode that will not be drawn. + The clipping is done using the alpha part of the stencil (adjusted with an alphaThreshold). + */ +@interface CCClippingNode : CCNode +{ + CCNode *_stencil; + GLfloat _alphaThreshold; + BOOL _inverted; +} + +/** The CCNode to use as a stencil to do the clipping. + The stencil node will be retained. + This default to nil. + */ +@property (nonatomic, retain) CCNode *stencil; + +/** The alpha threshold. + The content is drawn only where the stencil have pixel with alpha greater than the alphaThreshold. + Should be a float between 0 and 1. + This default to 1 (so alpha test is disabled). + */ +@property (nonatomic) GLfloat alphaThreshold; + +/** Inverted. If this is set to YES, + the stencil is inverted, so the content is drawn where the stencil is NOT drawn. + This default to NO. + */ +@property (nonatomic) BOOL inverted; + +/** Creates and initializes a clipping node without a stencil. + */ ++ (id)clippingNode; + +/** Creates and initializes a clipping node with an other node as its stencil. + The stencil node will be retained. + */ ++ (id)clippingNodeWithStencil:(CCNode *)stencil; + +/** Initializes a clipping node without a stencil. + */ +- (id)init; + +/** Initializes a clipping node with an other node as its stencil. + The stencil node will be retained, and its parent will be set to this clipping node. + */ +- (id)initWithStencil:(CCNode *)stencil; + +@end diff --git "a/21451198\345\215\242\350\266\205/project5/MyPlane/libs/cocos2d/CCClippingNode.m" "b/21451198\345\215\242\350\266\205/project5/MyPlane/libs/cocos2d/CCClippingNode.m" new file mode 100644 index 00000000..2dffe5f2 --- /dev/null +++ "b/21451198\345\215\242\350\266\205/project5/MyPlane/libs/cocos2d/CCClippingNode.m" @@ -0,0 +1,359 @@ +/* + * cocos2d for iPhone: http://www.cocos2d-iphone.org + * + * Copyright (c) 2012 Pierre-David Bélanger + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + * THE SOFTWARE. + * + */ + +#import "CCClippingNode.h" + +#import "CCGL.h" +#import "OpenGL_Internal.h" + +#import "CCGLProgram.h" +#import "CCShaderCache.h" + +#import "CCDirector.h" +#import "CCDrawingPrimitives.h" +#import "CGPointExtension.h" + +#import "kazmath/GL/matrix.h" + +static GLint _stencilBits = -1; + +static void setProgram(CCNode *n, CCGLProgram *p) { + n.shaderProgram = p; + if (!n.children) return; + CCNode *c; + CCARRAY_FOREACH(n.children, c) setProgram(c, p); + +} + +@implementation CCClippingNode + +@synthesize stencil = _stencil; +@synthesize alphaThreshold = _alphaThreshold; +@synthesize inverted = _inverted; + +- (void)dealloc +{ + [_stencil release]; + [super dealloc]; +} + ++ (id)clippingNode +{ + return [self node]; +} + ++ (id)clippingNodeWithStencil:(CCNode *)stencil +{ + return [[[self alloc] initWithStencil:stencil] autorelease]; +} + +- (id)init +{ + return [self initWithStencil:nil]; +} + +- (id)initWithStencil:(CCNode *)stencil +{ + if (self = [super init]) { + self.stencil = stencil; + self.alphaThreshold = 1; + self.inverted = NO; + // get (only once) the number of bits of the stencil buffer + static dispatch_once_t once; + dispatch_once(&once, ^{ + glGetIntegerv(GL_STENCIL_BITS, &_stencilBits); + // warn if the stencil buffer is not enabled + if (_stencilBits <= 0) { +#if defined(__CC_PLATFORM_IOS) + CCLOGWARN(@"Stencil buffer is not enabled; enable it by passing GL_DEPTH24_STENCIL8_OES into the depthFormat parrameter when initializing CCGLView. Until then, everything will be drawn without stencil."); +#elif defined(__CC_PLATFORM_MAC) + CCLOGWARN(@"Stencil buffer is not enabled; enable it by setting the Stencil attribue to 8 bit in the Attributes inspector of the CCGLView view object in MainMenu.xib, or programmatically by adding NSOpenGLPFAStencilSize and 8 in the NSOpenGLPixelFormatAttribute array of the NSOpenGLPixelFormat used when initializing CCGLView. Until then, everything will be drawn without stencil."); +#endif + } + }); + } + return self; +} + +- (void)onEnter +{ + [super onEnter]; + [_stencil onEnter]; +} + +- (void)onEnterTransitionDidFinish +{ + [super onEnterTransitionDidFinish]; + [_stencil onEnterTransitionDidFinish]; +} + +- (void)onExitTransitionDidStart +{ + [_stencil onExitTransitionDidStart]; + [super onExitTransitionDidStart]; +} + +- (void)onExit +{ + [_stencil onExit]; + [super onExit]; +} + +- (void)visit +{ + // if stencil buffer disabled + if (_stencilBits < 1) { + // draw everything, as if there where no stencil + [super visit]; + return; + } + + // return fast (draw nothing, or draw everything if in inverted mode) if: + // - nil stencil node + // - or stencil node invisible: + if (!_stencil || !_stencil.visible) { + if (_inverted) { + // draw everything + [super visit]; + } + return; + } + + // store the current stencil layer (position in the stencil buffer), + // this will allow nesting up to n CCClippingNode, + // where n is the number of bits of the stencil buffer. + static GLint layer = -1; + + // all the _stencilBits are in use? + if (layer + 1 == _stencilBits) { + // warn once + static dispatch_once_t once; + dispatch_once(&once, ^{ + CCLOGWARN(@"Nesting more than %d stencils is not supported. Everything will be drawn without stencil for this node and its childs.", _stencilBits); + }); + // draw everything, as if there where no stencil + [super visit]; + return; + } + + /////////////////////////////////// + // INIT + + // increment the current layer + layer++; + + // mask of the current layer (ie: for layer 3: 00000100) + GLint mask_layer = 0x1 << layer; + // mask of all layers less than the current (ie: for layer 3: 00000011) + GLint mask_layer_l = mask_layer - 1; + // mask of all layers less than or equal to the current (ie: for layer 3: 00000111) + GLint mask_layer_le = mask_layer | mask_layer_l; + + // manually save the stencil state + GLboolean currentStencilEnabled = GL_FALSE; + GLuint currentStencilWriteMask = ~0; + GLenum currentStencilFunc = GL_ALWAYS; + GLint currentStencilRef = 0; + GLuint currentStencilValueMask = ~0; + GLenum currentStencilFail = GL_KEEP; + GLenum currentStencilPassDepthFail = GL_KEEP; + GLenum currentStencilPassDepthPass = GL_KEEP; + currentStencilEnabled = glIsEnabled(GL_STENCIL_TEST); + glGetIntegerv(GL_STENCIL_WRITEMASK, (GLint *)¤tStencilWriteMask); + glGetIntegerv(GL_STENCIL_FUNC, (GLint *)¤tStencilFunc); + glGetIntegerv(GL_STENCIL_REF, ¤tStencilRef); + glGetIntegerv(GL_STENCIL_VALUE_MASK, (GLint *)¤tStencilValueMask); + glGetIntegerv(GL_STENCIL_FAIL, (GLint *)¤tStencilFail); + glGetIntegerv(GL_STENCIL_PASS_DEPTH_FAIL, (GLint *)¤tStencilPassDepthFail); + glGetIntegerv(GL_STENCIL_PASS_DEPTH_PASS, (GLint *)¤tStencilPassDepthPass); + + // enable stencil use + glEnable(GL_STENCIL_TEST); + // check for OpenGL error while enabling stencil test + CHECK_GL_ERROR_DEBUG(); + + // all bits on the stencil buffer are readonly, except the current layer bit, + // this means that operation like glClear or glStencilOp will be masked with this value + glStencilMask(mask_layer); + + // manually save the depth test state + //GLboolean currentDepthTestEnabled = GL_TRUE; + GLboolean currentDepthWriteMask = GL_TRUE; + //currentDepthTestEnabled = glIsEnabled(GL_DEPTH_TEST); + glGetBooleanv(GL_DEPTH_WRITEMASK, ¤tDepthWriteMask); + + // disable depth test while drawing the stencil + //glDisable(GL_DEPTH_TEST); + // disable update to the depth buffer while drawing the stencil, + // as the stencil is not meant to be rendered in the real scene, + // it should never prevent something else to be drawn, + // only disabling depth buffer update should do + glDepthMask(GL_FALSE); + + /////////////////////////////////// + // CLEAR STENCIL BUFFER + + // setup the stencil test func like this: + // for each pixel in the stencil buffer + // never draw it into the frame buffer + // if not in inverted mode: set the current layer value to 0 in the stencil buffer + // if in inverted mode: set the current layer value to 1 in the stencil buffer +#if defined(__CC_PLATFORM_MAC) + // There is a bug in some ATI drivers where glStencilMask does not affect glClear. + // Draw a full screen rectangle to clear the stencil buffer. + glStencilFunc(GL_NEVER, mask_layer, mask_layer); + glStencilOp(!_inverted ? GL_ZERO : GL_REPLACE, GL_KEEP, GL_KEEP); + + int viewport[4]; + glGetIntegerv(GL_VIEWPORT, viewport); + + int x = viewport[0]; + int y = viewport[1]; + int width = viewport[2]; + int height = viewport[3]; + + kmGLMatrixMode(KM_GL_PROJECTION); + kmGLPushMatrix(); + kmGLLoadIdentity(); + + kmMat4 orthoMatrix; + kmMat4OrthographicProjection(&orthoMatrix, x, width, y, height, -1, 1); + kmGLMultMatrix( &orthoMatrix ); + + kmGLMatrixMode(KM_GL_MODELVIEW); + kmGLPushMatrix(); + kmGLLoadIdentity(); + + ccDrawSolidRect(ccp(x, y), ccp(width, height), ccc4f(1, 1, 1, 1)); + + kmGLMatrixMode(KM_GL_PROJECTION); + kmGLPopMatrix(); + kmGLMatrixMode(KM_GL_MODELVIEW); + kmGLPopMatrix(); +#else + glClearStencil(!_inverted ? 0 : ~0); + glClear(GL_STENCIL_BUFFER_BIT); +#endif + + /////////////////////////////////// + // DRAW CLIPPING STENCIL + + // setup the stencil test func like this: + // for each pixel in the stencil node + // never draw it into the frame buffer + // if not in inverted mode: set the current layer value to 1 in the stencil buffer + // if in inverted mode: set the current layer value to 0 in the stencil buffer + glStencilFunc(GL_NEVER, mask_layer, mask_layer); + glStencilOp(!_inverted ? GL_REPLACE : GL_ZERO, GL_KEEP, GL_KEEP); + + // enable alpha test only if the alpha threshold < 1, + // indeed if alpha threshold == 1, every pixel will be drawn anyways +#if defined(__CC_PLATFORM_MAC) + GLboolean currentAlphaTestEnabled = GL_FALSE; + GLenum currentAlphaTestFunc = GL_ALWAYS; + GLclampf currentAlphaTestRef = 1; +#endif + if (_alphaThreshold < 1) { +#if defined(__CC_PLATFORM_IOS) + // since glAlphaTest do not exists in OES, use a shader that writes + // pixel only if greater than an alpha threshold + CCGLProgram *program = [[CCShaderCache sharedShaderCache] programForKey:kCCShader_PositionTextureColorAlphaTest]; + GLint alphaValueLocation = glGetUniformLocation(program.program, kCCUniformAlphaTestValue_s); + // set our alphaThreshold + [program setUniformLocation:alphaValueLocation withF1:_alphaThreshold]; + // we need to recursively apply this shader to all the nodes in the stencil node + // XXX: we should have a way to apply shader to all nodes without having to do this + setProgram(_stencil, program); +#elif defined(__CC_PLATFORM_MAC) + // manually save the alpha test state + currentAlphaTestEnabled = glIsEnabled(GL_ALPHA_TEST); + glGetIntegerv(GL_ALPHA_TEST_FUNC, (GLint *)¤tAlphaTestFunc); + glGetFloatv(GL_ALPHA_TEST_REF, ¤tAlphaTestRef); + // enable alpha testing + glEnable(GL_ALPHA_TEST); + // check for OpenGL error while enabling alpha test + CHECK_GL_ERROR_DEBUG(); + // pixel will be drawn only if greater than an alpha threshold + glAlphaFunc(GL_GREATER, _alphaThreshold); +#endif + } + + // draw the stencil node as if it was one of our child + // (according to the stencil test func/op and alpha (or alpha shader) test) + kmGLPushMatrix(); + [self transform]; + [_stencil visit]; + kmGLPopMatrix(); + + // restore alpha test state + if (_alphaThreshold < 1) { +#if defined(__CC_PLATFORM_IOS) + // XXX: we need to find a way to restore the shaders of the stencil node and its childs +#elif defined(__CC_PLATFORM_MAC) + // manually restore the alpha test state + glAlphaFunc(currentAlphaTestFunc, currentAlphaTestRef); + if (!currentAlphaTestEnabled) { + glDisable(GL_ALPHA_TEST); + } +#endif + } + + // restore the depth test state + glDepthMask(currentDepthWriteMask); + //if (currentDepthTestEnabled) { + // glEnable(GL_DEPTH_TEST); + //} + + /////////////////////////////////// + // DRAW CONTENT + + // setup the stencil test func like this: + // for each pixel of this node and its childs + // if all layers less than or equals to the current are set to 1 in the stencil buffer + // draw the pixel and keep the current layer in the stencil buffer + // else + // do not draw the pixel but keep the current layer in the stencil buffer + glStencilFunc(GL_EQUAL, mask_layer_le, mask_layer_le); + glStencilOp(GL_KEEP, GL_KEEP, GL_KEEP); + + // draw (according to the stencil test func) this node and its childs + [super visit]; + + /////////////////////////////////// + // CLEANUP + + // manually restore the stencil state + glStencilFunc(currentStencilFunc, currentStencilRef, currentStencilValueMask); + glStencilOp(currentStencilFail, currentStencilPassDepthFail, currentStencilPassDepthPass); + glStencilMask(currentStencilWriteMask); + if (!currentStencilEnabled) { + glDisable(GL_STENCIL_TEST); + } + + // we are done using this layer, decrement + layer--; +} + +@end diff --git "a/21451198\345\215\242\350\266\205/project5/MyPlane/libs/cocos2d/CCConfiguration.h" "b/21451198\345\215\242\350\266\205/project5/MyPlane/libs/cocos2d/CCConfiguration.h" new file mode 100644 index 00000000..5ca15c02 --- /dev/null +++ "b/21451198\345\215\242\350\266\205/project5/MyPlane/libs/cocos2d/CCConfiguration.h" @@ -0,0 +1,144 @@ +/* + * cocos2d for iPhone: http://www.cocos2d-iphone.org + * + * Copyright (c) 2010 Ricardo Quesada + * Copyright (c) 2011 Zynga Inc. + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + * THE SOFTWARE. + */ + +#import + +#import "Platforms/CCGL.h" + +/** OS version definitions. Includes both iOS and Mac OS versions + */ +enum { + kCCiOSVersion_4_0 = 0x04000000, + kCCiOSVersion_4_0_1 = 0x04000100, + kCCiOSVersion_4_1 = 0x04010000, + kCCiOSVersion_4_2 = 0x04020000, + kCCiOSVersion_4_2_1 = 0x04020100, + kCCiOSVersion_4_3 = 0x04030000, + kCCiOSVersion_4_3_1 = 0x04030100, + kCCiOSVersion_4_3_2 = 0x04030200, + kCCiOSVersion_4_3_3 = 0x04030300, + kCCiOSVersion_4_3_4 = 0x04030400, + kCCiOSVersion_4_3_5 = 0x04030500, + kCCiOSVersion_5_0 = 0x05000000, + kCCiOSVersion_5_0_1 = 0x05000100, + kCCiOSVersion_5_1_0 = 0x05010000, + kCCiOSVersion_6_0_0 = 0x06000000, + + kCCMacVersion_10_6 = 0x0a060000, + kCCMacVersion_10_7 = 0x0a070000, + kCCMacVersion_10_8 = 0x0a080000, +}; + +enum { + kCCDeviceiPhone, + kCCDeviceiPhoneRetinaDisplay, + kCCDeviceiPhone5, + kCCDeviceiPhone5RetinaDisplay, + kCCDeviceiPad, + kCCDeviceiPadRetinaDisplay, + + kCCDeviceMac, + kCCDeviceMacRetinaDisplay, +}; + +/** + CCConfiguration contains some openGL variables + @since v0.99.0 + */ +@interface CCConfiguration : NSObject { + + BOOL _openGLInitialized; + + GLint _maxTextureSize; + BOOL _supportsPVRTC; + BOOL _supportsNPOT; + BOOL _supportsBGRA8888; + BOOL _supportsDiscardFramebuffer; + BOOL _supportsShareableVAO; + GLint _maxSamplesAllowed; + GLint _maxTextureUnits; + + unsigned int _OSVersion; +} + +/** OpenGL Max texture size. */ +@property (nonatomic, readonly) GLint maxTextureSize; + +/** returns the maximum texture units + @since v2.0.0 + */ +@property (nonatomic, readonly) GLint maxTextureUnits; + +/** Whether or not the GPU supports NPOT (Non Power Of Two) textures. + OpenGL ES 2.0 already supports NPOT (iOS). + + @since v0.99.2 + */ +@property (nonatomic, readonly) BOOL supportsNPOT; + +/** Whether or not PVR Texture Compressed is supported */ +@property (nonatomic, readonly) BOOL supportsPVRTC; + +/** Whether or not BGRA8888 textures are supported. + + @since v0.99.2 + */ +@property (nonatomic, readonly) BOOL supportsBGRA8888; + +/** Whether or not glDiscardFramebufferEXT is supported + + @since v0.99.2 + */ +@property (nonatomic, readonly) BOOL supportsDiscardFramebuffer; + +/** Whether or not shareable VAOs are supported. + @since v2.0.0 + */ +@property (nonatomic, readonly) BOOL supportsShareableVAO; + +/** returns the OS version. + - On iOS devices it returns the firmware version. + - On Mac returns the OS version + + @since v0.99.5 + */ +@property (nonatomic, readonly) unsigned int OSVersion; + + +/** returns a shared instance of the CCConfiguration */ ++(CCConfiguration *) sharedConfiguration; + +/** returns whether or not an OpenGL is supported */ +- (BOOL) checkForGLExtension:(NSString *)searchName; + +/** returns the current device */ +-(NSInteger) runningDevice; + +/** dumps in the console the CCConfiguration information. + @since v2.1 + */ +-(void) dumpInfo; + +@end diff --git "a/21451198\345\215\242\350\266\205/project5/MyPlane/libs/cocos2d/CCConfiguration.m" "b/21451198\345\215\242\350\266\205/project5/MyPlane/libs/cocos2d/CCConfiguration.m" new file mode 100644 index 00000000..d3a985c7 --- /dev/null +++ "b/21451198\345\215\242\350\266\205/project5/MyPlane/libs/cocos2d/CCConfiguration.m" @@ -0,0 +1,315 @@ +/* + * cocos2d for iPhone: http://www.cocos2d-iphone.org + * + * Copyright (c) 2010 Ricardo Quesada + * Copyright (c) 2011 Zynga Inc. + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + * THE SOFTWARE. + */ + +#import "ccMacros.h" + +#ifdef __CC_PLATFORM_IOS +#import // Needed for UIDevice +#endif + +#import "Platforms/CCGL.h" +#import "CCConfiguration.h" +#import "ccMacros.h" +#import "ccConfig.h" +#import "Support/OpenGL_Internal.h" +#import "cocos2d.h" + +@interface CCConfiguration () +-(void) getOpenGLvariables; +@end + +@implementation CCConfiguration + +@synthesize maxTextureSize = _maxTextureSize, maxTextureUnits=_maxTextureUnits; +@synthesize supportsPVRTC = _supportsPVRTC; +@synthesize supportsNPOT = _supportsNPOT; +@synthesize supportsBGRA8888 = _supportsBGRA8888; +@synthesize supportsDiscardFramebuffer = _supportsDiscardFramebuffer; +@synthesize supportsShareableVAO = _supportsShareableVAO; +@synthesize OSVersion = _OSVersion; + +// +// singleton stuff +// +static CCConfiguration *_sharedConfiguration = nil; + +static char * glExtensions; + ++ (CCConfiguration *)sharedConfiguration +{ + if (!_sharedConfiguration) + _sharedConfiguration = [[self alloc] init]; + + return _sharedConfiguration; +} + ++(id)alloc +{ + NSAssert(_sharedConfiguration == nil, @"Attempted to allocate a second instance of a singleton."); + return [super alloc]; +} + + +#ifdef __CC_PLATFORM_IOS +#elif defined(__CC_PLATFORM_MAC) +- (NSString*)getMacVersion +{ + SInt32 versionMajor, versionMinor, versionBugFix; + Gestalt(gestaltSystemVersionMajor, &versionMajor); + Gestalt(gestaltSystemVersionMinor, &versionMinor); + Gestalt(gestaltSystemVersionBugFix, &versionBugFix); + + return [NSString stringWithFormat:@"%d.%d.%d", versionMajor, versionMinor, versionBugFix]; +} +#endif // __CC_PLATFORM_MAC + +-(id) init +{ + if( (self=[super init])) { + + // Obtain iOS version + _OSVersion = 0; +#ifdef __CC_PLATFORM_IOS + NSString *OSVer = [[UIDevice currentDevice] systemVersion]; +#elif defined(__CC_PLATFORM_MAC) + NSString *OSVer = [self getMacVersion]; +#endif + NSArray *arr = [OSVer componentsSeparatedByString:@"."]; + int idx = 0x01000000; + for( NSString *str in arr ) { + int value = [str intValue]; + _OSVersion += value * idx; + idx = idx >> 8; + } + } + +#if CC_ENABLE_GL_STATE_CACHE == 0 + printf("\n"); + NSLog(@"cocos2d: **** WARNING **** CC_ENABLE_GL_STATE_CACHE is disabled. To improve performance, enable it by editing ccConfig.h"); + printf("\n"); +#endif + + CHECK_GL_ERROR_DEBUG(); + + return self; +} + +- (BOOL) checkForGLExtension:(NSString *)searchName +{ + // For best results, extensionsNames should be stored in your renderer so that it does not + // need to be recreated on each invocation. + NSString *extensionsString = [NSString stringWithCString:glExtensions encoding: NSASCIIStringEncoding]; + NSArray *extensionsNames = [extensionsString componentsSeparatedByString:@" "]; + return [extensionsNames containsObject: searchName]; +} + +// XXX: Optimization: This should be called only once +-(NSInteger) runningDevice +{ + NSInteger ret=-1; + +#ifdef __CC_PLATFORM_IOS + + if( UI_USER_INTERFACE_IDIOM() == UIUserInterfaceIdiomPad) + { + ret = (CC_CONTENT_SCALE_FACTOR() == 2) ? kCCDeviceiPadRetinaDisplay : kCCDeviceiPad; + } + else if( UI_USER_INTERFACE_IDIOM() == UIUserInterfaceIdiomPhone ) + { + // From http://stackoverflow.com/a/12535566 + BOOL isiPhone5 = CGSizeEqualToSize([[UIScreen mainScreen] preferredMode].size,CGSizeMake(640, 1136)); + + if( CC_CONTENT_SCALE_FACTOR() == 2 ) { + ret = isiPhone5 ? kCCDeviceiPhone5RetinaDisplay : kCCDeviceiPhoneRetinaDisplay; + } else + ret = isiPhone5 ? kCCDeviceiPhone5 : kCCDeviceiPhone; + } + +#elif defined(__CC_PLATFORM_MAC) + + // XXX: Add here support for Mac Retina Display + ret = kCCDeviceMac; + +#endif // __CC_PLATFORM_MAC + + return ret; +} + +#pragma mark OpenGL getters + +/** OpenGL Max texture size. */ + +-(void) getOpenGLvariables +{ + if( ! _openGLInitialized ) { + + glExtensions = (char*) glGetString(GL_EXTENSIONS); + + NSAssert( glExtensions, @"OpenGL not initialized!"); + +#ifdef __CC_PLATFORM_IOS + if( _OSVersion >= kCCiOSVersion_4_0 ) + glGetIntegerv(GL_MAX_SAMPLES_APPLE, &_maxSamplesAllowed); + else + _maxSamplesAllowed = 0; +#elif defined(__CC_PLATFORM_MAC) + glGetIntegerv(GL_MAX_SAMPLES, &_maxSamplesAllowed); +#endif + + glGetIntegerv(GL_MAX_TEXTURE_SIZE, &_maxTextureSize); + glGetIntegerv(GL_MAX_COMBINED_TEXTURE_IMAGE_UNITS, &_maxTextureUnits ); + +#ifdef __CC_PLATFORM_IOS + _supportsNPOT = YES; +#elif defined(__CC_PLATFORM_MAC) + _supportsNPOT = [self checkForGLExtension:@"GL_ARB_texture_non_power_of_two"]; +#endif + + _supportsPVRTC = [self checkForGLExtension:@"GL_IMG_texture_compression_pvrtc"]; + + // It seems that somewhere between firmware iOS 3.0 and 4.2 Apple renamed + // GL_IMG_... to GL_APPLE.... So we should check both names +#ifdef __CC_PLATFORM_IOS + BOOL bgra8a = [self checkForGLExtension:@"GL_IMG_texture_format_BGRA8888"]; + BOOL bgra8b = [self checkForGLExtension:@"GL_APPLE_texture_format_BGRA8888"]; + _supportsBGRA8888 = bgra8a | bgra8b; +#elif defined(__CC_PLATFORM_MAC) + _supportsBGRA8888 = [self checkForGLExtension:@"GL_EXT_bgra"]; +#endif + _supportsDiscardFramebuffer = [self checkForGLExtension:@"GL_EXT_discard_framebuffer"]; + + _supportsShareableVAO = [self checkForGLExtension:@"GL_APPLE_vertex_array_object"]; + + _openGLInitialized = YES; + } +} + +-(GLint) maxTextureSize +{ + if( ! _openGLInitialized ) + [self getOpenGLvariables]; + return _maxTextureSize; +} + +-(GLint) maxTextureUnits +{ + if( ! _openGLInitialized ) + [self getOpenGLvariables]; + + return _maxTextureUnits; +} + +-(BOOL) supportsNPOT +{ + if( ! _openGLInitialized ) + [self getOpenGLvariables]; + + return _supportsNPOT; +} + +-(BOOL) supportsPVRTC +{ + if( ! _openGLInitialized ) + [self getOpenGLvariables]; + + return _supportsPVRTC; +} + +-(BOOL) supportsBGRA8888 +{ + if( ! _openGLInitialized ) + [self getOpenGLvariables]; + + return _supportsBGRA8888; +} + +-(BOOL) supportsDiscardFramebuffer +{ + if( ! _openGLInitialized ) + [self getOpenGLvariables]; + + return _supportsDiscardFramebuffer; +} + +-(BOOL) supportsShareableVAO +{ + if( ! _openGLInitialized ) + [self getOpenGLvariables]; + + return _supportsShareableVAO; +} + + +#pragma mark Helper + +-(void) dumpInfo +{ +#if DEBUG + printf("cocos2d: %s\n", cocos2d_version ); + +#ifdef __CC_PLATFORM_IOS + NSString *OSVer = [[UIDevice currentDevice] systemVersion]; +#elif defined(__CC_PLATFORM_MAC) + NSString *OSVer = [self getMacVersion]; +#endif + +#ifdef __CC_PLATFORM_MAC + printf("cocos2d: Director's thread: %s\n", +#if (CC_DIRECTOR_MAC_THREAD == CC_MAC_USE_MAIN_THREAD) + "Main thread" +#elif (CC_DIRECTOR_MAC_THREAD == CC_MAC_USE_OWN_THREAD) + "Own thread" +#elif (CC_DIRECTOR_MAC_THREAD == CC_MAC_USE_DISPLAY_LINK_THREAD) + "DisplayLink thread" +#endif // + ); +#endif // Mac + + printf("cocos2d: compiled with Profiling Support: %s\n", +#if CC_ENABLE_PROFILERS + "YES - *** Disable it when you finish profiling ***" +#else + "NO" +#endif + ); + + printf("cocos2d: OS version: %s (0x%08x)\n", [OSVer UTF8String], _OSVersion); + + printf("cocos2d: GL_VENDOR: %s\n", glGetString(GL_VENDOR) ); + printf("cocos2d: GL_RENDERER: %s\n", glGetString ( GL_RENDERER ) ); + printf("cocos2d: GL_VERSION: %s\n", glGetString ( GL_VERSION ) ); + + printf("cocos2d: GL_MAX_TEXTURE_SIZE: %d\n", _maxTextureSize); + printf("cocos2d: GL_MAX_TEXTURE_UNITS: %d\n", _maxTextureUnits); + printf("cocos2d: GL_MAX_SAMPLES: %d\n", _maxSamplesAllowed); + printf("cocos2d: GL supports PVRTC: %s\n", (_supportsPVRTC ? "YES" : "NO") ); + printf("cocos2d: GL supports BGRA8888 textures: %s\n", (_supportsBGRA8888 ? "YES" : "NO") ); + printf("cocos2d: GL supports NPOT textures: %s\n", (_supportsNPOT ? "YES" : "NO") ); + printf("cocos2d: GL supports discard_framebuffer: %s\n", (_supportsDiscardFramebuffer ? "YES" : "NO") ); + printf("cocos2d: GL supports shareable VAO: %s\n", (_supportsShareableVAO ? "YES" : "NO") ); + +#endif // DEBUG +} +@end diff --git "a/21451198\345\215\242\350\266\205/project5/MyPlane/libs/cocos2d/CCDirector.h" "b/21451198\345\215\242\350\266\205/project5/MyPlane/libs/cocos2d/CCDirector.h" new file mode 100644 index 00000000..f04019c7 --- /dev/null +++ "b/21451198\345\215\242\350\266\205/project5/MyPlane/libs/cocos2d/CCDirector.h" @@ -0,0 +1,353 @@ +/* + * cocos2d for iPhone: http://www.cocos2d-iphone.org + * + * Copyright (c) 2008-2010 Ricardo Quesada + * Copyright (c) 2011 Zynga Inc. + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + * THE SOFTWARE. + */ + + +#import "ccConfig.h" +#import "ccTypes.h" +#import "ccMacros.h" + +#import "CCProtocols.h" +#import "Platforms/CCGL.h" +#import "kazmath/mat4.h" + +/** @typedef ccDirectorProjection + Possible OpenGL projections used by director + */ +typedef enum { + /// sets a 2D projection (orthogonal projection). + kCCDirectorProjection2D, + + /// sets a 3D projection with a fovy=60, znear=0.5f and zfar=1500. + kCCDirectorProjection3D, + + /// it calls "updateProjection" on the projection delegate. + kCCDirectorProjectionCustom, + + /// Detault projection is 3D projection + kCCDirectorProjectionDefault = kCCDirectorProjection3D, + +} ccDirectorProjection; + + +@class CCLabelAtlas; +@class CCScene; +@class CCScheduler; +@class CCActionManager; + + +#ifdef __CC_PLATFORM_IOS +#define CC_VIEWCONTROLLER UIViewController +#elif defined(__CC_PLATFORM_MAC) +#define CC_VIEWCONTROLLER NSObject +#endif + +/**Class that creates and handle the main Window and manages how +and when to execute the Scenes. + + The CCDirector is also responsible for: + - initializing the OpenGL ES context + - setting the OpenGL pixel format (default on is RGB565) + - setting the OpenGL buffer depth (default one is 0-bit) + - setting the projection (default one is 3D) + + Since the CCDirector is a singleton, the standard way to use it is by calling: + - [[CCDirector sharedDirector] methodName]; + + The CCDirector also sets the default OpenGL context: + - GL_TEXTURE_2D is enabled + - GL_VERTEX_ARRAY is enabled + - GL_COLOR_ARRAY is enabled + - GL_TEXTURE_COORD_ARRAY is enabled +*/ +@interface CCDirector : CC_VIEWCONTROLLER +{ + // internal timer + NSTimeInterval _animationInterval; + NSTimeInterval _oldAnimationInterval; + + /* stats */ + BOOL _displayStats; + + NSUInteger _frames; + NSUInteger _totalFrames; + ccTime _secondsPerFrame; + + ccTime _accumDt; + ccTime _frameRate; + CCLabelAtlas *_FPSLabel; + CCLabelAtlas *_SPFLabel; + CCLabelAtlas *_drawsLabel; + + /* is the running scene paused */ + BOOL _isPaused; + + /* Is the director running */ + BOOL _isAnimating; + + /* The running scene */ + CCScene *_runningScene; + + /* This object will be visited after the scene. Useful to hook a notification node */ + id _notificationNode; + + /* will be the next 'runningScene' in the next frame + nextScene is a weak reference. */ + CCScene *_nextScene; + + /* If YES, then "old" scene will receive the cleanup message */ + BOOL _sendCleanupToScene; + + /* scheduled scenes */ + NSMutableArray *_scenesStack; + + /* last time the main loop was updated */ + struct timeval _lastUpdate; + /* delta time since last tick to main loop */ + ccTime _dt; + /* whether or not the next delta time will be zero */ + BOOL _nextDeltaTimeZero; + + /* projection used */ + ccDirectorProjection _projection; + + /* CCDirector delegate */ + id _delegate; + + /* window size in points */ + CGSize _winSizeInPoints; + + /* window size in pixels */ + CGSize _winSizeInPixels; + + /* the cocos2d running thread */ + NSThread *_runningThread; + + /* scheduler associated with this director */ + CCScheduler *_scheduler; + + /* action manager associated with this director */ + CCActionManager *_actionManager; + + /* OpenGLView. On iOS it is a copy of self.view */ + CCGLView *__view; +} + +/** returns the cocos2d thread. + If you want to run any cocos2d task, run it in this thread. + On iOS usually it is the main thread. + @since v0.99.5 + */ +@property (readonly, nonatomic ) NSThread *runningThread; +/** The current running Scene. Director can only run one Scene at the time */ +@property (nonatomic,readonly) CCScene* runningScene; +/** The FPS value */ +@property (nonatomic,readwrite, assign) NSTimeInterval animationInterval; +/** Whether or not to display director statistics */ +@property (nonatomic, readwrite, assign) BOOL displayStats; +/** whether or not the next delta time will be zero */ +@property (nonatomic,readwrite,assign) BOOL nextDeltaTimeZero; +/** Whether or not the Director is paused */ +@property (nonatomic,readonly,getter=isPaused) BOOL paused; +/** Whether or not the Director is active (animating) */ +@property (nonatomic,readonly) BOOL isAnimating; +/** Sets an OpenGL projection */ +@property (nonatomic,readwrite) ccDirectorProjection projection; +/** How many frames were called since the director started */ +@property (nonatomic,readonly) NSUInteger totalFrames; +/** seconds per frame */ +@property (nonatomic, readonly) ccTime secondsPerFrame; + +/** Whether or not the replaced scene will receive the cleanup message. + If the new scene is pushed, then the old scene won't receive the "cleanup" message. + If the new scene replaces the old one, the it will receive the "cleanup" message. + @since v0.99.0 + */ +@property (nonatomic, readonly) BOOL sendCleanupToScene; + +/** This object will be visited after the main scene is visited. + This object MUST implement the "visit" selector. + Useful to hook a notification object, like CCNotifications (http://github.com/manucorporat/CCNotifications) + @since v0.99.5 + */ +@property (nonatomic, readwrite, retain) id notificationNode; + +/** CCDirector delegate. It shall implement the CCDirectorDelegate protocol + @since v0.99.5 + */ +@property (nonatomic, readwrite, assign) id delegate; + +/** CCScheduler associated with this director + @since v2.0 + */ +@property (nonatomic,readwrite,retain) CCScheduler *scheduler; + +/** CCActionManager associated with this director + @since v2.0 + */ +@property (nonatomic,readwrite,retain) CCActionManager *actionManager; + +/** returns a shared instance of the director */ ++(CCDirector*)sharedDirector; + + +#pragma mark Director - Stats + +#pragma mark Director - Win Size +/** returns the size of the OpenGL view in points */ +- (CGSize) winSize; + +/** returns the size of the OpenGL view in pixels. + On Mac winSize and winSizeInPixels return the same value. + */ +- (CGSize) winSizeInPixels; + +/** changes the projection size */ +-(void) reshapeProjection:(CGSize)newWindowSize; + +/** Sets the glViewport*/ +-(void) setViewport; + +/** converts a UIKit coordinate to an OpenGL coordinate + Useful to convert (multi) touch coordinates to the current layout (portrait or landscape) + */ +-(CGPoint) convertToGL: (CGPoint) p; +/** converts an OpenGL coordinate to a UIKit coordinate + Useful to convert node points to window points for calls such as glScissor + */ +-(CGPoint) convertToUI:(CGPoint)p; + +/// XXX: missing description +-(float) getZEye; + +#pragma mark Director - Scene Management + +/** Enters the Director's main loop with the given Scene. + * Call it to run only your FIRST scene. + * Don't call it if there is already a running scene. + * + * It will call pushScene: and then it will call startAnimation + */ +- (void) runWithScene:(CCScene*) scene; + +/** Suspends the execution of the running scene, pushing it on the stack of suspended scenes. + * The new scene will be executed. + * Try to avoid big stacks of pushed scenes to reduce memory allocation. + * ONLY call it if there is a running scene. + */ +- (void) pushScene:(CCScene*) scene; + +/** Pops out a scene from the queue. + * This scene will replace the running one. + * The running scene will be deleted. If there are no more scenes in the stack the execution is terminated. + * ONLY call it if there is a running scene. + */ +- (void) popScene; + +/**Pops out all scenes from the queue until the root scene in the queue. + * This scene will replace the running one. + * Internally it will call `popToSceneStackLevel:1` + */ +- (void) popToRootScene; + +/** Pops out all scenes from the queue until it reaches `level`. + If level is 0, it will end the director. + If level is 1, it will pop all scenes until it reaches to root scene. + If level is <= than the current stack level, it won't do anything. + */ +-(void) popToSceneStackLevel:(NSUInteger)level; + +/** Replaces the running scene with a new one. The running scene is terminated. + * ONLY call it if there is a running scene. + */ +-(void) replaceScene: (CCScene*) scene; + +/** Ends the execution, releases the running scene. + It doesn't remove the OpenGL view from its parent. You have to do it manually. + */ +-(void) end; + +/** Pauses the running scene. + The running scene will be _drawed_ but all scheduled timers will be paused + While paused, the draw rate will be 4 FPS to reduce CPU consumption + */ +-(void) pause; + +/** Resumes the paused scene + The scheduled timers will be activated again. + The "delta time" will be 0 (as if the game wasn't paused) + */ +-(void) resume; + +/** Stops the animation. Nothing will be drawn. The main loop won't be triggered anymore. + If you want to pause your animation call [pause] instead. + */ +-(void) stopAnimation; + +/** The main loop is triggered again. + Call this function only if [stopAnimation] was called earlier + @warning Don't call this function to start the main loop. To run the main loop call runWithScene + */ +-(void) startAnimation; + +/** Draw the scene. + This method is called every frame. Don't call it manually. + */ +-(void) drawScene; + + +// XXX: Hack. Should be placed on CCDirectorMac.h. Refactoring needed +#if defined(__CC_PLATFORM_MAC) +/** sets the openGL view */ +-(void) setView:(CCGLView*)view; + +/** returns the OpenGL view */ +-(CCGLView*) view; +#endif + +#pragma mark Director - Memory Helper + +/** Removes all the cocos2d data that was cached automatically. + It will purge the CCTextureCache, CCLabelBMFont cache. + IMPORTANT: The CCSpriteFrameCache won't be purged. If you want to purge it, you have to purge it manually. + @since v0.99.3 + */ +-(void) purgeCachedData; + +// OpenGL Helper + +/** sets the OpenGL default values */ +-(void) setGLDefaultValues; +/** enables/disables OpenGL alpha blending */ +- (void) setAlphaBlending: (BOOL) on; +/** enables/disables OpenGL depth test */ +- (void) setDepthTest: (BOOL) on; + +// helper +/** creates the Stats labels */ +-(void) createStatsLabel; +@end + +// optimization. Should only be used to read it. Never to write it. +extern NSUInteger __ccNumberOfDraws; diff --git "a/21451198\345\215\242\350\266\205/project5/MyPlane/libs/cocos2d/CCDirector.m" "b/21451198\345\215\242\350\266\205/project5/MyPlane/libs/cocos2d/CCDirector.m" new file mode 100644 index 00000000..bf340550 --- /dev/null +++ "b/21451198\345\215\242\350\266\205/project5/MyPlane/libs/cocos2d/CCDirector.m" @@ -0,0 +1,682 @@ +/* + * cocos2d for iPhone: http://www.cocos2d-iphone.org + * + * Copyright (c) 2008-2010 Ricardo Quesada + * Copyright (c) 2011 Zynga Inc. + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + * THE SOFTWARE. + */ + + +/* Idea of decoupling Window from Director taken from OC3D project: http://code.google.com/p/oc3d/ + */ + +#import + +// cocos2d imports +#import "CCDirector.h" +#import "CCScheduler.h" +#import "CCActionManager.h" +#import "CCTextureCache.h" +#import "CCAnimationCache.h" +#import "CCLabelAtlas.h" +#import "ccMacros.h" +#import "CCTransition.h" +#import "CCScene.h" +#import "CCSpriteFrameCache.h" +#import "CCTexture2D.h" +#import "CCLabelBMFont.h" +#import "CCLayer.h" +#import "ccGLStateCache.h" +#import "CCShaderCache.h" +#import "ccFPSImages.h" +#import "CCDrawingPrimitives.h" +#import "CCConfiguration.h" + +// support imports +#import "Platforms/CCGL.h" +#import "Platforms/CCNS.h" + +#import "Support/OpenGL_Internal.h" +#import "Support/CGPointExtension.h" +#import "Support/CCProfiling.h" +#import "Support/CCFileUtils.h" + +#ifdef __CC_PLATFORM_IOS +#import "Platforms/iOS/CCDirectorIOS.h" +#define CC_DIRECTOR_DEFAULT CCDirectorDisplayLink +#elif defined(__CC_PLATFORM_MAC) +#import "Platforms/Mac/CCDirectorMac.h" +#define CC_DIRECTOR_DEFAULT CCDirectorDisplayLink +#endif + + +#pragma mark - +#pragma mark Director - global variables (optimization) + +// XXX it shoul be a Director ivar. Move it there once support for multiple directors is added +NSUInteger __ccNumberOfDraws = 0; + +#define kDefaultFPS 60.0 // 60 frames per second + +extern NSString * cocos2dVersion(void); + +@interface CCDirector (Private) +-(void) setNextScene; +// shows the statistics +-(void) showStats; +// calculates delta time since last time it was called +-(void) calculateDeltaTime; +// calculates the milliseconds per frame from the start of the frame +-(void) calculateMPF; +// returns the FPS image data pointer and len +-(void)getFPSImageData:(unsigned char**)datapointer length:(NSUInteger*)len; +@end + +@implementation CCDirector + +@synthesize animationInterval = _animationInterval; +@synthesize runningScene = _runningScene; +@synthesize displayStats = _displayStats; +@synthesize nextDeltaTimeZero = _nextDeltaTimeZero; +@synthesize paused = _isPaused; +@synthesize isAnimating = _isAnimating; +@synthesize sendCleanupToScene = _sendCleanupToScene; +@synthesize runningThread = _runningThread; +@synthesize notificationNode = _notificationNode; +@synthesize delegate = _delegate; +@synthesize totalFrames = _totalFrames; +@synthesize secondsPerFrame = _secondsPerFrame; +@synthesize scheduler = _scheduler; +@synthesize actionManager = _actionManager; + +// +// singleton stuff +// +static CCDirector *_sharedDirector = nil; + ++ (CCDirector *)sharedDirector +{ + if (!_sharedDirector) { + + // + // Default Director is DisplayLink + // + if( [ [CCDirector class] isEqual:[self class]] ) + _sharedDirector = [[CC_DIRECTOR_DEFAULT alloc] init]; + else + _sharedDirector = [[self alloc] init]; + } + + return _sharedDirector; +} + ++(id)alloc +{ + NSAssert(_sharedDirector == nil, @"Attempted to allocate a second instance of a singleton."); + return [super alloc]; +} + +- (id) init +{ + if( (self=[super init] ) ) { + + // scenes + _runningScene = nil; + _nextScene = nil; + + _notificationNode = nil; + + _oldAnimationInterval = _animationInterval = 1.0 / kDefaultFPS; + _scenesStack = [[NSMutableArray alloc] initWithCapacity:10]; + + // Set default projection (3D) + _projection = kCCDirectorProjectionDefault; + + // projection delegate if "Custom" projection is used + _delegate = nil; + + // FPS + _displayStats = NO; + _totalFrames = _frames = 0; + + // paused ? + _isPaused = NO; + + // running thread + _runningThread = nil; + + // scheduler + _scheduler = [[CCScheduler alloc] init]; + + // action manager + _actionManager = [[CCActionManager alloc] init]; + [_scheduler scheduleUpdateForTarget:_actionManager priority:kCCPrioritySystem paused:NO]; + + _winSizeInPixels = _winSizeInPoints = CGSizeZero; + } + + return self; +} + +- (NSString*) description +{ + return [NSString stringWithFormat:@"<%@ = %p | Size: %0.f x %0.f, view = %@>", [self class], self, _winSizeInPoints.width, _winSizeInPoints.height, __view]; +} + +- (void) dealloc +{ + CCLOGINFO(@"cocos2d: deallocing %@", self); + + [_FPSLabel release]; + [_SPFLabel release]; + [_drawsLabel release]; + [_runningScene release]; + [_notificationNode release]; + [_scenesStack release]; + [_scheduler release]; + [_actionManager release]; + + _sharedDirector = nil; + + [super dealloc]; +} + +-(void) setGLDefaultValues +{ + // This method SHOULD be called only after __view was initialized + NSAssert( __view, @"__view must be initialized"); + + [self setAlphaBlending: YES]; + [self setDepthTest: __view.depthFormat]; + [self setProjection: _projection]; + + // set other opengl default values + glClearColor(0.0f, 0.0f, 0.0f, 1.0f); +} + +// +// Draw the Scene +// +- (void) drawScene +{ + // Override me +} + +-(void) calculateDeltaTime +{ + struct timeval now; + + if( gettimeofday( &now, NULL) != 0 ) { + CCLOG(@"cocos2d: error in gettimeofday"); + _dt = 0; + return; + } + + // new delta time + if( _nextDeltaTimeZero ) { + _dt = 0; + _nextDeltaTimeZero = NO; + } else { + _dt = (now.tv_sec - _lastUpdate.tv_sec) + (now.tv_usec - _lastUpdate.tv_usec) / 1000000.0f; + _dt = MAX(0,_dt); + } + +#ifdef DEBUG + // If we are debugging our code, prevent big delta time + if( _dt > 0.2f ) + _dt = 1/60.0f; +#endif + + _lastUpdate = now; +} + +#pragma mark Director - Memory Helper + +-(void) purgeCachedData +{ + [CCLabelBMFont purgeCachedData]; + if ([_sharedDirector view]) + [[CCTextureCache sharedTextureCache] removeUnusedTextures]; + [[CCFileUtils sharedFileUtils] purgeCachedEntries]; +} + +#pragma mark Director - Scene OpenGL Helper + +-(ccDirectorProjection) projection +{ + return _projection; +} + +-(float) getZEye +{ + return ( _winSizeInPixels.height / 1.1566f / CC_CONTENT_SCALE_FACTOR() ); +} + +-(void) setViewport +{ + CCLOG(@"cocos2d: override me"); +} + +-(void) setProjection:(ccDirectorProjection)projection +{ + CCLOG(@"cocos2d: override me"); +} + +- (void) setAlphaBlending: (BOOL) on +{ + if (on) { + ccGLBlendFunc(CC_BLEND_SRC, CC_BLEND_DST); + + } else + ccGLBlendFunc(GL_ONE, GL_ZERO); + + CHECK_GL_ERROR_DEBUG(); +} + +- (void) setDepthTest: (BOOL) on +{ + if (on) { + glClearDepth(1.0f); + + glEnable(GL_DEPTH_TEST); + glDepthFunc(GL_LEQUAL); +// glHint(GL_PERSPECTIVE_CORRECTION_HINT, GL_NICEST); + } else + glDisable( GL_DEPTH_TEST ); + + CHECK_GL_ERROR_DEBUG(); +} + +#pragma mark Director Integration with a UIKit view + +-(void) setView:(CCGLView*)view +{ +// NSAssert( view, @"OpenGLView must be non-nil"); + + if( view != __view ) { + +#ifdef __CC_PLATFORM_IOS + [super setView:view]; +#endif + [__view release]; + __view = [view retain]; + + // set size + _winSizeInPixels = _winSizeInPoints = CCNSSizeToCGSize( [__view bounds].size ); + + // it could be nil + if( view ) { + [self createStatsLabel]; + [self setGLDefaultValues]; + } + + // Dump info once OpenGL was initilized + [[CCConfiguration sharedConfiguration] dumpInfo]; + + CHECK_GL_ERROR_DEBUG(); + } +} + +-(CCGLView*) view +{ + return __view; +} + + +#pragma mark Director Scene Landscape + +-(CGPoint)convertToGL:(CGPoint)uiPoint +{ + CCLOG(@"CCDirector#convertToGL: OVERRIDE ME."); + return CGPointZero; +} + +-(CGPoint)convertToUI:(CGPoint)glPoint +{ + CCLOG(@"CCDirector#convertToUI: OVERRIDE ME."); + return CGPointZero; +} + +-(CGSize)winSize +{ + return _winSizeInPoints; +} + +-(CGSize)winSizeInPixels +{ + return _winSizeInPixels; +} + +-(void) reshapeProjection:(CGSize)newWindowSize +{ + _winSizeInPixels = _winSizeInPoints = newWindowSize; + [self setProjection:_projection]; +} + +#pragma mark Director Scene Management + +- (void)runWithScene:(CCScene*) scene +{ + NSAssert( scene != nil, @"Argument must be non-nil"); + NSAssert(_runningScene == nil, @"This command can only be used to start the CCDirector. There is already a scene present."); + + [self pushScene:scene]; + [self startAnimation]; +} + +-(void) replaceScene: (CCScene*) scene +{ + NSAssert( _runningScene, @"Use runWithScene: instead to start the director"); + NSAssert( scene != nil, @"Argument must be non-nil"); + + NSUInteger index = [_scenesStack count]; + + _sendCleanupToScene = YES; + [_scenesStack replaceObjectAtIndex:index-1 withObject:scene]; + _nextScene = scene; // _nextScene is a weak ref +} + +- (void) pushScene: (CCScene*) scene +{ + NSAssert( scene != nil, @"Argument must be non-nil"); + + _sendCleanupToScene = NO; + + [_scenesStack addObject: scene]; + _nextScene = scene; // _nextScene is a weak ref +} + +-(void) popScene +{ + NSAssert( _runningScene != nil, @"A running Scene is needed"); + + [_scenesStack removeLastObject]; + NSUInteger c = [_scenesStack count]; + + if( c == 0 ) + [self end]; + else { + _sendCleanupToScene = YES; + _nextScene = [_scenesStack objectAtIndex:c-1]; + } +} + +-(void) popToRootScene +{ + [self popToSceneStackLevel:1]; +} + +-(void) popToSceneStackLevel:(NSUInteger)level +{ + NSAssert(_runningScene != nil, @"A running Scene is needed"); + NSUInteger c = [_scenesStack count]; + + // level 0? -> end + if( level == 0) { + [self end]; + return; + } + + // current level or lower -> nothing + if( level >= c) + return; + + // pop stack until reaching desired level + while (c > level) { + CCScene *current = [_scenesStack lastObject]; + if( [current isRunning] ){ + [current onExitTransitionDidStart]; + [current onExit]; + } + [current cleanup]; + + [_scenesStack removeLastObject]; + c--; + } + _nextScene = [_scenesStack lastObject]; + _sendCleanupToScene = NO; +} + +-(void) end +{ + [_runningScene onExitTransitionDidStart]; + [_runningScene onExit]; + [_runningScene cleanup]; + [_runningScene release]; + + _runningScene = nil; + _nextScene = nil; + + // remove all objects, but don't release it. + // runWithScene might be executed after 'end'. + [_scenesStack removeAllObjects]; + + [self stopAnimation]; + + [_FPSLabel release]; + [_SPFLabel release]; + [_drawsLabel release]; + _FPSLabel = nil, _SPFLabel=nil, _drawsLabel=nil; + + _delegate = nil; + + [self setView:nil]; + + // Purge bitmap cache + [CCLabelBMFont purgeCachedData]; + + // Purge all managers / caches + ccDrawFree(); + [CCAnimationCache purgeSharedAnimationCache]; + [CCSpriteFrameCache purgeSharedSpriteFrameCache]; + [CCTextureCache purgeSharedTextureCache]; + [CCShaderCache purgeSharedShaderCache]; + [[CCFileUtils sharedFileUtils] purgeCachedEntries]; + + // OpenGL view + + // Since the director doesn't attach the openglview to the window + // it shouldn't remove it from the window too. +// [openGLView_ removeFromSuperview]; + + + // Invalidate GL state cache + ccGLInvalidateStateCache(); + + CHECK_GL_ERROR(); +} + +-(void) setNextScene +{ + Class transClass = [CCTransitionScene class]; + BOOL runningIsTransition = [_runningScene isKindOfClass:transClass]; + BOOL newIsTransition = [_nextScene isKindOfClass:transClass]; + + // If it is not a transition, call onExit/cleanup + if( ! newIsTransition ) { + [_runningScene onExitTransitionDidStart]; + [_runningScene onExit]; + + // issue #709. the root node (scene) should receive the cleanup message too + // otherwise it might be leaked. + if( _sendCleanupToScene) + [_runningScene cleanup]; + } + + [_runningScene release]; + + _runningScene = [_nextScene retain]; + _nextScene = nil; + + if( ! runningIsTransition ) { + [_runningScene onEnter]; + [_runningScene onEnterTransitionDidFinish]; + } +} + +-(void) pause +{ + if( _isPaused ) + return; + + _oldAnimationInterval = _animationInterval; + + // when paused, don't consume CPU + [self setAnimationInterval:1/4.0]; + + [self willChangeValueForKey:@"isPaused"]; + _isPaused = YES; + [self didChangeValueForKey:@"isPaused"]; +} + +-(void) resume +{ + if( ! _isPaused ) + return; + + [self setAnimationInterval: _oldAnimationInterval]; + + if( gettimeofday( &_lastUpdate, NULL) != 0 ) { + CCLOG(@"cocos2d: Director: Error in gettimeofday"); + } + + [self willChangeValueForKey:@"isPaused"]; + _isPaused = NO; + [self didChangeValueForKey:@"isPaused"]; + + _dt = 0; +} + +- (void)startAnimation +{ + _nextDeltaTimeZero = YES; +} + +- (void)stopAnimation +{ + CCLOG(@"cocos2d: Director#stopAnimation. Override me"); +} + +- (void)setAnimationInterval:(NSTimeInterval)interval +{ + CCLOG(@"cocos2d: Director#setAnimationInterval. Override me"); +} + + +// display statistics +-(void) showStats +{ + _frames++; + _accumDt += _dt; + + if( _displayStats ) { + // Ms per Frame + + if( _accumDt > CC_DIRECTOR_STATS_INTERVAL) + { + NSString *spfstr = [[NSString alloc] initWithFormat:@"%.3f", _secondsPerFrame]; + [_SPFLabel setString:spfstr]; + [spfstr release]; + + _frameRate = _frames/_accumDt; + _frames = 0; + _accumDt = 0; + +// sprintf(format,"%.1f",frameRate); +// [FPSLabel setCString:format]; + + NSString *fpsstr = [[NSString alloc] initWithFormat:@"%.1f", _frameRate]; + [_FPSLabel setString:fpsstr]; + [fpsstr release]; + + NSString *draws = [[NSString alloc] initWithFormat:@"%4lu", (unsigned long)__ccNumberOfDraws]; + [_drawsLabel setString:draws]; + [draws release]; + } + + [_drawsLabel visit]; + [_FPSLabel visit]; + [_SPFLabel visit]; + } + + __ccNumberOfDraws = 0; +} + +-(void) calculateMPF +{ + struct timeval now; + gettimeofday( &now, NULL); + + _secondsPerFrame = (now.tv_sec - _lastUpdate.tv_sec) + (now.tv_usec - _lastUpdate.tv_usec) / 1000000.0f; +} + +#pragma mark Director - Helper + +-(void)getFPSImageData:(unsigned char**)datapointer length:(NSUInteger*)len +{ + *datapointer = cc_fps_images_png; + *len = cc_fps_images_len(); +} + +-(void) createStatsLabel +{ + CCTexture2D *texture; + CCTextureCache *textureCache = [CCTextureCache sharedTextureCache]; + + if( _FPSLabel && _SPFLabel ) { + + [_FPSLabel release]; + [_SPFLabel release]; + [_drawsLabel release]; + [textureCache removeTextureForKey:@"cc_fps_images"]; + _FPSLabel = nil; + _SPFLabel = nil; + _drawsLabel = nil; + + [[CCFileUtils sharedFileUtils] purgeCachedEntries]; + } + + CCTexture2DPixelFormat currentFormat = [CCTexture2D defaultAlphaPixelFormat]; + [CCTexture2D setDefaultAlphaPixelFormat:kCCTexture2DPixelFormat_RGBA4444]; + + unsigned char *data; + NSUInteger data_len; + [self getFPSImageData:&data length:&data_len]; + + NSData *nsdata = [NSData dataWithBytes:data length:data_len]; + CGDataProviderRef imgDataProvider = CGDataProviderCreateWithCFData( (CFDataRef) nsdata); + CGImageRef imageRef = CGImageCreateWithPNGDataProvider(imgDataProvider, NULL, true, kCGRenderingIntentDefault); + texture = [textureCache addCGImage:imageRef forKey:@"cc_fps_images"]; + CGDataProviderRelease(imgDataProvider); + CGImageRelease(imageRef); + + _FPSLabel = [[CCLabelAtlas alloc] initWithString:@"00.0" texture:texture itemWidth:12 itemHeight:32 startCharMap:'.']; + _SPFLabel = [[CCLabelAtlas alloc] initWithString:@"0.000" texture:texture itemWidth:12 itemHeight:32 startCharMap:'.']; + _drawsLabel = [[CCLabelAtlas alloc] initWithString:@"000" texture:texture itemWidth:12 itemHeight:32 startCharMap:'.']; + + [CCTexture2D setDefaultAlphaPixelFormat:currentFormat]; + + [_drawsLabel setPosition: ccpAdd( ccp(0,34), CC_DIRECTOR_STATS_POSITION ) ]; + [_SPFLabel setPosition: ccpAdd( ccp(0,17), CC_DIRECTOR_STATS_POSITION ) ]; + [_FPSLabel setPosition: CC_DIRECTOR_STATS_POSITION ]; +} + +@end + diff --git "a/21451198\345\215\242\350\266\205/project5/MyPlane/libs/cocos2d/CCDrawNode.h" "b/21451198\345\215\242\350\266\205/project5/MyPlane/libs/cocos2d/CCDrawNode.h" new file mode 100644 index 00000000..9a190daf --- /dev/null +++ "b/21451198\345\215\242\350\266\205/project5/MyPlane/libs/cocos2d/CCDrawNode.h" @@ -0,0 +1,65 @@ +/* Copyright (c) 2012 Scott Lembcke and Howling Moon Software + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + * SOFTWARE. + */ + +/* + * Code copied & pasted from SpacePatrol game https://github.com/slembcke/SpacePatrol + * + * Renamed and added some changes for cocos2d + * + */ + +#import "CCNode.h" + +/** CCDrawNode + Node that draws dots, segments and polygons. + Faster than the "drawing primitives" since they it draws everything in one single batch. + + @since v2.1 + */ +@interface CCDrawNode : CCNode +{ + GLuint _vao; + GLuint _vbo; + + NSUInteger _bufferCapacity; + GLsizei _bufferCount; + ccV2F_C4B_T2F *_buffer; + + ccBlendFunc _blendFunc; + + BOOL _dirty; +} + +@property(nonatomic, assign) ccBlendFunc blendFunc; + +/** draw a dot at a position, with a given radius and color */ +-(void)drawDot:(CGPoint)pos radius:(CGFloat)radius color:(ccColor4F)color; + +/** draw a segment with a radius and color */ +-(void)drawSegmentFrom:(CGPoint)a to:(CGPoint)b radius:(CGFloat)radius color:(ccColor4F)color; + +/** draw a polygon with a fill color and line color */ +-(void)drawPolyWithVerts:(CGPoint*)verts count:(NSUInteger)count fillColor:(ccColor4F)fill borderWidth:(CGFloat)width borderColor:(ccColor4F)line; + +/** Clear the geometry in the node's buffer. */ +-(void)clear; + +@end diff --git "a/21451198\345\215\242\350\266\205/project5/MyPlane/libs/cocos2d/CCDrawNode.m" "b/21451198\345\215\242\350\266\205/project5/MyPlane/libs/cocos2d/CCDrawNode.m" new file mode 100644 index 00000000..e92f71f4 --- /dev/null +++ "b/21451198\345\215\242\350\266\205/project5/MyPlane/libs/cocos2d/CCDrawNode.m" @@ -0,0 +1,377 @@ +/* Copyright (c) 2012 Scott Lembcke and Howling Moon Software + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + * SOFTWARE. + */ + +/* + * Code copied & pasted from SpacePatrol game https://github.com/slembcke/SpacePatrol + * + * Renamed and added some changes for cocos2d + * + */ + +#import "CCDrawNode.h" +#import "CCShaderCache.h" +#import "CCGLProgram.h" +#import "Support/CGPointExtension.h" +#import "Support/OpenGL_Internal.h" + + +// ccVertex2F == CGPoint in 32-bits, but not in 64-bits (OS X) +// that's why the "v2f" functions are needed +static ccVertex2F v2fzero = (ccVertex2F){0,0}; + +static inline ccVertex2F v2f( float x, float y ) +{ + return (ccVertex2F){x,y}; +} + +static inline ccVertex2F v2fadd( ccVertex2F v0, ccVertex2F v1 ) +{ + return v2f( v0.x+v1.x, v0.y+v1.y ); +} + +static inline ccVertex2F v2fsub( ccVertex2F v0, ccVertex2F v1 ) +{ + return v2f( v0.x-v1.x, v0.y-v1.y ); +} + +static inline ccVertex2F v2fmult( ccVertex2F v, float s ) +{ + return v2f( v.x * s, v.y * s ); +} + +static inline ccVertex2F v2fperp( ccVertex2F p0 ) +{ + return v2f( -p0.y, p0.x ); +} + +static inline ccVertex2F v2fneg( ccVertex2F p0 ) +{ + return v2f( -p0.x, - p0.y ); +} + +static inline float v2fdot(ccVertex2F p0, ccVertex2F p1) +{ + return p0.x * p1.x + p0.y * p1.y; +} + +static inline ccVertex2F v2fforangle( float _a_) +{ + return v2f( cosf(_a_), sinf(_a_) ); +} + +static inline ccVertex2F v2fnormalize( ccVertex2F p ) +{ + CGPoint r = ccpNormalize( ccp(p.x, p.y) ); + return v2f( r.x, r.y); +} + +static inline ccVertex2F __v2f(CGPoint v ) +{ +#ifdef __LP64__ + return v2f(v.x, v.y); +#else + return * ((ccVertex2F*) &v); +#endif +} + +static inline ccTex2F __t(ccVertex2F v ) +{ + return *(ccTex2F*)&v; +} + + +@implementation CCDrawNode + +@synthesize blendFunc = _blendFunc; + +#pragma mark memory + +-(void)ensureCapacity:(NSUInteger)count +{ + if(_bufferCount + count > _bufferCapacity){ + _bufferCapacity += MAX(_bufferCapacity, count); + _buffer = realloc(_buffer, _bufferCapacity*sizeof(ccV2F_C4B_T2F)); + +// NSLog(@"Resized vertex buffer to %d", _bufferCapacity); + } +} + +-(id)init +{ + if((self = [super init])){ + self.blendFunc = (ccBlendFunc){CC_BLEND_SRC, CC_BLEND_DST}; + + self.shaderProgram = [[CCShaderCache sharedShaderCache] programForKey:kCCShader_PositionLengthTexureColor]; + + [self ensureCapacity:512]; + + glGenVertexArrays(1, &_vao); + ccGLBindVAO(_vao); + + glGenBuffers(1, &_vbo); + glBindBuffer(GL_ARRAY_BUFFER, _vbo); + glBufferData(GL_ARRAY_BUFFER, sizeof(ccV2F_C4B_T2F)*_bufferCapacity, _buffer, GL_STREAM_DRAW); + + glEnableVertexAttribArray(kCCVertexAttrib_Position); + glVertexAttribPointer(kCCVertexAttrib_Position, 2, GL_FLOAT, GL_FALSE, sizeof(ccV2F_C4B_T2F), (GLvoid *)offsetof(ccV2F_C4B_T2F, vertices)); + + glEnableVertexAttribArray(kCCVertexAttrib_Color); + glVertexAttribPointer(kCCVertexAttrib_Color, 4, GL_UNSIGNED_BYTE, GL_TRUE, sizeof(ccV2F_C4B_T2F), (GLvoid *)offsetof(ccV2F_C4B_T2F, colors)); + + glEnableVertexAttribArray(kCCVertexAttrib_TexCoords); + glVertexAttribPointer(kCCVertexAttrib_TexCoords, 2, GL_FLOAT, GL_FALSE, sizeof(ccV2F_C4B_T2F), (GLvoid *)offsetof(ccV2F_C4B_T2F, texCoords)); + + glBindBuffer(GL_ARRAY_BUFFER, 0); + ccGLBindVAO(0); + + CHECK_GL_ERROR(); + + _dirty = YES; + } + + return self; +} + +-(void)dealloc +{ +#ifdef __CC_PLATFORM_IOS + NSAssert([EAGLContext currentContext], @"No GL context set!"); +#endif + + free(_buffer); _buffer = NULL; + + glDeleteBuffers(1, &_vbo); _vbo = 0; + glDeleteVertexArrays(1, &_vao); _vao = 0; + + [super dealloc]; +} + +#pragma mark Rendering + +-(void)render +{ + if( _dirty ) { + glBindBuffer(GL_ARRAY_BUFFER, _vbo); + glBufferData(GL_ARRAY_BUFFER, sizeof(ccV2F_C4B_T2F)*_bufferCapacity, _buffer, GL_STREAM_DRAW); + glBindBuffer(GL_ARRAY_BUFFER, 0); + _dirty = NO; + } + + ccGLBindVAO(_vao); + glDrawArrays(GL_TRIANGLES, 0, _bufferCount); + + CC_INCREMENT_GL_DRAWS(1); + + CHECK_GL_ERROR(); +} + +-(void)draw +{ + ccGLBlendFunc(_blendFunc.src, _blendFunc.dst); + + [_shaderProgram use]; + [_shaderProgram setUniformsForBuiltins]; + + [self render]; +} + +#pragma mark Immediate Mode + +-(void)drawDot:(CGPoint)pos radius:(CGFloat)radius color:(ccColor4F)color; +{ + NSUInteger vertex_count = 2*3; + [self ensureCapacity:vertex_count]; + + ccV2F_C4B_T2F a = {{pos.x - radius, pos.y - radius}, ccc4BFromccc4F(color), {-1.0, -1.0} }; + ccV2F_C4B_T2F b = {{pos.x - radius, pos.y + radius}, ccc4BFromccc4F(color), {-1.0, 1.0} }; + ccV2F_C4B_T2F c = {{pos.x + radius, pos.y + radius}, ccc4BFromccc4F(color), { 1.0, 1.0} }; + ccV2F_C4B_T2F d = {{pos.x + radius, pos.y - radius}, ccc4BFromccc4F(color), { 1.0, -1.0} }; + + ccV2F_C4B_T2F_Triangle *triangles = (ccV2F_C4B_T2F_Triangle *)(_buffer + _bufferCount); + triangles[0] = (ccV2F_C4B_T2F_Triangle){a, b, c}; + triangles[1] = (ccV2F_C4B_T2F_Triangle){a, c, d}; + + _bufferCount += vertex_count; + + _dirty = YES; +} + +-(void)drawSegmentFrom:(CGPoint)_a to:(CGPoint)_b radius:(CGFloat)radius color:(ccColor4F)color; +{ + NSUInteger vertex_count = 6*3; + [self ensureCapacity:vertex_count]; + + ccVertex2F a = __v2f(_a); + ccVertex2F b = __v2f(_b); + + + ccVertex2F n = v2fnormalize(v2fperp(v2fsub(b, a))); + ccVertex2F t = v2fperp(n); + + ccVertex2F nw = v2fmult(n, radius); + ccVertex2F tw = v2fmult(t, radius); + ccVertex2F v0 = v2fsub(b, v2fadd(nw, tw)); + ccVertex2F v1 = v2fadd(b, v2fsub(nw, tw)); + ccVertex2F v2 = v2fsub(b, nw); + ccVertex2F v3 = v2fadd(b, nw); + ccVertex2F v4 = v2fsub(a, nw); + ccVertex2F v5 = v2fadd(a, nw); + ccVertex2F v6 = v2fsub(a, v2fsub(nw, tw)); + ccVertex2F v7 = v2fadd(a, v2fadd(nw, tw)); + + + ccV2F_C4B_T2F_Triangle *triangles = (ccV2F_C4B_T2F_Triangle *)(_buffer + _bufferCount); + + triangles[0] = (ccV2F_C4B_T2F_Triangle) { + {v0, ccc4BFromccc4F(color), __t(v2fneg(v2fadd(n, t))) }, + {v1, ccc4BFromccc4F(color), __t(v2fsub(n, t)) }, + {v2, ccc4BFromccc4F(color), __t(v2fneg(n)) }, + }; + + triangles[1] = (ccV2F_C4B_T2F_Triangle){ + {v3, ccc4BFromccc4F(color), __t(n)}, + {v1, ccc4BFromccc4F(color), __t(v2fsub(n, t)) }, + {v2, ccc4BFromccc4F(color), __t(v2fneg(n)) }, + }; + + triangles[2] = (ccV2F_C4B_T2F_Triangle){ + {v3, ccc4BFromccc4F(color), __t(n)}, + {v4, ccc4BFromccc4F(color), __t(v2fneg(n)) }, + {v2, ccc4BFromccc4F(color), __t(v2fneg(n)) }, + }; + triangles[3] = (ccV2F_C4B_T2F_Triangle){ + {v3, ccc4BFromccc4F(color), __t(n) }, + {v4, ccc4BFromccc4F(color), __t(v2fneg(n)) }, + {v5, ccc4BFromccc4F(color), __t(n) }, + }; + triangles[4] = (ccV2F_C4B_T2F_Triangle){ + {v6, ccc4BFromccc4F(color), __t(v2fsub(t, n))}, + {v4, ccc4BFromccc4F(color), __t(v2fneg(n)) }, + {v5, ccc4BFromccc4F(color), __t(n)}, + }; + triangles[5] = (ccV2F_C4B_T2F_Triangle){ + {v6, ccc4BFromccc4F(color), __t(v2fsub(t, n)) }, + {v7, ccc4BFromccc4F(color), __t(v2fadd(n, t)) }, + {v5, ccc4BFromccc4F(color), __t(n)}, + }; + + _bufferCount += vertex_count; + + _dirty = YES; +} + +-(void)drawPolyWithVerts:(CGPoint *)verts count:(NSUInteger)count fillColor:(ccColor4F)fill borderWidth:(CGFloat)width borderColor:(ccColor4F)line; +{ + struct ExtrudeVerts {ccVertex2F offset, n;}; + struct ExtrudeVerts extrude[count]; + bzero(extrude, sizeof(extrude) ); + + for(int i=0; i 0.0 && width > 0.0); + + NSUInteger triangle_count = 3*count - 2; + NSUInteger vertex_count = 3*triangle_count; + [self ensureCapacity:vertex_count]; + + ccV2F_C4B_T2F_Triangle *triangles = (ccV2F_C4B_T2F_Triangle *)(_buffer + _bufferCount); + ccV2F_C4B_T2F_Triangle *cursor = triangles; + + CGFloat inset = (outline == 0.0 ? 0.5 : 0.0); + for(int i=0; i + +#import "ccTypes.h" +#import "ccMacros.h" + +#ifdef __CC_PLATFORM_IOS +#import // for CGPoint +#endif + + +#ifdef __cplusplus +extern "C" { +#endif + +@class CCPointArray; + + +/** + @file + Drawing OpenGL ES primitives. + - ccDrawPoint, ccDrawPoints + - ccDrawLine + - ccDrawRect, ccDrawSolidRect + - ccDrawPoly, ccDrawSolidPoly + - ccDrawCircle, ccDrawSolidCircle + - ccDrawArc, ccDrawSolidArc + - ccDrawQuadBezier + - ccDrawCubicBezier + - ccDrawCatmullRom + - ccDrawCardinalSpline + + You can change the color, point size, width by calling: + - ccDrawColor4B(), ccDrawColor4F() + - ccPointSize() + - glLineWidth() + + @warning These functions draws the Line, Point, Polygon, immediately. They aren't batched. If you are going to make a game that depends on these primitives, I suggest creating a batch. Instead you should use CCDrawNode + + */ + + +/** Initializes the drawing primitives */ +void ccDrawInit(void); + +/** Frees allocated resources by the drawing primitives */ +void ccDrawFree(void); + +/** draws a point given x and y coordinate measured in points. */ +void ccDrawPoint( CGPoint point ); + +/** draws an array of points. + @since v0.7.2 + */ +void ccDrawPoints( const CGPoint *points, NSUInteger numberOfPoints ); + +/** draws a line given the origin and destination point measured in points. */ +void ccDrawLine( CGPoint origin, CGPoint destination ); + +/** draws a rectangle given the origin and destination point measured in points. */ +void ccDrawRect( CGPoint origin, CGPoint destination ); + +/** draws a solid rectangle given the origin and destination point measured in points. + @since 1.1 + */ +void ccDrawSolidRect( CGPoint origin, CGPoint destination, ccColor4F color ); + +/** draws a polygon given a pointer to CGPoint coordinates and the number of vertices measured in points. + The polygon can be closed or open + */ +void ccDrawPoly( const CGPoint *vertices, NSUInteger numOfVertices, BOOL closePolygon ); + +/** draws a solid polygon given a pointer to CGPoint coordinates, the number of vertices measured in points, and a color. + */ +void ccDrawSolidPoly( const CGPoint *poli, NSUInteger numberOfPoints, ccColor4F color ); + +/** draws a circle given the center, radius and number of segments measured in points */ +void ccDrawCircle( CGPoint center, float radius, float angle, NSUInteger segments, BOOL drawLineToCenter); + +/** draws a solid circle given the center, radius and number of segments measured in points */ +void ccDrawSolidCircle( CGPoint center, float radius, NSUInteger segments); + +/** draws a arc given the center, radius, arc length and number of segments measured in points */ +void ccDrawArc(CGPoint center, CGFloat r, CGFloat a, CGFloat arcLength, NSUInteger segs, BOOL drawLineToCenter); + +/** draws a solid arc given the center, radius, arc length and number of segments measured in points */ +void ccDrawSolidArc(CGPoint center, CGFloat r, CGFloat a, CGFloat arcLength, NSUInteger segs); + +/** draws a quad bezier path measured in points. + @warning This function could be pretty slow. Use it only for debugging purposes. + @since v0.8 + */ +void ccDrawQuadBezier(CGPoint origin, CGPoint control, CGPoint destination, NSUInteger segments); + +/** draws a cubic bezier path measured in points. + @warning This function could be pretty slow. Use it only for debugging purposes. + @since v0.8 + */ +void ccDrawCubicBezier(CGPoint origin, CGPoint control1, CGPoint control2, CGPoint destination, NSUInteger segments); + +/** draws a Catmull Rom path. + @warning This function could be pretty slow. Use it only for debugging purposes. + @since v2.0 + */ +void ccDrawCatmullRom( CCPointArray *arrayOfControlPoints, NSUInteger segments ); + +/** draws a Cardinal Spline path. + @warning This function could be pretty slow. Use it only for debugging purposes. + @since v2.0 + */ +void ccDrawCardinalSpline( CCPointArray *config, CGFloat tension, NSUInteger segments ); + +/** set the drawing color with 4 unsigned bytes + @since v2.0 + */ +void ccDrawColor4B( GLubyte r, GLubyte g, GLubyte b, GLubyte a ); + +/** set the drawing color with 4 floats + @since v2.0 + */ +void ccDrawColor4F( GLfloat r, GLfloat g, GLfloat b, GLfloat a ); + +/** set the point size in points. Default 1. + @since v2.0 + */ +void ccPointSize( GLfloat pointSize ); + + +#ifdef __cplusplus +} +#endif + +#endif // __CC_DRAWING_PRIMITIVES_H diff --git "a/21451198\345\215\242\350\266\205/project5/MyPlane/libs/cocos2d/CCDrawingPrimitives.m" "b/21451198\345\215\242\350\266\205/project5/MyPlane/libs/cocos2d/CCDrawingPrimitives.m" new file mode 100644 index 00000000..98e0f316 --- /dev/null +++ "b/21451198\345\215\242\350\266\205/project5/MyPlane/libs/cocos2d/CCDrawingPrimitives.m" @@ -0,0 +1,531 @@ +/* + * cocos2d for iPhone: http://www.cocos2d-iphone.org + * + * Copyright (c) 2008-2010 Ricardo Quesada + * Copyright (c) 2011 Zynga Inc. + * Copyright (c) 2013 Nader Eloshaiker + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + * THE SOFTWARE. + */ + +/* + * + * IMPORTANT IMPORTANT IMPORTANT IMPORTANT + * + * + * LEGACY FUNCTIONS + * + * USE CCDrawNode instead + * + */ + +#import +#import +#import + +#import "CCDrawingPrimitives.h" +#import "ccMacros.h" +#import "Platforms/CCGL.h" +#import "ccGLStateCache.h" +#import "CCShaderCache.h" +#import "CCGLProgram.h" +#import "CCActionCatmullRom.h" +#import "Support/OpenGL_Internal.h" + + +static BOOL initialized = NO; +static CCGLProgram *shader_ = nil; +static int colorLocation_ = -1; +static ccColor4F color_ = {1,1,1,1}; +static int pointSizeLocation_ = -1; +static GLfloat pointSize_ = 1; + +static void lazy_init( void ) +{ + if( ! initialized ) { + + // + // Position and 1 color passed as a uniform (to similate glColor4ub ) + // + shader_ = [[CCShaderCache sharedShaderCache] programForKey:kCCShader_Position_uColor]; + [shader_ retain]; + + colorLocation_ = glGetUniformLocation( shader_.program, "u_color"); + pointSizeLocation_ = glGetUniformLocation( shader_.program, "u_pointSize"); + + initialized = YES; + } + +} + +void ccDrawFree(void) +{ + [shader_ release]; + + shader_ = nil; + initialized = NO; +} + +void ccDrawInit(void) +{ + lazy_init(); +} + +void ccDrawPoint( CGPoint point ) +{ + lazy_init(); + + ccVertex2F p = (ccVertex2F) {point.x, point.y}; + + ccGLEnableVertexAttribs( kCCVertexAttribFlag_Position ); + + [shader_ use]; + [shader_ setUniformsForBuiltins]; + + [shader_ setUniformLocation:colorLocation_ with4fv:(GLfloat*) &color_.r count:1]; + [shader_ setUniformLocation:pointSizeLocation_ withF1:pointSize_]; + + glVertexAttribPointer(kCCVertexAttrib_Position, 2, GL_FLOAT, GL_FALSE, 0, &p); + + glDrawArrays(GL_POINTS, 0, 1); + + CC_INCREMENT_GL_DRAWS(1); +} + +void ccDrawPoints( const CGPoint *points, NSUInteger numberOfPoints ) +{ + lazy_init(); + + ccGLEnableVertexAttribs( kCCVertexAttribFlag_Position ); + + [shader_ use]; + [shader_ setUniformsForBuiltins]; + [shader_ setUniformLocation:colorLocation_ with4fv:(GLfloat*) &color_.r count:1]; + [shader_ setUniformLocation:pointSizeLocation_ withF1:pointSize_]; + + // XXX: Mac OpenGL error. arrays can't go out of scope before draw is executed + ccVertex2F newPoints[numberOfPoints]; + + // iPhone and 32-bit machines optimization + if( sizeof(CGPoint) == sizeof(ccVertex2F) ) + glVertexAttribPointer(kCCVertexAttrib_Position, 2, GL_FLOAT, GL_FALSE, 0, points); + + else + { + // Mac on 64-bit + for( NSUInteger i=0; i +#import "ccMacros.h" +#import "Platforms/CCGL.h" + +enum { + kCCVertexAttrib_Position, + kCCVertexAttrib_Color, + kCCVertexAttrib_TexCoords, + + kCCVertexAttrib_MAX, +}; + +enum { + kCCUniformPMatrix, + kCCUniformMVMatrix, + kCCUniformMVPMatrix, + kCCUniformTime, + kCCUniformSinTime, + kCCUniformCosTime, + kCCUniformRandom01, + kCCUniformSampler, + + kCCUniform_MAX, +}; + +#define kCCShader_PositionTextureColor @"ShaderPositionTextureColor" +#define kCCShader_PositionTextureColorAlphaTest @"ShaderPositionTextureColorAlphaTest" +#define kCCShader_PositionColor @"ShaderPositionColor" +#define kCCShader_PositionTexture @"ShaderPositionTexture" +#define kCCShader_PositionTexture_uColor @"ShaderPositionTexture_uColor" +#define kCCShader_PositionTextureA8Color @"ShaderPositionTextureA8Color" +#define kCCShader_Position_uColor @"ShaderPosition_uColor" +#define kCCShader_PositionLengthTexureColor @"ShaderPositionLengthTextureColor" + +// uniform names +#define kCCUniformPMatrix_s "CC_PMatrix" +#define kCCUniformMVMatrix_s "CC_MVMatrix" +#define kCCUniformMVPMatrix_s "CC_MVPMatrix" +#define kCCUniformTime_s "CC_Time" +#define kCCUniformSinTime_s "CC_SinTime" +#define kCCUniformCosTime_s "CC_CosTime" +#define kCCUniformRandom01_s "CC_Random01" +#define kCCUniformSampler_s "CC_Texture0" +#define kCCUniformAlphaTestValue_s "CC_AlphaValue" + +// Attribute names +#define kCCAttributeNameColor @"a_color" +#define kCCAttributeNamePosition @"a_position" +#define kCCAttributeNameTexCoord @"a_texCoord" + + +struct _hashUniformEntry; + +/** CCGLProgram + Class that implements a glProgram + + + @since v2.0.0 + */ +@interface CCGLProgram : NSObject +{ + struct _hashUniformEntry *_hashForUniforms; + +@public + GLuint _program, + _vertShader, + _fragShader; + + GLint _uniforms[kCCUniform_MAX]; + + struct { + unsigned int usesTime:1; + unsigned int usesMVP:1; + unsigned int usesMV:1; + unsigned int usesRandom:1; + } _flags; +} + +@property(nonatomic, readonly) GLuint program; + +/** creates the CCGLProgram with a vertex and fragment from byte arrays */ ++ (id)programWithVertexShaderByteArray:(const GLchar*)vShaderByteArray fragmentShaderByteArray:(const GLchar*)fShaderByteArray; + +/** creates the CCGLProgram with a vertex and fragment with contents of filenames */ ++ (id)programWithVertexShaderFilename:(NSString *)vShaderFilename fragmentShaderFilename:(NSString *)fShaderFilename; + +/** Initializes the CCGLProgram with a vertex and fragment with bytes array */ +- (id)initWithVertexShaderByteArray:(const GLchar*)vShaderByteArray fragmentShaderByteArray:(const GLchar*)fShaderByteArray; + +/** Initializes the CCGLProgram with a vertex and fragment with contents of filenames */ +- (id)initWithVertexShaderFilename:(NSString *)vShaderFilename fragmentShaderFilename:(NSString *)fShaderFilename; + +/** It will add a new attribute to the shader */ +- (void)addAttribute:(NSString *)attributeName index:(GLuint)index; + +/** links the glProgram */ +- (BOOL)link; + +/** it will call glUseProgram() */ +- (void)use; + +/** It will create 4 uniforms: + - kCCUniformPMatrix + - kCCUniformMVMatrix + - kCCUniformMVPMatrix + - kCCUniformSampler + + And it will bind "kCCUniformSampler" to 0 + */ +- (void) updateUniforms; + +/** calls retrieves the named uniform location for this shader program. */ +- (GLint)uniformLocationForName:(NSString*)name; + +/** calls glUniform1i only if the values are different than the previous call for this same shader program. */ +-(void) setUniformLocation:(GLint)location withI1:(GLint)i1; + +/** calls glUniform1f only if the values are different than the previous call for this same shader program. */ +-(void) setUniformLocation:(GLint)location withF1:(GLfloat)f1; + +/** calls glUniform2f only if the values are different than the previous call for this same shader program. */ +-(void) setUniformLocation:(GLint)location withF1:(GLfloat)f1 f2:(GLfloat)f2; + +/** calls glUniform3f only if the values are different than the previous call for this same shader program. */ +-(void) setUniformLocation:(GLint)location withF1:(GLfloat)f1 f2:(GLfloat)f2 f3:(GLfloat)f3; + +/** calls glUniform4f only if the values are different than the previous call for this same shader program. */ +-(void) setUniformLocation:(GLint)location withF1:(GLfloat)f1 f2:(GLfloat)f2 f3:(GLfloat)f3 f4:(GLfloat)f4; + +/** calls glUniform2fv only if the values are different than the previous call for this same shader program. */ +-(void) setUniformLocation:(GLint)location with2fv:(GLfloat*)floats count:(NSUInteger)numberOfArrays; + +/** calls glUniform3fv only if the values are different than the previous call for this same shader program. */ +-(void) setUniformLocation:(GLint)location with3fv:(GLfloat*)floats count:(NSUInteger)numberOfArrays; + +/** calls glUniform4fv only if the values are different than the previous call for this same shader program. */ +-(void) setUniformLocation:(GLint)location with4fv:(GLvoid*)floats count:(NSUInteger)numberOfArrays; + +/** calls glUniformMatrix4fv only if the values are different than the previous call for this same shader program. */ +-(void) setUniformLocation:(GLint)location withMatrix4fv:(GLvoid*)matrix_array count:(NSUInteger)numberOfMatrix; + +/** will update the builtin uniforms if they are different than the previous call for this same shader program. */ +-(void) setUniformsForBuiltins; + +/** Deprecated alias for setUniformsForBuiltins */ +-(void)setUniformForModelViewProjectionMatrix __attribute__((__deprecated__)); + +/** returns the vertexShader error log */ +- (NSString *)vertexShaderLog; + +/** returns the fragmentShader error log */ +- (NSString *)fragmentShaderLog; + +/** returns the program error log */ +- (NSString *)programLog; +@end diff --git "a/21451198\345\215\242\350\266\205/project5/MyPlane/libs/cocos2d/CCGLProgram.m" "b/21451198\345\215\242\350\266\205/project5/MyPlane/libs/cocos2d/CCGLProgram.m" new file mode 100644 index 00000000..59075fd0 --- /dev/null +++ "b/21451198\345\215\242\350\266\205/project5/MyPlane/libs/cocos2d/CCGLProgram.m" @@ -0,0 +1,492 @@ +// +// Copyright 2011 Jeff Lamarche +// +// Copyright 2012 Goffredo Marocchi +// +// Copyright 2012 Ricardo Quesada +// +// +// Redistribution and use in source and binary forms, with or without modification, are permitted provided +// that the following conditions are met: +// 1. Redistributions of source code must retain the above copyright notice, this list of conditions and +// the following disclaimer. +// +// 2. Redistributions in binary form must reproduce the above copyright notice, this list of conditions +// and the following disclaimer in the documentation and/or other materials provided with the +// distribution. +// +// THIS SOFTWARE IS PROVIDED BY THE FREEBSD PROJECT ``AS IS'' AND ANY EXPRESS OR IMPLIED +// WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND +// FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FREEBSD PROJECT +// OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR +// CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS +// OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED +// AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING +// NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF +// ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + + +#import "CCGLProgram.h" +#import "ccGLStateCache.h" +#import "ccMacros.h" +#import "Support/CCFileUtils.h" +#import "Support/uthash.h" +#import "Support/OpenGL_Internal.h" + +#import "CCDirector.h" + +// extern +#import "kazmath/GL/matrix.h" +#import "kazmath/kazmath.h" + + +typedef struct _hashUniformEntry +{ + GLvoid *value; // value + NSUInteger location; // Key + UT_hash_handle hh; // hash entry +} tHashUniformEntry; + + +#pragma mark Function Pointer Definitions +typedef void (*GLInfoFunction)(GLuint program, + GLenum pname, + GLint* params); +typedef void (*GLLogFunction) (GLuint program, + GLsizei bufsize, + GLsizei* length, + GLchar* infolog); +#pragma mark - +#pragma mark Private Extension Method Declaration + +@interface CCGLProgram() +- (BOOL)compileShader:(GLuint *)shader type:(GLenum)type byteArray:(const GLchar*)byteArray; + +- (NSString *)logForOpenGLObject:(GLuint)object infoCallback:(GLInfoFunction)infoFunc logFunc:(GLLogFunction)logFunc; +@end + +#pragma mark - + +@implementation CCGLProgram + +@synthesize program = _program; + ++ (id)programWithVertexShaderByteArray:(const GLchar*)vShaderByteArray fragmentShaderByteArray:(const GLchar*)fShaderByteArray +{ + return [[[self alloc] initWithVertexShaderByteArray:vShaderByteArray fragmentShaderByteArray:fShaderByteArray] autorelease]; +} + ++ (id)programWithVertexShaderFilename:(NSString *)vShaderFilename fragmentShaderFilename:(NSString *)fShaderFilename +{ + return [[[self alloc] initWithVertexShaderFilename:vShaderFilename fragmentShaderFilename:fShaderFilename] autorelease]; +} + +- (id)initWithVertexShaderByteArray:(const GLchar *)vShaderByteArray fragmentShaderByteArray:(const GLchar *)fShaderByteArray +{ + if ((self = [super init]) ) + { + _program = glCreateProgram(); + + _vertShader = _fragShader = 0; + + if( vShaderByteArray ) { + + if (![self compileShader:&_vertShader + type:GL_VERTEX_SHADER + byteArray:vShaderByteArray] ) + CCLOG(@"cocos2d: ERROR: Failed to compile vertex shader"); + } + + // Create and compile fragment shader + if( fShaderByteArray ) { + if (![self compileShader:&_fragShader + type:GL_FRAGMENT_SHADER + byteArray:fShaderByteArray] ) + + CCLOG(@"cocos2d: ERROR: Failed to compile fragment shader"); + } + + if( _vertShader ) + glAttachShader(_program, _vertShader); + + if( _fragShader ) + glAttachShader(_program, _fragShader); + + _hashForUniforms = NULL; + } + + return self; +} + +- (id)initWithVertexShaderFilename:(NSString *)vShaderFilename fragmentShaderFilename:(NSString *)fShaderFilename +{ + NSString *v = [[CCFileUtils sharedFileUtils] fullPathForFilenameIgnoringResolutions:vShaderFilename]; + NSString *f = [[CCFileUtils sharedFileUtils] fullPathForFilenameIgnoringResolutions:fShaderFilename]; + if( !(v || f) ) { + if(!v) + CCLOGWARN(@"Could not open vertex shader: %@", vShaderFilename); + if(!f) + CCLOGWARN(@"Could not open fragment shader: %@", fShaderFilename); + return nil; + } + const GLchar * vertexSource = (GLchar*) [[NSString stringWithContentsOfFile:v encoding:NSUTF8StringEncoding error:nil] UTF8String]; + const GLchar * fragmentSource = (GLchar*) [[NSString stringWithContentsOfFile:f encoding:NSUTF8StringEncoding error:nil] UTF8String]; + + return [self initWithVertexShaderByteArray:vertexSource fragmentShaderByteArray:fragmentSource]; +} + +- (NSString*) description +{ + return [NSString stringWithFormat:@"<%@ = %p | Program = %i, VertexShader = %i, FragmentShader = %i>", [self class], self, _program, _vertShader, _fragShader]; +} + + +- (BOOL)compileShader:(GLuint *)shader type:(GLenum)type byteArray:(const GLchar *)source +{ + GLint status; + + if (!source) + return NO; + + const GLchar *sources[] = { +#ifdef __CC_PLATFORM_IOS + (type == GL_VERTEX_SHADER ? "precision highp float;\n" : "precision mediump float;\n"), +#endif + "uniform mat4 CC_PMatrix;\n" + "uniform mat4 CC_MVMatrix;\n" + "uniform mat4 CC_MVPMatrix;\n" + "uniform vec4 CC_Time;\n" + "uniform vec4 CC_SinTime;\n" + "uniform vec4 CC_CosTime;\n" + "uniform vec4 CC_Random01;\n" + "//CC INCLUDES END\n\n", + source, + }; + + *shader = glCreateShader(type); + glShaderSource(*shader, sizeof(sources)/sizeof(*sources), sources, NULL); + glCompileShader(*shader); + + glGetShaderiv(*shader, GL_COMPILE_STATUS, &status); + + if( ! status ) { + GLsizei length; + glGetShaderiv(*shader, GL_SHADER_SOURCE_LENGTH, &length); + GLchar src[length]; + + glGetShaderSource(*shader, length, NULL, src); + CCLOG(@"cocos2d: ERROR: Failed to compile shader:\n%s", src); + + if( type == GL_VERTEX_SHADER ) + CCLOG(@"cocos2d: %@", [self vertexShaderLog] ); + else + CCLOG(@"cocos2d: %@", [self fragmentShaderLog] ); + + abort(); + } + return ( status == GL_TRUE ); +} + +#pragma mark - + +- (void)addAttribute:(NSString *)attributeName index:(GLuint)index +{ + glBindAttribLocation(_program, + index, + [attributeName UTF8String]); +} + +-(void) updateUniforms +{ + _uniforms[ kCCUniformPMatrix] = glGetUniformLocation(_program, kCCUniformPMatrix_s); + _uniforms[ kCCUniformMVMatrix] = glGetUniformLocation(_program, kCCUniformMVMatrix_s); + _uniforms[kCCUniformMVPMatrix] = glGetUniformLocation(_program, kCCUniformMVPMatrix_s); + + _uniforms[kCCUniformTime] = glGetUniformLocation(_program, kCCUniformTime_s); + _uniforms[kCCUniformSinTime] = glGetUniformLocation(_program, kCCUniformSinTime_s); + _uniforms[kCCUniformCosTime] = glGetUniformLocation(_program, kCCUniformCosTime_s); + + _uniforms[kCCUniformRandom01] = glGetUniformLocation(_program, kCCUniformRandom01_s); + + _uniforms[kCCUniformSampler] = glGetUniformLocation(_program, kCCUniformSampler_s); + + _flags.usesMVP = _uniforms[kCCUniformMVPMatrix] != -1; + _flags.usesMV = (_uniforms[kCCUniformMVMatrix] != -1 && _uniforms[kCCUniformPMatrix] != -1 ); + _flags.usesTime = ( + _uniforms[kCCUniformTime] != -1 || + _uniforms[kCCUniformSinTime] != -1 || + _uniforms[kCCUniformCosTime] != -1 + ); + _flags.usesRandom = _uniforms[kCCUniformRandom01] != -1; + + + [self use]; + + // Since sample most probably won't change, set it to 0 now. + [self setUniformLocation:_uniforms[kCCUniformSampler] withI1:0]; +} + +#pragma mark - + +-(BOOL) link +{ + NSAssert(_program != 0, @"Cannot link invalid program"); + + GLint status = GL_TRUE; + glLinkProgram(_program); + + if (_vertShader) + glDeleteShader(_vertShader); + + if (_fragShader) + glDeleteShader(_fragShader); + + _vertShader = _fragShader = 0; + +#if DEBUG + glGetProgramiv(_program, GL_LINK_STATUS, &status); + NSString* log = self.programLog; + + if (status == GL_FALSE) { + NSLog(@"cocos2d: ERROR: Failed to link program: %i - %@", _program, log); + ccGLDeleteProgram( _program ); + _program = 0; + } +#endif + + return (status == GL_TRUE); +} + +-(void) use +{ + ccGLUseProgram(_program); +} + +#pragma mark - + +-(NSString *) logForOpenGLObject:(GLuint)object + infoCallback:(GLInfoFunction)infoFunc + logFunc:(GLLogFunction)logFunc +{ + GLint logLength = 0, charsWritten = 0; + + infoFunc(object, GL_INFO_LOG_LENGTH, &logLength); + if (logLength < 1) + return nil; + + char *logBytes = malloc(logLength); + logFunc(object, logLength, &charsWritten, logBytes); + NSString *log = [[[NSString alloc] initWithBytes:logBytes + length:logLength + encoding:NSUTF8StringEncoding] + autorelease]; + free(logBytes); + return log; +} + +- (NSString *)vertexShaderLog +{ + return [self logForOpenGLObject:_vertShader + infoCallback:(GLInfoFunction)&glGetShaderiv + logFunc:(GLLogFunction)&glGetShaderInfoLog]; +} + +- (NSString *)fragmentShaderLog +{ + return [self logForOpenGLObject:_fragShader + infoCallback:(GLInfoFunction)&glGetShaderiv + logFunc:(GLLogFunction)&glGetShaderInfoLog]; +} + +- (NSString *)programLog +{ + return [self logForOpenGLObject:_program + infoCallback:(GLInfoFunction)&glGetProgramiv + logFunc:(GLLogFunction)&glGetProgramInfoLog]; +} + +#pragma mark - Uniform cache + +-(BOOL) updateUniformLocation:(GLint)location withData:(GLvoid*)data sizeOfData:(NSUInteger)bytes +{ + if(location < 0) + return FALSE; + + BOOL updated = YES; + tHashUniformEntry *element = NULL; + HASH_FIND_INT(_hashForUniforms, &location, element); + + if( ! element ) { + + element = malloc( sizeof(*element) ); + + // key + element->location = location; + + // value + element->value = malloc( bytes ); + memcpy(element->value, data, bytes ); + + HASH_ADD_INT(_hashForUniforms, location, element); + } + else + { + if( memcmp( element->value, data, bytes) == 0 ) + updated = NO; + else + memcpy( element->value, data, bytes ); + } + + return updated; +} + +- (GLint)uniformLocationForName:(NSString*)name +{ + NSAssert(name != nil, @"Invalid uniform name" ); + NSAssert(_program != 0, @"Invalid operation. Cannot get uniform location when program is not initialized"); + + return glGetUniformLocation(_program, [name UTF8String]); +} + +-(void) setUniformLocation:(GLint)location withI1:(GLint)i1 +{ + BOOL updated = [self updateUniformLocation:location withData:&i1 sizeOfData:sizeof(i1)*1]; + + if( updated ) + glUniform1i( (GLint)location, i1); +} + +-(void) setUniformLocation:(GLint)location withF1:(GLfloat)f1 +{ + BOOL updated = [self updateUniformLocation:location withData:&f1 sizeOfData:sizeof(f1)*1]; + + if( updated ) + glUniform1f( (GLint)location, f1); +} + +-(void) setUniformLocation:(GLint)location withF1:(GLfloat)f1 f2:(GLfloat)f2 +{ + GLfloat floats[2] = {f1,f2}; + BOOL updated = [self updateUniformLocation:location withData:floats sizeOfData:sizeof(floats)]; + + if( updated ) + glUniform2f( (GLint)location, f1, f2); +} + +-(void) setUniformLocation:(GLint)location withF1:(GLfloat)f1 f2:(GLfloat)f2 f3:(GLfloat)f3 +{ + GLfloat floats[3] = {f1,f2,f3}; + BOOL updated = [self updateUniformLocation:location withData:floats sizeOfData:sizeof(floats)]; + + if( updated ) + glUniform3f( (GLint)location, f1, f2, f3); +} + +-(void) setUniformLocation:(GLint)location withF1:(GLfloat)f1 f2:(GLfloat)f2 f3:(GLfloat)f3 f4:(GLfloat)f4 +{ + GLfloat floats[4] = {f1,f2,f3,f4}; + BOOL updated = [self updateUniformLocation:location withData:floats sizeOfData:sizeof(floats)]; + + if( updated ) + glUniform4f( (GLint)location, f1, f2, f3,f4); +} + +-(void) setUniformLocation:(GLint)location with2fv:(GLfloat*)floats count:(NSUInteger)numberOfArrays +{ + BOOL updated = [self updateUniformLocation:location withData:floats sizeOfData:sizeof(float)*2*numberOfArrays]; + + if( updated ) + glUniform2fv( (GLint)location, (GLsizei)numberOfArrays, floats ); +} + +-(void) setUniformLocation:(GLint)location with3fv:(GLfloat*)floats count:(NSUInteger)numberOfArrays +{ + BOOL updated = [self updateUniformLocation:location withData:floats sizeOfData:sizeof(float)*3*numberOfArrays]; + + if( updated ) + glUniform3fv( (GLint)location, (GLsizei)numberOfArrays, floats ); +} + +-(void) setUniformLocation:(GLint)location with4fv:(GLvoid*)floats count:(NSUInteger)numberOfArrays +{ + BOOL updated = [self updateUniformLocation:location withData:floats sizeOfData:sizeof(float)*4*numberOfArrays]; + + if( updated ) + glUniform4fv( (GLint)location, (GLsizei)numberOfArrays, floats ); +} + + +-(void) setUniformLocation:(GLint)location withMatrix4fv:(GLvoid*)matrixArray count:(NSUInteger)numberOfMatrices +{ + BOOL updated = [self updateUniformLocation:location withData:matrixArray sizeOfData:sizeof(float)*16*numberOfMatrices]; + + if( updated ) + glUniformMatrix4fv( (GLint)location, (GLsizei)numberOfMatrices, GL_FALSE, matrixArray); +} + +-(void) setUniformsForBuiltins +{ + kmMat4 matrixP; + kmMat4 matrixMV; + + kmGLGetMatrix(KM_GL_PROJECTION, &matrixP ); + kmGLGetMatrix(KM_GL_MODELVIEW, &matrixMV ); + + if( _flags.usesMVP) { + kmMat4 matrixMVP; + kmMat4Multiply(&matrixMVP, &matrixP, &matrixMV); + [self setUniformLocation:_uniforms[kCCUniformMVPMatrix] withMatrix4fv:matrixMVP.mat count:1]; + } + + if( _flags.usesMV) { + [self setUniformLocation:_uniforms[ kCCUniformPMatrix] withMatrix4fv: matrixP.mat count:1]; + [self setUniformLocation:_uniforms[ kCCUniformMVMatrix] withMatrix4fv: matrixMV.mat count:1]; + } + + if(_flags.usesTime){ + CCDirector *director = [CCDirector sharedDirector]; + // This doesn't give the most accurate global time value. + // Cocos2D doesn't store a high precision time value, so this will have to do. + // Getting Mach time per frame per shader using time could be extremely expensive. + ccTime time = director.totalFrames*director.animationInterval; + + [self setUniformLocation:_uniforms[kCCUniformTime] withF1:time/10.0 f2:time f3:time*2 f4:time*4]; + [self setUniformLocation:_uniforms[kCCUniformSinTime] withF1:sinf(time/8.0) f2:sinf(time/4.0) f3:sinf(time/2.0) f4:sinf(time)]; + [self setUniformLocation:_uniforms[kCCUniformCosTime] withF1:cosf(time/8.0) f2:cosf(time/4.0) f3:cosf(time/2.0) f4:cosf(time)]; + } + + if(_flags.usesRandom) + [self setUniformLocation:_uniforms[kCCUniformRandom01] withF1:CCRANDOM_0_1() f2:CCRANDOM_0_1() f3:CCRANDOM_0_1() f4:CCRANDOM_0_1()]; +} + +-(void)setUniformForModelViewProjectionMatrix; +{ + [self setUniformsForBuiltins]; +} + + +#pragma mark - + +- (void)dealloc +{ + CCLOGINFO( @"cocos2d: deallocing %@", self); + + // there is no need to delete the shaders. They should have been already deleted. + NSAssert( _vertShader == 0, @"Vertex Shaders should have been already deleted"); + NSAssert( _fragShader == 0, @"Fragment Shaders should have been already deleted"); + + if (_program) + ccGLDeleteProgram(_program); + + tHashUniformEntry *current_element, *tmp; + + // Purge uniform hash + HASH_ITER(hh, _hashForUniforms, current_element, tmp) { + HASH_DEL(_hashForUniforms, current_element); + free(current_element->value); + free(current_element); + } + + [super dealloc]; +} +@end diff --git "a/21451198\345\215\242\350\266\205/project5/MyPlane/libs/cocos2d/CCGrabber.h" "b/21451198\345\215\242\350\266\205/project5/MyPlane/libs/cocos2d/CCGrabber.h" new file mode 100644 index 00000000..06bb210f --- /dev/null +++ "b/21451198\345\215\242\350\266\205/project5/MyPlane/libs/cocos2d/CCGrabber.h" @@ -0,0 +1,44 @@ +/* + * cocos2d for iPhone: http://www.cocos2d-iphone.org + * + * Copyright (c) 2009 On-Core + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + * THE SOFTWARE. + * + */ + + +#import "Platforms/CCGL.h" +#import + +@class CCTexture2D; + +/** FBO class that grabs the the contents of the screen */ +@interface CCGrabber : NSObject +{ + GLuint _FBO; + GLint _oldFBO; + GLfloat oldClearColor_[4]; +} + +-(void)grab:(CCTexture2D*)texture; +-(void)beforeRender:(CCTexture2D*)texture; +-(void)afterRender:(CCTexture2D*)texture; + +@end diff --git "a/21451198\345\215\242\350\266\205/project5/MyPlane/libs/cocos2d/CCGrabber.m" "b/21451198\345\215\242\350\266\205/project5/MyPlane/libs/cocos2d/CCGrabber.m" new file mode 100644 index 00000000..bee9c066 --- /dev/null +++ "b/21451198\345\215\242\350\266\205/project5/MyPlane/libs/cocos2d/CCGrabber.m" @@ -0,0 +1,99 @@ +/* + * cocos2d for iPhone: http://www.cocos2d-iphone.org + * + * Copyright (c) 2009 On-Core + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + * THE SOFTWARE. + * + */ + + +#import "Platforms/CCGL.h" +#import "CCGrabber.h" +#import "ccMacros.h" +#import "CCTexture2D.h" +#import "Support/OpenGL_Internal.h" + +@implementation CCGrabber + +-(id) init +{ + if(( self = [super init] )) { + // generate FBO + glGenFramebuffers(1, &_FBO); + } + return self; +} + +-(void)grab:(CCTexture2D*)texture +{ + glGetIntegerv(GL_FRAMEBUFFER_BINDING, &_oldFBO); + + // bind + glBindFramebuffer(GL_FRAMEBUFFER, _FBO); + + // associate texture with FBO + glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, texture.name, 0); + + // check if it worked (probably worth doing :) ) + GLuint status = glCheckFramebufferStatus(GL_FRAMEBUFFER); + if (status != GL_FRAMEBUFFER_COMPLETE) + [NSException raise:@"Frame Grabber" format:@"Could not attach texture to framebuffer"]; + + glBindFramebuffer(GL_FRAMEBUFFER, _oldFBO); +} + +-(void)beforeRender:(CCTexture2D*)texture +{ + glGetIntegerv(GL_FRAMEBUFFER_BINDING, &_oldFBO); + glBindFramebuffer(GL_FRAMEBUFFER, _FBO); + + // save clear color + glGetFloatv(GL_COLOR_CLEAR_VALUE,oldClearColor_); + + // BUG XXX: doesn't work with RGB565. + glClearColor(0,0,0,0); + + // BUG #631: To fix #631, uncomment the lines with #631 + // Warning: But it CCGrabber won't work with 2 effects at the same time +// glClearColor(0.0f,0.0f,0.0f,1.0f); // #631 + + glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); + +// glColorMask(TRUE, TRUE, TRUE, FALSE); // #631 + +} + +-(void)afterRender:(CCTexture2D*)texture +{ + glBindFramebuffer(GL_FRAMEBUFFER, _oldFBO); +// glColorMask(TRUE, TRUE, TRUE, TRUE); // #631 + + // Restore clear color + glClearColor( oldClearColor_[0], oldClearColor_[1], oldClearColor_[2], oldClearColor_[3] ); +} + +- (void) dealloc +{ + CCLOGINFO(@"cocos2d: deallocing %@", self); + glDeleteFramebuffers(1, &_FBO); + [super dealloc]; +} + +@end diff --git "a/21451198\345\215\242\350\266\205/project5/MyPlane/libs/cocos2d/CCGrid.h" "b/21451198\345\215\242\350\266\205/project5/MyPlane/libs/cocos2d/CCGrid.h" new file mode 100644 index 00000000..21886a5d --- /dev/null +++ "b/21451198\345\215\242\350\266\205/project5/MyPlane/libs/cocos2d/CCGrid.h" @@ -0,0 +1,130 @@ +/* + * cocos2d for iPhone: http://www.cocos2d-iphone.org + * + * Copyright (c) 2009 On-Core + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + * THE SOFTWARE. + * + */ + + +#import + +#import "CCNode.h" +#import "CCCamera.h" +#import "ccTypes.h" +#import "CCDirector.h" +#import "kazmath/mat4.h" + +@class CCTexture2D; +@class CCGrabber; +@class CCGLProgram; + +/** Base class for other + */ +@interface CCGridBase : NSObject +{ + BOOL _active; + int _reuseGrid; + CGSize _gridSize; + CCTexture2D *_texture; + CGPoint _step; + CCGrabber *_grabber; + BOOL _isTextureFlipped; + + CCGLProgram *_shaderProgram; + + ccDirectorProjection _directorProjection; +} + +/** whether or not the grid is active */ +@property (nonatomic,readwrite) BOOL active; +/** number of times that the grid will be reused */ +@property (nonatomic,readwrite) int reuseGrid; +/** size of the grid */ +@property (nonatomic,readonly) CGSize gridSize; +/** pixels between the grids */ +@property (nonatomic,readwrite) CGPoint step; +/** texture used */ +@property (nonatomic, retain) CCTexture2D *texture; +/** grabber used */ +@property (nonatomic, retain) CCGrabber *grabber; +/** is texture flipped */ +@property (nonatomic, readwrite) BOOL isTextureFlipped; +/** shader program */ +@property (nonatomic, readwrite, assign) CCGLProgram *shaderProgram; + ++(id) gridWithSize:(CGSize)gridSize texture:(CCTexture2D*)texture flippedTexture:(BOOL)flipped; ++(id) gridWithSize:(CGSize)gridSize; + +-(id) initWithSize:(CGSize)gridSize texture:(CCTexture2D*)texture flippedTexture:(BOOL)flipped; +-(id)initWithSize:(CGSize)gridSize; +-(void)beforeDraw; +-(void)afterDraw:(CCNode*)target; +-(void)blit; +-(void)reuse; + +-(void)calculateVertexPoints; + +@end + +//////////////////////////////////////////////////////////// + +/** + CCGrid3D is a 3D grid implementation. Each vertex has 3 dimensions: x,y,z + */ +@interface CCGrid3D : CCGridBase +{ + GLvoid *_texCoordinates; + GLvoid *_vertices; + GLvoid *_originalVertices; + GLushort *_indices; +} + +/** returns the vertex at a given position */ +-(ccVertex3F)vertex:(CGPoint)pos; +/** returns the original (non-transformed) vertex at a given position */ +-(ccVertex3F)originalVertex:(CGPoint)pos; +/** sets a new vertex at a given position */ +-(void)setVertex:(CGPoint)pos vertex:(ccVertex3F)vertex; + +@end + +//////////////////////////////////////////////////////////// + +/** + CCTiledGrid3D is a 3D grid implementation. It differs from Grid3D in that + the tiles can be separated from the grid. +*/ +@interface CCTiledGrid3D : CCGridBase +{ + GLvoid *_texCoordinates; + GLvoid *_vertices; + GLvoid *_originalVertices; + GLushort *_indices; +} + +/** returns the tile at the given position */ +-(ccQuad3)tile:(CGPoint)pos; +/** returns the original tile (untransformed) at the given position */ +-(ccQuad3)originalTile:(CGPoint)pos; +/** sets a new tile */ +-(void)setTile:(CGPoint)pos coords:(ccQuad3)coords; + +@end diff --git "a/21451198\345\215\242\350\266\205/project5/MyPlane/libs/cocos2d/CCGrid.m" "b/21451198\345\215\242\350\266\205/project5/MyPlane/libs/cocos2d/CCGrid.m" new file mode 100644 index 00000000..b9f6eb19 --- /dev/null +++ "b/21451198\345\215\242\350\266\205/project5/MyPlane/libs/cocos2d/CCGrid.m" @@ -0,0 +1,584 @@ +/* + * cocos2d for iPhone: http://www.cocos2d-iphone.org + * + * Copyright (c) 2009 On-Core + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + * THE SOFTWARE. + * + */ + + +#import "ccMacros.h" +#import "CCGrid.h" +#import "CCTexture2D.h" +#import "CCDirector.h" +#import "CCGrabber.h" +#import "CCGLProgram.h" +#import "CCShaderCache.h" +#import "ccGLStateCache.h" + +#import "Platforms/CCGL.h" +#import "Support/CGPointExtension.h" +#import "Support/ccUtils.h" +#import "Support/TransformUtils.h" +#import "Support/OpenGL_Internal.h" + +#import "kazmath/kazmath.h" +#import "kazmath/GL/matrix.h" + +#ifdef __CC_PLATFORM_IOS +#import "Platforms/iOS/CCDirectorIOS.h" +#endif // __CC_PLATFORM_IOS + +#pragma mark - +#pragma mark CCGridBase + +@implementation CCGridBase + +@synthesize reuseGrid = _reuseGrid; +@synthesize texture = _texture; +@synthesize grabber = _grabber; +@synthesize gridSize = _gridSize; +@synthesize step = _step; +@synthesize shaderProgram = _shaderProgram; + ++(id) gridWithSize:(CGSize)gridSize texture:(CCTexture2D*)texture flippedTexture:(BOOL)flipped +{ + return [[[self alloc] initWithSize:gridSize texture:texture flippedTexture:flipped] autorelease]; +} + ++(id) gridWithSize:(CGSize)gridSize +{ + return [[(CCGridBase*)[self alloc] initWithSize:gridSize] autorelease]; +} + +-(id) initWithSize:(CGSize)gridSize texture:(CCTexture2D*)texture flippedTexture:(BOOL)flipped +{ + if( (self=[super init]) ) { + + _active = NO; + _reuseGrid = 0; + _gridSize = gridSize; + + self.texture = texture; + _isTextureFlipped = flipped; + + CGSize texSize = [_texture contentSize]; + _step.x = texSize.width / _gridSize.width; + _step.y = texSize.height / _gridSize.height; + + _grabber = [[CCGrabber alloc] init]; + [_grabber grab:_texture]; + + self.shaderProgram = [[CCShaderCache sharedShaderCache] programForKey:kCCShader_PositionTexture]; + + [self calculateVertexPoints]; + } + return self; +} + +-(id)initWithSize:(CGSize)gSize +{ + CCDirector *director = [CCDirector sharedDirector]; + CGSize s = [director winSizeInPixels]; + + + unsigned long POTWide = ccNextPOT(s.width); + unsigned long POTHigh = ccNextPOT(s.height); + +#ifdef __CC_PLATFORM_IOS + CCGLView *glview = (CCGLView*)[[CCDirector sharedDirector] view]; + NSString *pixelFormat = [glview pixelFormat]; + + CCTexture2DPixelFormat format = [pixelFormat isEqualToString: kEAGLColorFormatRGB565] ? kCCTexture2DPixelFormat_RGB565 : kCCTexture2DPixelFormat_RGBA8888; +#elif defined(__CC_PLATFORM_MAC) + CCTexture2DPixelFormat format = kCCTexture2DPixelFormat_RGBA8888; +#endif + + int bpp = ( format == kCCTexture2DPixelFormat_RGB565 ? 2 : 4 ); + + void *data = calloc((size_t)(POTWide * POTHigh * bpp), 1); + if( ! data ) { + CCLOG(@"cocos2d: CCGrid: not enough memory"); + [self release]; + return nil; + } + + CCTexture2D *texture = [[CCTexture2D alloc] initWithData:data pixelFormat:format pixelsWide:POTWide pixelsHigh:POTHigh contentSize:s]; + free( data ); + + if( ! texture ) { + CCLOG(@"cocos2d: CCGrid: error creating texture"); + [self release]; + return nil; + } + + self = [self initWithSize:gSize texture:texture flippedTexture:NO]; + + [texture release]; + + return self; +} +- (NSString*) description +{ + return [NSString stringWithFormat:@"<%@ = %p | Dimensions = %ldx%ld>", [self class], self, (long)_gridSize.width, (long)_gridSize.height]; +} + +- (void) dealloc +{ + CCLOGINFO(@"cocos2d: deallocing %@", self); + +// [self setActive: NO]; + + [_texture release]; + [_grabber release]; + [super dealloc]; +} + +// properties +-(BOOL) active +{ + return _active; +} + +-(void) setActive:(BOOL)active +{ + _active = active; + if( ! active ) { + CCDirector *director = [CCDirector sharedDirector]; + ccDirectorProjection proj = [director projection]; + [director setProjection:proj]; + } +} + +-(BOOL) isTextureFlipped +{ + return _isTextureFlipped; +} + +-(void) setIsTextureFlipped:(BOOL)flipped +{ + if( _isTextureFlipped != flipped ) { + _isTextureFlipped = flipped; + [self calculateVertexPoints]; + } +} + +-(void)set2DProjection +{ + CCDirector *director = [CCDirector sharedDirector]; + + CGSize size = [director winSizeInPixels]; + + glViewport(0, 0, size.width, size.height); + kmGLMatrixMode(KM_GL_PROJECTION); + kmGLLoadIdentity(); + + kmMat4 orthoMatrix; + kmMat4OrthographicProjection(&orthoMatrix, 0, size.width, 0, size.height, -1, 1); + kmGLMultMatrix( &orthoMatrix ); + + kmGLMatrixMode(KM_GL_MODELVIEW); + kmGLLoadIdentity(); + + + ccSetProjectionMatrixDirty(); +} + +-(void)beforeDraw +{ + // save projection + CCDirector *director = [CCDirector sharedDirector]; + _directorProjection = [director projection]; + + // 2d projection +// [director setProjection:kCCDirectorProjection2D]; + [self set2DProjection]; + + + [_grabber beforeRender:_texture]; +} + + +-(void)afterDraw:(CCNode *)target +{ + [_grabber afterRender:_texture]; + + // restore projection + CCDirector *director = [CCDirector sharedDirector]; + [director setProjection: _directorProjection]; + + if( target.camera.dirty ) { + + CGPoint offset = [target anchorPointInPoints]; + + // + // XXX: Camera should be applied in the AnchorPoint + // + kmGLTranslatef(offset.x, offset.y, 0); + [target.camera locate]; + kmGLTranslatef(-offset.x, -offset.y, 0); + } + + ccGLBindTexture2D( _texture.name ); + + [self blit]; +} + + +-(void)blit +{ + [NSException raise:@"GridBase" format:@"Abstract class needs implementation"]; +} + +-(void)reuse +{ + [NSException raise:@"GridBase" format:@"Abstract class needs implementation"]; +} + +-(void)calculateVertexPoints +{ + [NSException raise:@"GridBase" format:@"Abstract class needs implementation"]; +} + +@end + +//////////////////////////////////////////////////////////// + +#pragma mark - +#pragma mark CCGrid3D +@implementation CCGrid3D + +-(void)dealloc +{ + free(_texCoordinates); + free(_vertices); + free(_indices); + free(_originalVertices); + [super dealloc]; +} + +-(void)blit +{ + NSInteger n = _gridSize.width * _gridSize.height; + + ccGLEnableVertexAttribs( kCCVertexAttribFlag_Position | kCCVertexAttribFlag_TexCoords ); + [_shaderProgram use]; + [_shaderProgram setUniformsForBuiltins]; + + // + // Attributes + // + + // position + glVertexAttribPointer(kCCVertexAttrib_Position, 3, GL_FLOAT, GL_FALSE, 0, _vertices); + + // texCoods + glVertexAttribPointer(kCCVertexAttrib_TexCoords, 2, GL_FLOAT, GL_FALSE, 0, _texCoordinates); + + glDrawElements(GL_TRIANGLES, (GLsizei) n*6, GL_UNSIGNED_SHORT, _indices); + + CC_INCREMENT_GL_DRAWS(1); +} + +-(void)calculateVertexPoints +{ + float width = (float)_texture.pixelsWide; + float height = (float)_texture.pixelsHigh; + float imageH = _texture.contentSizeInPixels.height; + + int x, y, i; + + if (_vertices) free(_vertices); + if (_originalVertices) free(_originalVertices); + if (_texCoordinates) free(_texCoordinates); + if (_indices) free(_indices); + + NSUInteger numOfPoints = (_gridSize.width+1) * (_gridSize.height+1); + + _vertices = malloc(numOfPoints * sizeof(ccVertex3F)); + _originalVertices = malloc(numOfPoints * sizeof(ccVertex3F)); + _texCoordinates = malloc(numOfPoints * sizeof(ccVertex2F)); + _indices = malloc( (_gridSize.width * _gridSize.height) * sizeof(GLushort)*6); + + GLfloat *vertArray = (GLfloat*)_vertices; + GLfloat *texArray = (GLfloat*)_texCoordinates; + GLushort *idxArray = (GLushort *)_indices; + + for( x = 0; x < _gridSize.width; x++ ) + { + for( y = 0; y < _gridSize.height; y++ ) + { + NSInteger idx = (y * _gridSize.width) + x; + + GLfloat x1 = x * _step.x; + GLfloat x2 = x1 + _step.x; + GLfloat y1 = y * _step.y; + GLfloat y2 = y1 + _step.y; + + GLushort a = x * (_gridSize.height+1) + y; + GLushort b = (x+1) * (_gridSize.height+1) + y; + GLushort c = (x+1) * (_gridSize.height+1) + (y+1); + GLushort d = x * (_gridSize.height+1) + (y+1); + + GLushort tempidx[6] = { a, b, d, b, c, d }; + + memcpy(&idxArray[6*idx], tempidx, 6*sizeof(GLushort)); + + int l1[4] = { a*3, b*3, c*3, d*3 }; + ccVertex3F e = {x1,y1,0}; + ccVertex3F f = {x2,y1,0}; + ccVertex3F g = {x2,y2,0}; + ccVertex3F h = {x1,y2,0}; + + ccVertex3F l2[4] = { e, f, g, h }; + + int tex1[4] = { a*2, b*2, c*2, d*2 }; + CGPoint tex2[4] = { ccp(x1, y1), ccp(x2, y1), ccp(x2, y2), ccp(x1, y2) }; + + for( i = 0; i < 4; i++ ) + { + vertArray[ l1[i] ] = l2[i].x; + vertArray[ l1[i] + 1 ] = l2[i].y; + vertArray[ l1[i] + 2 ] = l2[i].z; + + texArray[ tex1[i] ] = tex2[i].x / width; + if( _isTextureFlipped ) + texArray[ tex1[i] + 1 ] = (imageH - tex2[i].y) / height; + else + texArray[ tex1[i] + 1 ] = tex2[i].y / height; + } + } + } + + memcpy(_originalVertices, _vertices, (_gridSize.width+1)*(_gridSize.height+1)*sizeof(ccVertex3F)); +} + +-(ccVertex3F)vertex:(CGPoint)pos +{ + NSAssert( pos.x == (NSUInteger)pos.x && pos.y == (NSUInteger) pos.y , @"Numbers must be integers"); + + NSInteger index = (pos.x * (_gridSize.height+1) + pos.y) * 3; + float *vertArray = (float *)_vertices; + + ccVertex3F vert = { vertArray[index], vertArray[index+1], vertArray[index+2] }; + + return vert; +} + +-(ccVertex3F)originalVertex:(CGPoint)pos +{ + NSAssert( pos.x == (NSUInteger)pos.x && pos.y == (NSUInteger) pos.y , @"Numbers must be integers"); + + NSInteger index = (pos.x * (_gridSize.height+1) + pos.y) * 3; + float *vertArray = (float *)_originalVertices; + + ccVertex3F vert = { vertArray[index], vertArray[index+1], vertArray[index+2] }; + + return vert; +} + +-(void)setVertex:(CGPoint)pos vertex:(ccVertex3F)vertex +{ + NSAssert( pos.x == (NSUInteger)pos.x && pos.y == (NSUInteger) pos.y , @"Numbers must be integers"); + + NSInteger index = (pos.x * (_gridSize.height+1) + pos.y) * 3; + float *vertArray = (float *)_vertices; + vertArray[index] = vertex.x; + vertArray[index+1] = vertex.y; + vertArray[index+2] = vertex.z; +} + +-(void)reuse +{ + if ( _reuseGrid > 0 ) + { + memcpy(_originalVertices, _vertices, (_gridSize.width+1)*(_gridSize.height+1)*sizeof(ccVertex3F)); + _reuseGrid--; + } +} + +@end + +//////////////////////////////////////////////////////////// + +#pragma mark - +#pragma mark CCTiledGrid3D + +@implementation CCTiledGrid3D + +-(void)dealloc +{ + free(_texCoordinates); + free(_vertices); + free(_indices); + free(_originalVertices); + [super dealloc]; +} + +-(void)blit +{ + NSInteger n = _gridSize.width * _gridSize.height; + + [_shaderProgram use]; + [_shaderProgram setUniformsForBuiltins]; + + + // + // Attributes + // + ccGLEnableVertexAttribs( kCCVertexAttribFlag_Position | kCCVertexAttribFlag_TexCoords ); + + // position + glVertexAttribPointer(kCCVertexAttrib_Position, 3, GL_FLOAT, GL_FALSE, 0, _vertices); + + // texCoods + glVertexAttribPointer(kCCVertexAttrib_TexCoords, 2, GL_FLOAT, GL_FALSE, 0, _texCoordinates); + + glDrawElements(GL_TRIANGLES, (GLsizei) n*6, GL_UNSIGNED_SHORT, _indices); + + CC_INCREMENT_GL_DRAWS(1); +} + +-(void)calculateVertexPoints +{ + float width = (float)_texture.pixelsWide; + float height = (float)_texture.pixelsHigh; + float imageH = _texture.contentSizeInPixels.height; + + NSInteger numQuads = _gridSize.width * _gridSize.height; + + if (_vertices) free(_vertices); + if (_originalVertices) free(_originalVertices); + if (_texCoordinates) free(_texCoordinates); + if (_indices) free(_indices); + + _vertices = malloc(numQuads*4*sizeof(ccVertex3F)); + _originalVertices = malloc(numQuads*4*sizeof(ccVertex3F)); + _texCoordinates = malloc(numQuads*4*sizeof(ccVertex2F)); + _indices = malloc(numQuads*6*sizeof(GLushort)); + + GLfloat *vertArray = (GLfloat*)_vertices; + GLfloat *texArray = (GLfloat*)_texCoordinates; + GLushort *idxArray = (GLushort *)_indices; + + int x, y; + + for( x = 0; x < _gridSize.width; x++ ) + { + for( y = 0; y < _gridSize.height; y++ ) + { + float x1 = x * _step.x; + float x2 = x1 + _step.x; + float y1 = y * _step.y; + float y2 = y1 + _step.y; + + *vertArray++ = x1; + *vertArray++ = y1; + *vertArray++ = 0; + *vertArray++ = x2; + *vertArray++ = y1; + *vertArray++ = 0; + *vertArray++ = x1; + *vertArray++ = y2; + *vertArray++ = 0; + *vertArray++ = x2; + *vertArray++ = y2; + *vertArray++ = 0; + + float newY1 = y1; + float newY2 = y2; + + if( _isTextureFlipped ) { + newY1 = imageH - y1; + newY2 = imageH - y2; + } + + *texArray++ = x1 / width; + *texArray++ = newY1 / height; + *texArray++ = x2 / width; + *texArray++ = newY1 / height; + *texArray++ = x1 / width; + *texArray++ = newY2 / height; + *texArray++ = x2 / width; + *texArray++ = newY2 / height; + } + } + + for( x = 0; x < numQuads; x++) + { + idxArray[x*6+0] = x*4+0; + idxArray[x*6+1] = x*4+1; + idxArray[x*6+2] = x*4+2; + + idxArray[x*6+3] = x*4+1; + idxArray[x*6+4] = x*4+2; + idxArray[x*6+5] = x*4+3; + } + + memcpy(_originalVertices, _vertices, numQuads*12*sizeof(GLfloat)); +} + +-(void)setTile:(CGPoint)pos coords:(ccQuad3)coords +{ + NSAssert( pos.x == (NSUInteger)pos.x && pos.y == (NSUInteger) pos.y , @"Numbers must be integers"); + + NSInteger idx = (_gridSize.height * pos.x + pos.y) * 4 * 3; + float *vertArray = (float*)_vertices; + memcpy(&vertArray[idx], &coords, sizeof(ccQuad3)); +} + +-(ccQuad3)originalTile:(CGPoint)pos +{ + NSAssert( pos.x == (NSUInteger)pos.x && pos.y == (NSUInteger) pos.y , @"Numbers must be integers"); + + NSInteger idx = (_gridSize.height * pos.x + pos.y) * 4 * 3; + float *vertArray = (float*)_originalVertices; + + ccQuad3 ret; + memcpy(&ret, &vertArray[idx], sizeof(ccQuad3)); + + return ret; +} + +-(ccQuad3)tile:(CGPoint)pos +{ + NSAssert( pos.x == (NSUInteger)pos.x && pos.y == (NSUInteger) pos.y , @"Numbers must be integers"); + + NSInteger idx = (_gridSize.height * pos.x + pos.y) * 4 * 3; + float *vertArray = (float*)_vertices; + + ccQuad3 ret; + memcpy(&ret, &vertArray[idx], sizeof(ccQuad3)); + + return ret; +} + +-(void)reuse +{ + if ( _reuseGrid > 0 ) + { + NSInteger numQuads = _gridSize.width * _gridSize.height; + + memcpy(_originalVertices, _vertices, numQuads*12*sizeof(GLfloat)); + _reuseGrid--; + } +} + +@end diff --git "a/21451198\345\215\242\350\266\205/project5/MyPlane/libs/cocos2d/CCLabelAtlas.h" "b/21451198\345\215\242\350\266\205/project5/MyPlane/libs/cocos2d/CCLabelAtlas.h" new file mode 100644 index 00000000..369c1e91 --- /dev/null +++ "b/21451198\345\215\242\350\266\205/project5/MyPlane/libs/cocos2d/CCLabelAtlas.h" @@ -0,0 +1,71 @@ +/* + * cocos2d for iPhone: http://www.cocos2d-iphone.org + * + * Copyright (c) 2008-2010 Ricardo Quesada + * Copyright (c) 2011 Zynga Inc. + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + * THE SOFTWARE. + * + */ + + +#import "CCAtlasNode.h" +#import "CCTextureAtlas.h" + +/** CCLabelAtlas is a subclass of CCAtlasNode. + + It can be as a replacement of CCLabel since it is MUCH faster. + + CCLabelAtlas versus CCLabel: + - CCLabelAtlas is MUCH faster than CCLabel + - CCLabelAtlas "characters" have a fixed height and width + - CCLabelAtlas "characters" can be anything you want since they are taken from an image file + + A more flexible class is CCLabelBMFont. It supports variable width characters and it also has a nice editor. + */ +@interface CCLabelAtlas : CCAtlasNode +{ + // string to render + NSString *_string; + + // the first char in the charmap + NSUInteger _mapStartChar; +} + + +/** creates the CCLabelAtlas with a string, a char map file(the atlas), the width and height of each element in points and the starting char of the atlas */ ++(id) labelWithString:(NSString*) string charMapFile: (NSString*) charmapfile itemWidth:(NSUInteger)w itemHeight:(NSUInteger)h startCharMap:(NSUInteger)firstElement; + +/** creates the CCLabelAtlas with a string and a configuration file + @since v2.0 + */ ++(id) labelWithString:(NSString*) string fntFile:(NSString*)fontFile; + +/** initializes the CCLabelAtlas with a string, a char map file(the atlas), the width and height in points of each element and the starting char of the atlas */ +-(id) initWithString:(NSString*) string charMapFile: (NSString*) charmapfile itemWidth:(NSUInteger)w itemHeight:(NSUInteger)h startCharMap:(NSUInteger)firstElement; + +/** initializes the CCLabelAtlas with a string, a texture, the width and height in points of each element and the starting char of the atlas */ +-(id) initWithString:(NSString*) theString texture:(CCTexture2D*)texture itemWidth:(NSUInteger)w itemHeight:(NSUInteger)h startCharMap:(NSUInteger)c; + +/** initializes the CCLabelAtlas with a string and a configuration file + @since v2.0 + */ +-(id) initWithString:(NSString*) string fntFile:(NSString*)fontFile; + +@end diff --git "a/21451198\345\215\242\350\266\205/project5/MyPlane/libs/cocos2d/CCLabelAtlas.m" "b/21451198\345\215\242\350\266\205/project5/MyPlane/libs/cocos2d/CCLabelAtlas.m" new file mode 100644 index 00000000..49150426 --- /dev/null +++ "b/21451198\345\215\242\350\266\205/project5/MyPlane/libs/cocos2d/CCLabelAtlas.m" @@ -0,0 +1,214 @@ +/* + * cocos2d for iPhone: http://www.cocos2d-iphone.org + * + * Copyright (c) 2008-2011 Ricardo Quesada + * Copyright (c) 2011 Zynga Inc. + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + * THE SOFTWARE. + * + */ + + +#import "ccConfig.h" +#import "ccMacros.h" +#import "CCDrawingPrimitives.h" +#import "CCLabelAtlas.h" +#import "CCShaderCache.h" +#import "CCGLProgram.h" +#import "ccGLStateCache.h" +#import "CCTextureCache.h" +#import "CCDirector.h" +#import "Support/CGPointExtension.h" +#import "Support/TransformUtils.h" +#import "Support/CCFileUtils.h" + +// external +#import "kazmath/GL/matrix.h" + +@implementation CCLabelAtlas + +#pragma mark CCLabelAtlas - Creation & Init ++(id) labelWithString:(NSString*)string charMapFile:(NSString*)charmapfile itemWidth:(NSUInteger)w itemHeight:(NSUInteger)h startCharMap:(NSUInteger)c +{ + return [[[self alloc] initWithString:string charMapFile:charmapfile itemWidth:w itemHeight:h startCharMap:c] autorelease]; +} + ++(id) labelWithString:(NSString*)string fntFile:(NSString*)fntFile +{ + return [[[self alloc] initWithString:string fntFile:fntFile] autorelease]; +} + +-(id) initWithString:(NSString*) theString fntFile:(NSString*)fntFile +{ + NSDictionary *dict = [NSDictionary dictionaryWithContentsOfFile:[[CCFileUtils sharedFileUtils] fullPathForFilename:fntFile]]; + + NSAssert( [[dict objectForKey:@"version"] intValue] == 1, @"Unsupported version. Upgrade cocos2d version"); + + // obtain the path, and prepend it + NSString *path = [fntFile stringByDeletingLastPathComponent]; + NSString *textureFilename = [path stringByAppendingPathComponent:[dict objectForKey:@"textureFilename"]]; + + NSUInteger width = [[dict objectForKey:@"itemWidth"] unsignedIntValue] / CC_CONTENT_SCALE_FACTOR(); + NSUInteger height = [[dict objectForKey:@"itemHeight"] unsignedIntValue] / CC_CONTENT_SCALE_FACTOR(); + NSUInteger startChar = [[dict objectForKey:@"firstChar"] unsignedIntValue]; + + return [self initWithString:theString + charMapFile:textureFilename + itemWidth:width + itemHeight:height + startCharMap:startChar]; +} + +-(id) initWithString:(NSString*)string charMapFile: (NSString*)filename itemWidth:(NSUInteger)w itemHeight:(NSUInteger)h startCharMap:(NSUInteger)c +{ + CCTexture2D *texture = [[CCTextureCache sharedTextureCache] addImage:filename]; + return [self initWithString:string texture:texture itemWidth:w itemHeight:h startCharMap:c]; +} + +-(id) initWithString:(NSString*) theString texture:(CCTexture2D*)texture itemWidth:(NSUInteger)w itemHeight:(NSUInteger)h startCharMap:(NSUInteger)c +{ + if ((self=[super initWithTexture:texture tileWidth:w tileHeight:h itemsToRender:[theString length] ]) ) { + + _mapStartChar = c; + [self setString: theString]; + } + + return self; +} + +-(void) dealloc +{ + [_string release]; + + [super dealloc]; +} + +#pragma mark CCLabelAtlas - Atlas generation + +-(void) updateAtlasValues +{ + NSUInteger n = [_string length]; + + ccV3F_C4B_T2F_Quad quad; + + const unsigned char *s = (unsigned char*) [_string UTF8String]; + + CCTexture2D *texture = [_textureAtlas texture]; + float textureWide = [texture pixelsWide]; + float textureHigh = [texture pixelsHigh]; + float itemWidthInPixels = _itemWidth * CC_CONTENT_SCALE_FACTOR(); + float itemHeightInPixels = _itemHeight * CC_CONTENT_SCALE_FACTOR(); + + + for( NSUInteger i=0; i _textureAtlas.capacity ) + [_textureAtlas resizeCapacity:len]; + + [_string release]; + _string = [newString copy]; + [self updateAtlasValues]; + + CGSize s = CGSizeMake(len * _itemWidth, _itemHeight); + [self setContentSize:s]; + + self.quadsToDraw = len; + } +} + +-(NSString*) string +{ + return _string; +} + +#pragma mark CCLabelAtlas - DebugDraw + +#if CC_LABELATLAS_DEBUG_DRAW +- (void) draw +{ + [super draw]; + + CGSize s = [self contentSize]; + CGPoint vertices[4]={ + ccp(0,0),ccp(s.width,0), + ccp(s.width,s.height),ccp(0,s.height), + }; + ccDrawPoly(vertices, 4, YES); +} +#endif // CC_LABELATLAS_DEBUG_DRAW + +@end diff --git "a/21451198\345\215\242\350\266\205/project5/MyPlane/libs/cocos2d/CCLabelBMFont.h" "b/21451198\345\215\242\350\266\205/project5/MyPlane/libs/cocos2d/CCLabelBMFont.h" new file mode 100644 index 00000000..7fb9d8e2 --- /dev/null +++ "b/21451198\345\215\242\350\266\205/project5/MyPlane/libs/cocos2d/CCLabelBMFont.h" @@ -0,0 +1,240 @@ +/* + * cocos2d for iPhone: http://www.cocos2d-iphone.org + * + * Copyright (c) 2008-2010 Ricardo Quesada + * Copyright (c) 2011 Zynga Inc. + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + * THE SOFTWARE. + * + * Portions of this code are based and inspired on: + * http://www.71squared.co.uk/2009/04/iphone-game-programming-tutorial-4-bitmap-font-class + * by Michael Daley + * + * Use any of these editors to generate BMFonts: + * http://glyphdesigner.71squared.com/ (Commercial, Mac OS X) + * http://www.n4te.com/hiero/hiero.jnlp (Free, Java) + * http://slick.cokeandcode.com/demos/hiero.jnlp (Free, Java) + * http://www.angelcode.com/products/bmfont/ (Free, Windows only) + */ + +#import "CCSpriteBatchNode.h" +#import "Support/uthash.h" + +enum { + kCCLabelAutomaticWidth = -1, +}; + +/** @struct ccBMFontDef + BMFont definition + */ +typedef struct _BMFontDef { + //! ID of the character + unichar charID; + //! origin and size of the font + CGRect rect; + //! The X amount the image should be offset when drawing the image (in pixels) + short xOffset; + //! The Y amount the image should be offset when drawing the image (in pixels) + short yOffset; + //! The amount to move the current position after drawing the character (in pixels) + short xAdvance; +} ccBMFontDef; + +/** @struct ccBMFontPadding + BMFont padding + @since v0.8.2 + */ +typedef struct _BMFontPadding { + /// padding left + int left; + /// padding top + int top; + /// padding right + int right; + /// padding bottom + int bottom; +} ccBMFontPadding; + +#pragma mark - Hash Element +typedef struct _FontDefHashElement +{ + NSUInteger key; // key. Font Unicode value + ccBMFontDef fontDef; // font definition + UT_hash_handle hh; +} tCCFontDefHashElement; + +// Equal function for targetSet. +typedef struct _KerningHashElement +{ + int key; // key for the hash. 16-bit for 1st element, 16-bit for 2nd element + int amount; + UT_hash_handle hh; +} tCCKerningHashElement; +#pragma mark - + +/** CCBMFontConfiguration has parsed configuration of the the .fnt file + @since v0.8 + */ +@interface CCBMFontConfiguration : NSObject +{ + // Character Set defines the letters that actually exist in the font + NSCharacterSet *_characterSet; + + // atlas name + NSString *_atlasName; + + // XXX: Creating a public interface so that the bitmapFontArray[] is accessible +@public + + // BMFont definitions + tCCFontDefHashElement *_fontDefDictionary; + + // FNTConfig: Common Height. Should be signed (issue #1343) + NSInteger _commonHeight; + + // Padding + ccBMFontPadding _padding; + + // values for kerning + tCCKerningHashElement *_kerningDictionary; +} + +// Character set +@property (nonatomic, retain, readonly) NSCharacterSet *characterSet; + +// atlasName +@property (nonatomic, readwrite, retain) NSString *atlasName; + +/** allocates a CCBMFontConfiguration with a FNT file */ ++(id) configurationWithFNTFile:(NSString*)FNTfile; +/** initializes a CCBMFontConfiguration with a FNT file */ +-(id) initWithFNTfile:(NSString*)FNTfile; +@end + + +/** CCLabelBMFont is a subclass of CCSpriteBatchNode + + Features: + - Treats each character like a CCSprite. This means that each individual character can be: + - rotated + - scaled + - translated + - tinted + - chage the opacity + - It can be used as part of a menu item. + - anchorPoint can be used to align the "label" + - Supports AngelCode text format + + Limitations: + - All inner characters are using an anchorPoint of (0.5f, 0.5f) and it is not recommend to change it + because it might affect the rendering + + CCLabelBMFont implements the protocol CCLabelProtocol, like CCLabel and CCLabelAtlas. + CCLabelBMFont has the flexibility of CCLabel, the speed of CCLabelAtlas and all the features of CCSprite. + If in doubt, use CCLabelBMFont instead of CCLabelAtlas / CCLabel. + + Supported editors: + - http://glyphdesigner.71squared.com/ + - http://www.bmglyph.com/ + - http://www.n4te.com/hiero/hiero.jnlp + - http://slick.cokeandcode.com/demos/hiero.jnlp + - http://www.angelcode.com/products/bmfont/ + + @since v0.8 + */ + +@interface CCLabelBMFont : CCSpriteBatchNode +{ + // string to render + NSString *_string; + + // name of fntFile + NSString *_fntFile; + + // initial string without line breaks + NSString *_initialString; + // max width until a line break is added + float _width; + // alignment of all lines + CCTextAlignment _alignment; + + CCBMFontConfiguration *_configuration; + + // texture RGBA + GLubyte _displayedOpacity, _realOpacity; + ccColor3B _displayedColor, _realColor; + BOOL _cascadeOpacityEnabled, _cascadeColorEnabled; + BOOL _opacityModifyRGB; + + // offset of the texture atlas + CGPoint _imageOffset; + + // reused char + CCSprite *_reusedChar; +} + +/** Purges the cached data. + Removes from memory the cached configurations and the atlas name dictionary. + @since v0.99.3 + */ ++(void) purgeCachedData; + +/** alignment used for the label */ +@property (nonatomic,assign,readonly) CCTextAlignment alignment; +/** fntFile used for the font */ +@property (nonatomic,retain) NSString* fntFile; +/** conforms to CCRGBAProtocol protocol */ +@property (nonatomic,readwrite) GLubyte opacity; +/** conforms to CCRGBAProtocol protocol */ +@property (nonatomic,readwrite) ccColor3B color; + + +/** creates a BMFont label with an initial string and the FNT file. */ ++(id) labelWithString:(NSString*)string fntFile:(NSString*)fntFile; +/** creates a BMFont label with an initial string, the FNT file, width, and alignment option */ ++(id) labelWithString:(NSString*)string fntFile:(NSString*)fntFile width:(float)width alignment:(CCTextAlignment)alignment; +/** creates a BMFont label with an initial string, the FNT file, width, alignment option and the offset of where the glyphs start on the .PNG image */ ++(id) labelWithString:(NSString*)string fntFile:(NSString*)fntFile width:(float)width alignment:(CCTextAlignment)alignment imageOffset:(CGPoint)offset; + +/** init a BMFont label with an initial string and the FNT file */ +-(id) initWithString:(NSString*)string fntFile:(NSString*)fntFile; +/** init a BMFont label with an initial string and the FNT file, width, and alignment option*/ +-(id) initWithString:(NSString*)string fntFile:(NSString*)fntFile width:(float)width alignment:(CCTextAlignment)alignment; +/** init a BMFont label with an initial string and the FNT file, width, alignment option and the offset of where the glyphs start on the .PNG image */ +-(id) initWithString:(NSString*)string fntFile:(NSString*)fntFile width:(float)width alignment:(CCTextAlignment)alignment imageOffset:(CGPoint)offset; + +/** updates the font chars based on the string to render */ +-(void) createFontChars; + +/** set label width */ +- (void)setWidth:(float)width; + +/** set label alignment */ +- (void)setAlignment:(CCTextAlignment)alignment; + +@end + +/** Free function that parses a FNT file a place it on the cache + */ +CCBMFontConfiguration * FNTConfigLoadFile( NSString *file ); +/** Purges the FNT config cache + */ +void FNTConfigRemoveCache( void ); + + diff --git "a/21451198\345\215\242\350\266\205/project5/MyPlane/libs/cocos2d/CCLabelBMFont.m" "b/21451198\345\215\242\350\266\205/project5/MyPlane/libs/cocos2d/CCLabelBMFont.m" new file mode 100644 index 00000000..659417f3 --- /dev/null +++ "b/21451198\345\215\242\350\266\205/project5/MyPlane/libs/cocos2d/CCLabelBMFont.m" @@ -0,0 +1,1023 @@ +/* + * cocos2d for iPhone: http://www.cocos2d-iphone.org + * + * Copyright (c) 2008-2010 Ricardo Quesada + * Copyright (c) 2011 Zynga Inc. + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + * THE SOFTWARE. + * + * Portions of this code are based and inspired on: + * http://www.71squared.co.uk/2009/04/iphone-game-programming-tutorial-4-bitmap-font-class + * by Michael Daley + * + * + * Use any of these editors to generate BMFonts: + * http://glyphdesigner.71squared.com/ (Commercial, Mac OS X) + * http://www.n4te.com/hiero/hiero.jnlp (Free, Java) + * http://slick.cokeandcode.com/demos/hiero.jnlp (Free, Java) + * http://www.angelcode.com/products/bmfont/ (Free, Windows only) + */ + +#import "ccConfig.h" +#import "ccMacros.h" +#import "CCLabelBMFont.h" +#import "CCSprite.h" +#import "CCDrawingPrimitives.h" +#import "CCConfiguration.h" +#import "CCTextureCache.h" +#import "Support/CCFileUtils.h" +#import "Support/CGPointExtension.h" +#import "Support/uthash.h" + +#pragma mark - +#pragma mark FNTConfig Cache - free functions + +NSMutableDictionary *configurations = nil; +CCBMFontConfiguration* FNTConfigLoadFile( NSString *fntFile) +{ + CCBMFontConfiguration *ret = nil; + + if( configurations == nil ) + configurations = [[NSMutableDictionary dictionaryWithCapacity:3] retain]; + + ret = [configurations objectForKey:fntFile]; + if( ret == nil ) { + ret = [CCBMFontConfiguration configurationWithFNTFile:fntFile]; + if( ret ) + [configurations setObject:ret forKey:fntFile]; + } + + return ret; +} + +void FNTConfigRemoveCache( void ) +{ + [configurations removeAllObjects]; +} + +#pragma mark - +#pragma mark BitmapFontConfiguration + +@interface CCBMFontConfiguration () +-(NSMutableString *) parseConfigFile:(NSString*)controlFile; +-(void) parseCharacterDefinition:(NSString*)line charDef:(ccBMFontDef*)characterDefinition; +-(void) parseInfoArguments:(NSString*)line; +-(void) parseCommonArguments:(NSString*)line; +-(void) parseImageFileName:(NSString*)line fntFile:(NSString*)fntFile; +-(void) parseKerningEntry:(NSString*)line; +-(void) purgeKerningDictionary; +-(void) purgeFontDefDictionary; +@end + +#pragma mark - +#pragma mark CCBMFontConfiguration + +@implementation CCBMFontConfiguration +@synthesize characterSet=_characterSet; +@synthesize atlasName=_atlasName; + ++(id) configurationWithFNTFile:(NSString*)FNTfile +{ + return [[[self alloc] initWithFNTfile:FNTfile] autorelease]; +} + +-(id) initWithFNTfile:(NSString*)fntFile +{ + if((self=[super init])) { + + _kerningDictionary = NULL; + _fontDefDictionary = NULL; + + NSMutableString *validCharsString = [self parseConfigFile:fntFile]; + + if( ! validCharsString ) { + [self release]; + return nil; + } + + _characterSet = [[NSCharacterSet characterSetWithCharactersInString:validCharsString] retain]; + } + return self; +} + +- (void) dealloc +{ + CCLOGINFO( @"cocos2d: deallocing %@", self); + [_characterSet release]; + [self purgeFontDefDictionary]; + [self purgeKerningDictionary]; + [_atlasName release]; + [super dealloc]; +} + +- (NSString*) description +{ + return [NSString stringWithFormat:@"<%@ = %p | Glphys:%d Kernings:%d | Image = %@>", [self class], self, + HASH_COUNT(_fontDefDictionary), + HASH_COUNT(_kerningDictionary), + _atlasName]; +} + + +-(void) purgeFontDefDictionary +{ + tCCFontDefHashElement *current, *tmp; + + HASH_ITER(hh, _fontDefDictionary, current, tmp) { + HASH_DEL(_fontDefDictionary, current); + free(current); + } +} + +-(void) purgeKerningDictionary +{ + tCCKerningHashElement *current; + + while(_kerningDictionary) { + current = _kerningDictionary; + HASH_DEL(_kerningDictionary,current); + free(current); + } +} + +- (NSMutableString *)parseConfigFile:(NSString*)fntFile +{ + NSString *fullpath = [[CCFileUtils sharedFileUtils] fullPathForFilename:fntFile]; + NSError *error; + NSString *contents = [NSString stringWithContentsOfFile:fullpath encoding:NSUTF8StringEncoding error:&error]; + + NSMutableString *validCharsString = [[NSMutableString alloc] initWithCapacity:512]; + + if( ! contents ) { + NSLog(@"cocos2d: Error parsing FNTfile %@: %@", fntFile, error); + return nil; + } + + // Move all lines in the string, which are denoted by \n, into an array + NSArray *lines = [[NSArray alloc] initWithArray:[contents componentsSeparatedByString:@"\n"]]; + + // Create an enumerator which we can use to move through the lines read from the control file + NSEnumerator *nse = [lines objectEnumerator]; + + // Create a holder for each line we are going to work with + NSString *line; + + // Loop through all the lines in the lines array processing each one + while( (line = [nse nextObject]) ) { + // parse spacing / padding + if([line hasPrefix:@"info face"]) { + // XXX: info parsing is incomplete + // Not needed for the Hiero editors, but needed for the AngelCode editor +// [self parseInfoArguments:line]; + } + // Check to see if the start of the line is something we are interested in + else if([line hasPrefix:@"common lineHeight"]) { + [self parseCommonArguments:line]; + } + else if([line hasPrefix:@"page id"]) { + [self parseImageFileName:line fntFile:fntFile]; + } + else if([line hasPrefix:@"chars c"]) { + // Ignore this line + } + else if([line hasPrefix:@"char"]) { + // Parse the current line and create a new CharDef + tCCFontDefHashElement *element = malloc( sizeof(*element) ); + + [self parseCharacterDefinition:line charDef:&element->fontDef]; + + element->key = element->fontDef.charID; + HASH_ADD_INT(_fontDefDictionary, key, element); + + [validCharsString appendString:[NSString stringWithFormat:@"%C", element->fontDef.charID]]; + } +// else if([line hasPrefix:@"kernings count"]) { +// [self parseKerningCapacity:line]; +// } + else if([line hasPrefix:@"kerning first"]) { + [self parseKerningEntry:line]; + } + } + // Finished with lines so release it + [lines release]; + + return [validCharsString autorelease]; +} + +-(void) parseImageFileName:(NSString*)line fntFile:(NSString*)fntFile +{ + NSString *propertyValue = nil; + + // Break the values for this line up using = + NSArray *values = [line componentsSeparatedByString:@"="]; + + // Get the enumerator for the array of components which has been created + NSEnumerator *nse = [values objectEnumerator]; + + // We need to move past the first entry in the array before we start assigning values + [nse nextObject]; + + // page ID. Sanity check + propertyValue = [nse nextObject]; + NSAssert( [propertyValue intValue] == 0, @"XXX: LabelBMFont only supports 1 page"); + + // file + propertyValue = [nse nextObject]; + NSArray *array = [propertyValue componentsSeparatedByString:@"\""]; + propertyValue = [array objectAtIndex:1]; + NSAssert(propertyValue,@"LabelBMFont file could not be found"); + + // Supports subdirectories + NSString *dir = [fntFile stringByDeletingLastPathComponent]; + _atlasName = [dir stringByAppendingPathComponent:propertyValue]; + + [_atlasName retain]; +} + +-(void) parseInfoArguments:(NSString*)line +{ + // + // possible lines to parse: + // info face="Script" size=32 bold=0 italic=0 charset="" unicode=1 stretchH=100 smooth=1 aa=1 padding=1,4,3,2 spacing=0,0 outline=0 + // info face="Cracked" size=36 bold=0 italic=0 charset="" unicode=0 stretchH=100 smooth=1 aa=1 padding=0,0,0,0 spacing=1,1 + // + NSArray *values = [line componentsSeparatedByString:@"="]; + NSEnumerator *nse = [values objectEnumerator]; + NSString *propertyValue = nil; + + // We need to move past the first entry in the array before we start assigning values + [nse nextObject]; + + // face (ignore) + [nse nextObject]; + + // size (ignore) + [nse nextObject]; + + // bold (ignore) + [nse nextObject]; + + // italic (ignore) + [nse nextObject]; + + // charset (ignore) + [nse nextObject]; + + // unicode (ignore) + [nse nextObject]; + + // strechH (ignore) + [nse nextObject]; + + // smooth (ignore) + [nse nextObject]; + + // aa (ignore) + [nse nextObject]; + + // padding (ignore) + propertyValue = [nse nextObject]; + { + + NSArray *paddingValues = [propertyValue componentsSeparatedByString:@","]; + NSEnumerator *paddingEnum = [paddingValues objectEnumerator]; + // padding top + propertyValue = [paddingEnum nextObject]; + _padding.top = [propertyValue intValue]; + + // padding right + propertyValue = [paddingEnum nextObject]; + _padding.right = [propertyValue intValue]; + + // padding bottom + propertyValue = [paddingEnum nextObject]; + _padding.bottom = [propertyValue intValue]; + + // padding left + propertyValue = [paddingEnum nextObject]; + _padding.left = [propertyValue intValue]; + + CCLOG(@"cocos2d: padding: %d,%d,%d,%d", _padding.left, _padding.top, _padding.right, _padding.bottom); + } + + // spacing (ignore) + [nse nextObject]; +} + +-(void) parseCommonArguments:(NSString*)line +{ + // + // line to parse: + // common lineHeight=104 base=26 scaleW=1024 scaleH=512 pages=1 packed=0 + // + NSArray *values = [line componentsSeparatedByString:@"="]; + NSEnumerator *nse = [values objectEnumerator]; + NSString *propertyValue = nil; + + // We need to move past the first entry in the array before we start assigning values + [nse nextObject]; + + // Character ID + propertyValue = [nse nextObject]; + _commonHeight = [propertyValue intValue]; + + // base (ignore) + [nse nextObject]; + + + // scaleW. sanity check + propertyValue = [nse nextObject]; + NSAssert( [propertyValue intValue] <= [[CCConfiguration sharedConfiguration] maxTextureSize], @"CCLabelBMFont: page can't be larger than supported"); + + // scaleH. sanity check + propertyValue = [nse nextObject]; + NSAssert( [propertyValue intValue] <= [[CCConfiguration sharedConfiguration] maxTextureSize], @"CCLabelBMFont: page can't be larger than supported"); + + // pages. sanity check + propertyValue = [nse nextObject]; + NSAssert( [propertyValue intValue] == 1, @"CCBitfontAtlas: only supports 1 page"); + + // packed (ignore) What does this mean ?? +} +- (void)parseCharacterDefinition:(NSString*)line charDef:(ccBMFontDef*)characterDefinition +{ + // Break the values for this line up using = + NSArray *values = [line componentsSeparatedByString:@"="]; + NSEnumerator *nse = [values objectEnumerator]; + NSString *propertyValue; + + // We need to move past the first entry in the array before we start assigning values + [nse nextObject]; + + // Character ID + propertyValue = [nse nextObject]; + propertyValue = [propertyValue substringToIndex: [propertyValue rangeOfString: @" "].location]; + characterDefinition->charID = [propertyValue intValue]; + + // Character x + propertyValue = [nse nextObject]; + characterDefinition->rect.origin.x = [propertyValue intValue]; + // Character y + propertyValue = [nse nextObject]; + characterDefinition->rect.origin.y = [propertyValue intValue]; + // Character width + propertyValue = [nse nextObject]; + characterDefinition->rect.size.width = [propertyValue intValue]; + // Character height + propertyValue = [nse nextObject]; + characterDefinition->rect.size.height = [propertyValue intValue]; + // Character xoffset + propertyValue = [nse nextObject]; + characterDefinition->xOffset = [propertyValue intValue]; + // Character yoffset + propertyValue = [nse nextObject]; + characterDefinition->yOffset = [propertyValue intValue]; + // Character xadvance + propertyValue = [nse nextObject]; + characterDefinition->xAdvance = [propertyValue intValue]; +} + +-(void) parseKerningEntry:(NSString*) line +{ + NSArray *values = [line componentsSeparatedByString:@"="]; + NSEnumerator *nse = [values objectEnumerator]; + NSString *propertyValue; + + // We need to move past the first entry in the array before we start assigning values + [nse nextObject]; + + // first + propertyValue = [nse nextObject]; + int first = [propertyValue intValue]; + + // second + propertyValue = [nse nextObject]; + int second = [propertyValue intValue]; + + // second + propertyValue = [nse nextObject]; + int amount = [propertyValue intValue]; + + tCCKerningHashElement *element = calloc( sizeof( *element ), 1 ); + element->amount = amount; + element->key = (first<<16) | (second&0xffff); + HASH_ADD_INT(_kerningDictionary,key, element); +} + +@end + +#pragma mark - +#pragma mark CCLabelBMFont + +@interface CCLabelBMFont () + +-(int) kerningAmountForFirst:(unichar)first second:(unichar)second; +-(void) updateLabel; +-(void) setString:(NSString*) newString updateLabel:(BOOL)update; + +@end + +#pragma mark - +#pragma mark CCLabelBMFont + +@implementation CCLabelBMFont + +@synthesize alignment = _alignment; +@synthesize cascadeColorEnabled = _cascadeColorEnabled, cascadeOpacityEnabled = _cascadeOpacityEnabled; + +#pragma mark LabelBMFont - Purge Cache ++(void) purgeCachedData +{ + FNTConfigRemoveCache(); +} + +#pragma mark LabelBMFont - Creation & Init + ++(id) labelWithString:(NSString *)string fntFile:(NSString *)fntFile +{ + return [[[self alloc] initWithString:string fntFile:fntFile width:kCCLabelAutomaticWidth alignment:kCCTextAlignmentLeft imageOffset:CGPointZero] autorelease]; +} + ++(id) labelWithString:(NSString*)string fntFile:(NSString*)fntFile width:(float)width alignment:(CCTextAlignment)alignment +{ + return [[[self alloc] initWithString:string fntFile:fntFile width:width alignment:alignment imageOffset:CGPointZero] autorelease]; +} + ++(id) labelWithString:(NSString*)string fntFile:(NSString*)fntFile width:(float)width alignment:(CCTextAlignment)alignment imageOffset:(CGPoint)offset +{ + return [[[self alloc] initWithString:string fntFile:fntFile width:width alignment:alignment imageOffset:offset] autorelease]; +} + +-(id) init +{ + return [self initWithString:nil fntFile:nil width:kCCLabelAutomaticWidth alignment:kCCTextAlignmentLeft imageOffset:CGPointZero]; +} + +-(id) initWithString:(NSString*)theString fntFile:(NSString*)fntFile +{ + return [self initWithString:theString fntFile:fntFile width:kCCLabelAutomaticWidth alignment:kCCTextAlignmentLeft]; +} + +-(id) initWithString:(NSString*)theString fntFile:(NSString*)fntFile width:(float)width alignment:(CCTextAlignment)alignment +{ + return [self initWithString:theString fntFile:fntFile width:width alignment:alignment imageOffset:CGPointZero]; +} + +// designated initializer +-(id) initWithString:(NSString*)theString fntFile:(NSString*)fntFile width:(float)width alignment:(CCTextAlignment)alignment imageOffset:(CGPoint)offset +{ + NSAssert(!_configuration, @"re-init is no longer supported"); + + // if theString && fntfile are both nil, then it is OK + NSAssert( (theString && fntFile) || (theString==nil && fntFile==nil), @"Invalid params for CCLabelBMFont"); + + CCTexture2D *texture = nil; + + if( fntFile ) { + CCBMFontConfiguration *newConf = FNTConfigLoadFile(fntFile); + if(!newConf) { + CCLOGWARN(@"cocos2d: WARNING. CCLabelBMFont: Impossible to create font. Please check file: '%@'", fntFile ); + [self release]; + return nil; + } + + _configuration = [newConf retain]; + _fntFile = [fntFile copy]; + + texture = [[CCTextureCache sharedTextureCache] addImage:_configuration.atlasName]; + + } else + texture = [[[CCTexture2D alloc] init] autorelease]; + + + if ( (self=[super initWithTexture:texture capacity:[theString length]]) ) { + _width = width; + _alignment = alignment; + + _displayedOpacity = _realOpacity = 255; + _displayedColor = _realColor = ccWHITE; + _cascadeOpacityEnabled = YES; + _cascadeColorEnabled = YES; + + _contentSize = CGSizeZero; + + _opacityModifyRGB = [[_textureAtlas texture] hasPremultipliedAlpha]; + + _anchorPoint = ccp(0.5f, 0.5f); + + _imageOffset = offset; + + _reusedChar = [[CCSprite alloc] initWithTexture:_textureAtlas.texture rect:CGRectMake(0, 0, 0, 0) rotated:NO]; + [_reusedChar setBatchNode:self]; + + [self setString:theString updateLabel:YES]; + } + + return self; +} + +-(void) dealloc +{ + [_string release]; + [_initialString release]; + [_configuration release]; + [_fntFile release]; + [_reusedChar release]; + + [super dealloc]; +} + +#pragma mark LabelBMFont - Alignment + +- (void)updateLabel +{ + [self setString:_initialString updateLabel:NO]; + + if (_width > 0){ + //Step 1: Make multiline + + NSString *multilineString = @"", *lastWord = @""; + int line = 1, i = 0; + NSUInteger stringLength = [self.string length]; + float startOfLine = -1, startOfWord = -1; + int skip = 0; + //Go through each character and insert line breaks as necessary + for (int j = 0; j < [_children count]; j++) { + CCSprite *characterSprite; + int justSkipped = 0; + while(!(characterSprite = (CCSprite *)[self getChildByTag:j+skip+justSkipped])) + justSkipped++; + skip += justSkipped; + + if (!characterSprite.visible) + continue; + + if (i >= stringLength || i < 0) + break; + + unichar character = [self.string characterAtIndex:i]; + + if (startOfWord == -1) + startOfWord = characterSprite.position.x - characterSprite.contentSize.width/2; + if (startOfLine == -1) + startOfLine = startOfWord; + + //Character is a line break + //Put lastWord on the current line and start a new line + //Reset lastWord + if ([[NSCharacterSet newlineCharacterSet] characterIsMember:character]) { + lastWord = [lastWord stringByTrimmingCharactersInSet:[NSCharacterSet whitespaceCharacterSet]]; + lastWord = [lastWord stringByPaddingToLength:[lastWord length] + justSkipped withString:[NSString stringWithFormat:@"%C", character] startingAtIndex:0]; + multilineString = [multilineString stringByAppendingString:lastWord]; + lastWord = @""; + startOfWord = -1; + line++; + startOfLine = -1; + i+=justSkipped; + + //CCLabelBMFont do not have a character for new lines, so do NOT "continue;" in the for loop. Process the next character + if (i >= stringLength || i < 0) + break; + character = [self.string characterAtIndex:i]; + + if (startOfWord == -1) + startOfWord = characterSprite.position.x - characterSprite.contentSize.width/2; + if (startOfLine == -1) + startOfLine = startOfWord; + } + + //Character is a whitespace + //Put lastWord on current line and continue on current line + //Reset lastWord + if ([[NSCharacterSet whitespaceCharacterSet] characterIsMember:character]) { + lastWord = [lastWord stringByAppendingFormat:@"%C", character]; + multilineString = [multilineString stringByAppendingString:lastWord]; + lastWord = @""; + startOfWord = -1; + i++; + continue; + } + + //Character is out of bounds + //Do not put lastWord on current line. Add "\n" to current line to start a new line + //Append to lastWord + if (characterSprite.position.x + characterSprite.contentSize.width/2 - startOfLine > _width) { + lastWord = [lastWord stringByAppendingFormat:@"%C", character]; + NSString *trimmedString = [multilineString stringByTrimmingCharactersInSet:[NSCharacterSet whitespaceCharacterSet]]; + multilineString = [trimmedString stringByAppendingString:@"\n"]; + line++; + startOfLine = -1; + i++; + continue; + } else { + //Character is normal + //Append to lastWord + lastWord = [lastWord stringByAppendingFormat:@"%C", character]; + i++; + continue; + } + } + + multilineString = [multilineString stringByAppendingFormat:@"%@", lastWord]; + + [self setString:multilineString updateLabel:NO]; + } + + //Step 2: Make alignment + + if (self.alignment != kCCTextAlignmentLeft) { + + int i = 0; + //Number of spaces skipped + int lineNumber = 0; + //Go through line by line + for (NSString *lineString in [_string componentsSeparatedByCharactersInSet:[NSCharacterSet newlineCharacterSet]]) { + int lineWidth = 0; + + //Find index of last character in this line + NSInteger index = i + [lineString length] - 1 + lineNumber; + if (index < 0) + continue; + + //Find position of last character on the line + CCSprite *lastChar = (CCSprite *)[self getChildByTag:index]; + + lineWidth = lastChar.position.x + lastChar.contentSize.width/2; + + //Figure out how much to shift each character in this line horizontally + float shift = 0; + switch (self.alignment) { + case kCCTextAlignmentCenter: + shift = self.contentSize.width/2 - lineWidth/2; + break; + case kCCTextAlignmentRight: + shift = self.contentSize.width - lineWidth; + default: + break; + } + + if (shift != 0) { + int j = 0; + //For each character, shift it so that the line is center aligned + for (j = 0; j < [lineString length]; j++) { + index = i + j + lineNumber; + if (index < 0) + continue; + CCSprite *characterSprite = (CCSprite *)[self getChildByTag:index]; + characterSprite.position = ccpAdd(characterSprite.position, ccp(shift, 0)); + } + } + i += [lineString length]; + lineNumber++; + } + } +} + +#pragma mark LabelBMFont - Atlas generation + +-(int) kerningAmountForFirst:(unichar)first second:(unichar)second +{ + int ret = 0; + unsigned int key = (first<<16) | (second & 0xffff); + + if( _configuration->_kerningDictionary ) { + tCCKerningHashElement *element = NULL; + HASH_FIND_INT(_configuration->_kerningDictionary, &key, element); + if(element) + ret = element->amount; + } + + return ret; +} + +-(void) createFontChars +{ + NSInteger nextFontPositionX = 0; + NSInteger nextFontPositionY = 0; + unichar prev = -1; + NSInteger kerningAmount = 0; + + CGSize tmpSize = CGSizeZero; + + NSInteger longestLine = 0; + NSUInteger totalHeight = 0; + + NSUInteger quantityOfLines = 1; + + NSCharacterSet *charSet = _configuration.characterSet; + + NSUInteger stringLen = [_string length]; + if( ! stringLen ) + return; + + // quantity of lines NEEDS to be calculated before parsing the lines, + // since the Y position needs to be calcualted before hand + for(NSUInteger i=0; i < stringLen-1;i++) { + unichar c = [_string characterAtIndex:i]; + if( c=='\n') + quantityOfLines++; + } + + totalHeight = _configuration->_commonHeight * quantityOfLines; + nextFontPositionY = -(_configuration->_commonHeight - _configuration->_commonHeight*quantityOfLines); + CGRect rect; + ccBMFontDef fontDef; + + for(NSUInteger i = 0; i_commonHeight; + continue; + } + + if(![charSet characterIsMember:c]){ + CCLOGWARN(@"cocos2d: CCLabelBMFont: Attempted to use character not defined in this bitmap: %C", c); + continue; + } + + kerningAmount = [self kerningAmountForFirst:prev second:c]; + + tCCFontDefHashElement *element = NULL; + + // unichar is a short, and an int is needed on HASH_FIND_INT + NSUInteger key = (NSUInteger)c; + HASH_FIND_INT(_configuration->_fontDefDictionary , &key, element); + if( ! element ) { + CCLOGWARN(@"cocos2d: CCLabelBMFont: characer not found %c", c); + continue; + } + + fontDef = element->fontDef; + + rect = fontDef.rect; + rect = CC_RECT_PIXELS_TO_POINTS(rect); + + rect.origin.x += _imageOffset.x; + rect.origin.y += _imageOffset.y; + + CCSprite *fontChar; + + BOOL hasSprite = YES; + fontChar = (CCSprite*) [self getChildByTag:i]; + if( fontChar ) + { + // Reusing previous Sprite + fontChar.visible = YES; + } + else + { + // New Sprite ? Set correct color, opacity, etc... + if( 0 ) { + /* WIP: Doesn't support many features yet. + But this code is super fast. It doesn't create any sprite. + Ideal for big labels. + */ + fontChar = _reusedChar; + fontChar.batchNode = nil; + hasSprite = NO; + } else { + fontChar = [[CCSprite alloc] initWithTexture:_textureAtlas.texture rect:rect]; + [self addChild:fontChar z:i tag:i]; + [fontChar release]; + } + + // Apply label properties + [fontChar setOpacityModifyRGB:_opacityModifyRGB]; + + // Color MUST be set before opacity, since opacity might change color if OpacityModifyRGB is on + [fontChar updateDisplayedColor:_displayedColor]; + [fontChar updateDisplayedOpacity:_displayedOpacity]; + } + + // updating previous sprite + [fontChar setTextureRect:rect rotated:NO untrimmedSize:rect.size]; + + + // See issue 1343. cast( signed short + unsigned integer ) == unsigned integer (sign is lost!) + NSInteger yOffset = _configuration->_commonHeight - fontDef.yOffset; + CGPoint fontPos = ccp( (CGFloat)nextFontPositionX + fontDef.xOffset + fontDef.rect.size.width*0.5f + kerningAmount, + (CGFloat)nextFontPositionY + yOffset - rect.size.height*0.5f * CC_CONTENT_SCALE_FACTOR() ); + fontChar.position = CC_POINT_PIXELS_TO_POINTS(fontPos); + + // update kerning + nextFontPositionX += fontDef.xAdvance + kerningAmount; + prev = c; + + + if (longestLine < nextFontPositionX) + longestLine = nextFontPositionX; + + if( ! hasSprite ) + [self updateQuadFromSprite:fontChar quadIndex:i]; + } + + // If the last character processed has an xAdvance which is less that the width of the characters image, then we need + // to adjust the width of the string to take this into account, or the character will overlap the end of the bounding + // box + if (fontDef.xAdvance < fontDef.rect.size.width) { + tmpSize.width = longestLine + fontDef.rect.size.width - fontDef.xAdvance; + } else { + tmpSize.width = longestLine; + } + tmpSize.height = totalHeight; + + [self setContentSize:CC_SIZE_PIXELS_TO_POINTS(tmpSize)]; +} + +#pragma mark LabelBMFont - CCLabelProtocol protocol +-(NSString*) string +{ + return _string; +} + +-(void) setCString:(char*)label +{ + [self setString:[NSString stringWithUTF8String:label] ]; +} + +- (void) setString:(NSString*)newString +{ + [self setString:newString updateLabel:YES]; +} + +- (void) setString:(NSString*) newString updateLabel:(BOOL)update +{ + if( !update ) { + [_string release]; + _string = [newString copy]; + } else { + [_initialString release]; + _initialString = [newString copy]; + } + + CCSprite *child; + CCARRAY_FOREACH(_children, child) + child.visible = NO; + + [self createFontChars]; + + if (update) + [self updateLabel]; +} + +#pragma mark LabelBMFont - CCRGBAProtocol protocol + +-(ccColor3B) color +{ + return _realColor; +} + +-(ccColor3B) displayedColor +{ + return _displayedColor; +} + +-(void) setColor:(ccColor3B)color +{ + _displayedColor = _realColor = color; + + if( _cascadeColorEnabled ) { + ccColor3B parentColor = ccWHITE; + if( [_parent conformsToProtocol:@protocol(CCRGBAProtocol)] && [(id)_parent isCascadeColorEnabled] ) + parentColor = [(id)_parent displayedColor]; + [self updateDisplayedColor:parentColor]; + } +} + +-(GLubyte) opacity +{ + return _realOpacity; +} + +-(GLubyte) displayedOpacity +{ + return _displayedOpacity; +} + +/** Override synthesized setOpacity to recurse items */ +- (void) setOpacity:(GLubyte)opacity +{ + _displayedOpacity = _realOpacity = opacity; + + if( _cascadeOpacityEnabled ) { + GLubyte parentOpacity = 255; + if( [_parent conformsToProtocol:@protocol(CCRGBAProtocol)] && [(id)_parent isCascadeOpacityEnabled] ) + parentOpacity = [(id)_parent displayedOpacity]; + [self updateDisplayedOpacity:parentOpacity]; + } +} + +-(void) setOpacityModifyRGB:(BOOL)modify +{ + _opacityModifyRGB = modify; + + id child; + CCARRAY_FOREACH(_children, child) + [child setOpacityModifyRGB:modify]; +} + +-(BOOL) doesOpacityModifyRGB +{ + return _opacityModifyRGB; +} + +- (void)updateDisplayedOpacity:(GLubyte)parentOpacity +{ + _displayedOpacity = _realOpacity * parentOpacity/255.0; + + CCSprite *item; + CCARRAY_FOREACH(_children, item) { + [item updateDisplayedOpacity:_displayedOpacity]; + } +} + +- (void)updateDisplayedColor:(ccColor3B)parentColor +{ + _displayedColor.r = _realColor.r * parentColor.r/255.0; + _displayedColor.g = _realColor.g * parentColor.g/255.0; + _displayedColor.b = _realColor.b * parentColor.b/255.0; + + CCSprite *item; + CCARRAY_FOREACH(_children, item) { + [item updateDisplayedColor:_displayedColor]; + } +} + +#pragma mark LabelBMFont - AnchorPoint +-(void) setAnchorPoint:(CGPoint)point +{ + if( ! CGPointEqualToPoint(point, _anchorPoint) ) { + [super setAnchorPoint:point]; + [self createFontChars]; + } +} + +#pragma mark LabelBMFont - Alignment +- (void)setWidth:(float)width { + _width = width; + [self updateLabel]; +} + +- (void)setAlignment:(CCTextAlignment)alignment { + _alignment = alignment; + [self updateLabel]; +} + +#pragma mark LabelBMFont - FntFile +- (void) setFntFile:(NSString*) fntFile +{ + if( fntFile != _fntFile ) { + + CCBMFontConfiguration *newConf = FNTConfigLoadFile(fntFile); + + NSAssert( newConf, @"CCLabelBMFont: Impossible to create font. Please check file: '%@'", fntFile ); + + [_fntFile release]; + _fntFile = [fntFile retain]; + + [_configuration release]; + _configuration = [newConf retain]; + + [self setTexture:[[CCTextureCache sharedTextureCache] addImage:_configuration.atlasName]]; + [self createFontChars]; + } +} + +- (NSString*) fntFile +{ + return _fntFile; +} + +#pragma mark LabelBMFont - Debug draw +#if CC_LABELBMFONT_DEBUG_DRAW +-(void) draw +{ + [super draw]; + + CGSize s = [self contentSize]; + CGPoint vertices[4]={ + ccp(0,0),ccp(s.width,0), + ccp(s.width,s.height),ccp(0,s.height), + }; + ccDrawPoly(vertices, 4, YES); +} +#endif // CC_LABELBMFONT_DEBUG_DRAW +@end diff --git "a/21451198\345\215\242\350\266\205/project5/MyPlane/libs/cocos2d/CCLabelTTF.h" "b/21451198\345\215\242\350\266\205/project5/MyPlane/libs/cocos2d/CCLabelTTF.h" new file mode 100644 index 00000000..6b881773 --- /dev/null +++ "b/21451198\345\215\242\350\266\205/project5/MyPlane/libs/cocos2d/CCLabelTTF.h" @@ -0,0 +1,180 @@ +/* + * cocos2d for iPhone: http://www.cocos2d-iphone.org + * + * Copyright (c) 2008-2010 Ricardo Quesada + * Copyright (c) 2011 Zynga Inc. + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + * THE SOFTWARE. + * + */ + + +#import "CCTexture2D.h" +#import "CCSprite.h" +#import "CCFontDefinition.h" +#import "Platforms/CCNS.h" + + +/** CCLabel is a subclass of CCTextureNode that knows how to render text labels + * + * All features from CCTextureNode are valid in CCLabel + * + * CCLabel objects are slow. Consider using CCLabelAtlas or CCLabelBMFont instead. + */ + +@interface CCLabelTTF : CCSprite +{ + CGSize _dimensions; + CCTextAlignment _hAlignment; + CCVerticalTextAlignment _vAlignment; + NSString *_fontName; + CGFloat _fontSize; + CCLineBreakMode _lineBreakMode; + NSString *_string; + + /** font shadow */ + bool _shadowEnabled; + float _shadowOpacity; + float _shadowBlur; + CGSize _shadowOffset; + + /** font stroke */ + bool _strokeEnabled; + ccColor3B _strokeColor; + float _strokeSize; + + /** font fill color */ + ccColor3B _textFillColor; +} + +/** Font name used in the label */ +@property (nonatomic,retain) NSString* fontName; +/** Font size of the label */ +@property (nonatomic,assign) float fontSize; +/** Dimensions of the label in Points */ +@property (nonatomic,assign) CGSize dimensions; +/** The alignment of the label */ +@property (nonatomic,assign) CCTextAlignment horizontalAlignment; +/** The vertical alignment of the label */ +@property (nonatomic,assign) CCVerticalTextAlignment verticalAlignment; + + + +/** creates a CCLabelTTF with a string and a font definition */ ++ (id) labelWithString:(NSString*)string fontDefinition:(CCFontDefinition *)definition; + +/** creates a CCLabelTTF with a font name and font size in points*/ ++ (id) labelWithString:(NSString*)string fontName:(NSString*)name fontSize:(CGFloat)size; + +/** creates a CCLabelTTF from a fontname, horizontal alignment, dimension in points, and font size in points. + Supported lineBreakModes: + - iOS: all UILineBreakMode supported modes + - Mac: Only NSLineBreakByWordWrapping is supported. + @since v1.0 + */ ++ (id) labelWithString:(NSString*)string fontName:(NSString*)name fontSize:(CGFloat)size dimensions:(CGSize)dimensions hAlignment:(CCTextAlignment)alignment; + +/** creates a CCLabelTTF from a fontname, horizontal alignment, dimension in points, line break mode, and font size in points. + Supported lineBreakModes: + - iOS: all UILineBreakMode supported modes + - Mac: Only NSLineBreakByWordWrapping is supported. + @since v1.0 + */ ++ (id) labelWithString:(NSString*)string fontName:(NSString*)name fontSize:(CGFloat)size dimensions:(CGSize)dimensions hAlignment:(CCTextAlignment)alignment lineBreakMode:(CCLineBreakMode)lineBreakMode; + +/** creates a CCLabelTTF from a fontname, horizontal alignment, vertical alignment, dimension in points, line break mode, and font size in points. + Supported lineBreakModes: + - iOS: all UILineBreakMode supported modes + - Mac: Only NSLineBreakByWordWrapping is supported. + @since v1.0 + */ ++ (id) labelWithString:(NSString*)string fontName:(NSString*)name fontSize:(CGFloat)size dimensions:(CGSize)dimensions hAlignment:(CCTextAlignment)alignment vAlignment:(CCVerticalTextAlignment)vertAlignment lineBreakMode:(CCLineBreakMode)lineBreakMode ; + +/** creates a CCLabel from a fontname, alignment, dimension in points and font size in points*/ ++ (id) labelWithString:(NSString*)string fontName:(NSString*)name fontSize:(CGFloat)size dimensions:(CGSize)dimensions hAlignment:(CCTextAlignment)alignment vAlignment:(CCVerticalTextAlignment)vertAlignment; + + +/** initializes the CCLabelTTF with a font name and font size in points */ +- (id) initWithString:(NSString*)string fontName:(NSString*)name fontSize:(CGFloat)size; + +/** initializes the CCLabelTTF with a font name, horizontal alignment, dimension in points, and font size in points. + Default verticalAlignment: kCCVerticalTextAlignmentTop + Default lineBreakMode: CCLineBreakModeWordWrap + @since v1.0 + */ +- (id) initWithString:(NSString*)string fontName:(NSString*)name fontSize:(CGFloat)size dimensions:(CGSize)dimensions hAlignment:(CCTextAlignment)alignment; + +/** initializes the CCLabelTTF with a font name, horizontal alignment, dimension in points, line break mode and font size in points. + Default verticalAlignment: kCCVerticalTextAlignmentTop + + Supported lineBreakModes: + - iOS: all UILineBreakMode supported modes + - Mac: Only NSLineBreakByWordWrapping is supported. + @since v1.0 + */ +- (id) initWithString:(NSString*)str fontName:(NSString*)name fontSize:(CGFloat)size dimensions:(CGSize)dimensions hAlignment:(CCTextAlignment)alignment lineBreakMode:(CCLineBreakMode)lineBreakMode; + +/** initializes the CCLabelTTF with a font name, horizontal alignment, vertical alignment, dimension in points and font size in points. + Default lineBreakMode: CCLineBreakModeWordWrap + */ +- (id) initWithString:(NSString*)string fontName:(NSString*)name fontSize:(CGFloat)size dimensions:(CGSize)dimensions hAlignment:(CCTextAlignment)alignment vAlignment:(CCVerticalTextAlignment)vertAlignment; + +/** initializes the CCLabelTTF with a font name, horizontal alignment, vertical alignment, dimension in points, line break mode and font size in points. + Supported lineBreakModes: + - iOS: all UILineBreakMode supported modes + - Mac: Only NSLineBreakByWordWrapping is supported. + @since v2.0 + */ +- (id) initWithString:(NSString*)str fontName:(NSString*)name fontSize:(CGFloat)size dimensions:(CGSize)dimensions hAlignment:(CCTextAlignment)alignment vAlignment:(CCVerticalTextAlignment)vAlignment lineBreakMode:(CCLineBreakMode)lineBreakMode ; + +/** changes the string to render + * @warning Changing the string is as expensive as creating a new CCLabelTTF. To obtain better performance use CCLabelAtlas or CCLabelBMFont. + */ +- (void) setString:(NSString*)str; + + +/** enable or disable shadow for the label */ +- (void) enableShadowWithOffset:(CGSize)shadowOffset opacity:(float)shadowOpacity blur:(float)shadowBlur updateImage:(Boolean) mustUpdate; + +/** disable shadow rendering */ +- (void) disableShadowAndUpdateImage:(Boolean)mustUpdate; + +/** enable or disable stroke */ +- (void) enableStrokeWithColor:(ccColor3B)strokeColor size:(float)strokeSize updateImage:(Boolean) mustUpdate; + +/** disable stroke */ +- (void) disableStrokeAndUpdateImage:(Boolean) mustUpdate; + +/** set text tinting */ +- (void) setFontFillColor:(ccColor3B) tintColor updateImage:(Boolean) mustUpdate; + +/** init the label with string and text definition*/ +- (id) initWithString:(NSString *) string fontDefinition:(CCFontDefinition *)definition; + +/** get and set the font definition */ +- (CCFontDefinition*) getFontDefinition; + +/** get and set the font definition */ +- (void) setFontDefinition: (CCFontDefinition *) fontDef; + + + + + +@end diff --git "a/21451198\345\215\242\350\266\205/project5/MyPlane/libs/cocos2d/CCLabelTTF.m" "b/21451198\345\215\242\350\266\205/project5/MyPlane/libs/cocos2d/CCLabelTTF.m" new file mode 100644 index 00000000..99633a9e --- /dev/null +++ "b/21451198\345\215\242\350\266\205/project5/MyPlane/libs/cocos2d/CCLabelTTF.m" @@ -0,0 +1,600 @@ +/* + * cocos2d for iPhone: http://www.cocos2d-iphone.org + * + * Copyright (c) 2008-2010 Ricardo Quesada + * Copyright (c) 2011 Zynga Inc. + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + * THE SOFTWARE. + * + */ + + +#import "CCLabelTTF.h" +#import "Support/CGPointExtension.h" +#import "ccMacros.h" +#import "CCShaderCache.h" +#import "CCGLProgram.h" +#import "Support/CCFileUtils.h" +#import "ccDeprecated.h" + +#ifdef __CC_PLATFORM_IOS +#import "Platforms/iOS/CCDirectorIOS.h" +#import +#endif + +#if CC_USE_LA88_LABELS +#define SHADER_PROGRAM kCCShader_PositionTextureColor +#else +#define SHADER_PROGRAM kCCShader_PositionTextureA8Color +#endif + +@interface CCLabelTTF () +- (BOOL) updateTexture; +- (NSString*) getFontName:(NSString*)fontName; +- (CCFontDefinition*) prepareFontDefinitionAndAdjustForResolution:(Boolean) resAdjust; +@end + +@implementation CCLabelTTF + +// - ++ (id) labelWithString:(NSString*)string fontDefinition:(CCFontDefinition *)definition +{ + return [[[self alloc] initWithString:string fontDefinition:definition] autorelease]; +} + +// - ++ (id) labelWithString:(NSString*)string fontName:(NSString*)name fontSize:(CGFloat)size +{ + return [[[self alloc] initWithString:string fontName:name fontSize:size]autorelease]; +} + +// hAlignment ++ (id) labelWithString:(NSString*)string fontName:(NSString*)name fontSize:(CGFloat)size dimensions:(CGSize)dimensions hAlignment:(CCTextAlignment)alignment +{ + return [[[self alloc] initWithString:string fontName:name fontSize:size dimensions:dimensions hAlignment:alignment vAlignment:kCCVerticalTextAlignmentTop lineBreakMode:kCCLineBreakModeWordWrap]autorelease]; +} + +// hAlignment, vAlignment ++ (id) labelWithString:(NSString*)string fontName:(NSString*)name fontSize:(CGFloat)size dimensions:(CGSize)dimensions hAlignment:(CCTextAlignment)alignment vAlignment:(CCVerticalTextAlignment) vertAlignment +{ + return [[[self alloc] initWithString:string fontName:name fontSize:size dimensions:dimensions hAlignment:alignment vAlignment:vertAlignment]autorelease]; +} + +// hAlignment, lineBreakMode ++ (id) labelWithString:(NSString*)string fontName:(NSString*)name fontSize:(CGFloat)size dimensions:(CGSize)dimensions hAlignment:(CCTextAlignment)alignment lineBreakMode:(CCLineBreakMode)lineBreakMode +{ + return [[[self alloc] initWithString:string fontName:name fontSize:size dimensions:dimensions hAlignment:alignment vAlignment:kCCVerticalTextAlignmentTop lineBreakMode:lineBreakMode]autorelease]; +} + +// hAlignment, vAlignment, lineBreakMode ++ (id) labelWithString:(NSString*)string fontName:(NSString*)name fontSize:(CGFloat)size dimensions:(CGSize)dimensions hAlignment:(CCTextAlignment)alignment vAlignment:(CCVerticalTextAlignment) vertAlignment lineBreakMode:(CCLineBreakMode)lineBreakMode +{ + return [[[self alloc] initWithString:string fontName:name fontSize:size dimensions:dimensions hAlignment:alignment vAlignment:vertAlignment lineBreakMode:lineBreakMode]autorelease]; +} + +- (id) init +{ + return [self initWithString:@"" fontName:@"Helvetica" fontSize:12]; +} + +- (id) initWithString:(NSString*)str fontName:(NSString*)name fontSize:(CGFloat)size +{ + return [self initWithString:str fontName:name fontSize:size dimensions:CGSizeZero hAlignment:kCCTextAlignmentLeft vAlignment:kCCVerticalTextAlignmentTop lineBreakMode:kCCLineBreakModeWordWrap]; +} + +// hAlignment +- (id) initWithString:(NSString*)str fontName:(NSString*)name fontSize:(CGFloat)size dimensions:(CGSize)dimensions hAlignment:(CCTextAlignment)alignment +{ + return [self initWithString:str fontName:name fontSize:size dimensions:dimensions hAlignment:alignment vAlignment:kCCVerticalTextAlignmentTop lineBreakMode:kCCLineBreakModeWordWrap]; +} + +// hAlignment, vAlignment +- (id) initWithString:(NSString*)str fontName:(NSString*)name fontSize:(CGFloat)size dimensions:(CGSize)dimensions hAlignment:(CCTextAlignment)alignment vAlignment:(CCVerticalTextAlignment) vertAlignment +{ + return [self initWithString:str fontName:name fontSize:size dimensions:dimensions hAlignment:alignment vAlignment:vertAlignment lineBreakMode:kCCLineBreakModeWordWrap]; +} + +// hAlignment, lineBreakMode +- (id) initWithString:(NSString*)str fontName:(NSString*)name fontSize:(CGFloat)size dimensions:(CGSize)dimensions hAlignment:(CCTextAlignment)alignment lineBreakMode:(CCLineBreakMode)lineBreakMode +{ + return [self initWithString:str fontName:name fontSize:size dimensions:dimensions hAlignment:alignment vAlignment:kCCVerticalTextAlignmentTop lineBreakMode:lineBreakMode]; +} + +// hAlignment, vAligment, lineBreakMode +- (id) initWithString:(NSString*)str fontName:(NSString*)name fontSize:(CGFloat)size dimensions:(CGSize)dimensions hAlignment:(CCTextAlignment)alignment vAlignment:(CCVerticalTextAlignment) vertAlignment lineBreakMode:(CCLineBreakMode)lineBreakMode +{ + if( (self=[super init]) ) { + + // shader program + self.shaderProgram = [[CCShaderCache sharedShaderCache] programForKey:SHADER_PROGRAM]; + + _dimensions = dimensions; + _hAlignment = alignment; + _vAlignment = vertAlignment; + _fontName = [[self getFontName: name] copy]; + _fontSize = size; + _lineBreakMode = lineBreakMode; + + [self setString:str]; + } + return self; +} + +- (void) setString:(NSString*)str +{ + NSAssert( str, @"Invalid string" ); + + if( _string.hash != str.hash ) { + [_string release]; + _string = [str copy]; + + [self updateTexture]; + } +} + +-(NSString*) string +{ + return _string; +} + +- (NSString*) getFontName:(NSString*)fontName +{ + // Custom .ttf file ? + if ([[fontName lowercaseString] hasSuffix:@".ttf"]) + { + // This is a file, register font with font manager + NSString* fontFile = [[CCFileUtils sharedFileUtils] fullPathForFilename:fontName]; + NSURL* fontURL = [NSURL fileURLWithPath:fontFile]; + CTFontManagerRegisterFontsForURL((CFURLRef)fontURL, kCTFontManagerScopeProcess, NULL); + + return [[fontFile lastPathComponent] stringByDeletingPathExtension]; + } + + return fontName; +} + +- (void)setFontName:(NSString*)fontName +{ + fontName = [self getFontName:fontName]; + + if( fontName.hash != _fontName.hash ) { + [_fontName release]; + _fontName = [fontName copy]; + + // Force update + if( _string ) + [self updateTexture]; + } +} + +- (NSString*)fontName +{ + return _fontName; +} + +- (void) setFontSize:(float)fontSize +{ + if( fontSize != _fontSize ) { + _fontSize = fontSize; + + // Force update + if( _string ) + [self updateTexture]; + } +} + +- (float) fontSize +{ + return _fontSize; +} + +-(void) setDimensions:(CGSize) dim +{ + if( dim.width != _dimensions.width || dim.height != _dimensions.height) + { + _dimensions = dim; + + // Force update + if( _string ) + [self updateTexture]; + } +} + +-(CGSize) dimensions +{ + return _dimensions; +} + +-(void) setHorizontalAlignment:(CCTextAlignment)alignment +{ + if (alignment != _hAlignment) + { + _hAlignment = alignment; + + // Force update + if( _string ) + [self updateTexture]; + + } +} + +- (CCTextAlignment) horizontalAlignment +{ + return _hAlignment; +} + +-(void) setVerticalAlignment:(CCVerticalTextAlignment)verticalAlignment +{ + if (_vAlignment != verticalAlignment) + { + _vAlignment = verticalAlignment; + + // Force update + if( _string ) + [self updateTexture]; + } +} + +- (CCVerticalTextAlignment) verticalAlignment +{ + return _vAlignment; +} + +- (void) dealloc +{ + [_string release]; + [_fontName release]; + + [super dealloc]; +} + +- (NSString*) description +{ + // XXX: _string, _fontName can't be displayed here, since they might be already released + + return [NSString stringWithFormat:@"<%@ = %p | FontSize = %.1f>", [self class], self, _fontSize]; +} + +// Helper +- (BOOL) updateTexture +{ + CCTexture2D *tex; + + if ( _shadowEnabled || _strokeEnabled ) + { + CCFontDefinition *tempDef = [self prepareFontDefinitionAndAdjustForResolution:true]; + tex = [[CCTexture2D alloc ]initWithString:_string fontDef:tempDef]; + } + else + { + if( _dimensions.width == 0 || _dimensions.height == 0 ) + tex = [[CCTexture2D alloc] initWithString:_string + fontName:_fontName + fontSize:_fontSize * CC_CONTENT_SCALE_FACTOR()]; + else + tex = [[CCTexture2D alloc] initWithString:_string + fontName:_fontName + fontSize:_fontSize * CC_CONTENT_SCALE_FACTOR() + dimensions:CC_SIZE_POINTS_TO_PIXELS(_dimensions) + hAlignment:_hAlignment + vAlignment:_vAlignment + lineBreakMode:_lineBreakMode + ]; + } + + if( !tex ) + return NO; + +#ifdef __CC_PLATFORM_IOS + // iPad ? + if( UI_USER_INTERFACE_IDIOM() == UIUserInterfaceIdiomPad ) { + if( CC_CONTENT_SCALE_FACTOR() == 2 ) + [tex setResolutionType:kCCResolutioniPadRetinaDisplay]; + else + [tex setResolutionType:kCCResolutioniPad]; + } + // iPhone ? + else + { + if( CC_CONTENT_SCALE_FACTOR() == 2 ) + [tex setResolutionType:kCCResolutioniPhoneRetinaDisplay]; + else + [tex setResolutionType:kCCResolutioniPhone]; + } +#endif + + [self setTexture:tex]; + [tex release]; + + CGRect rect = CGRectZero; + rect.size = [_texture contentSize]; + [self setTextureRect: rect]; + + return YES; +} + +/** init the label with string and text definition*/ +- (id) initWithString:(NSString *) string fontDefinition:(CCFontDefinition *)definition +{ + if( (self=[super init]) ) { + + // shader program + self.shaderProgram = [[CCShaderCache sharedShaderCache] programForKey:SHADER_PROGRAM]; + + _dimensions = definition.dimensions; + _hAlignment = definition.alignment; + _vAlignment = definition.vertAlignment; + _fontName = [definition.fontName copy]; + _fontSize = definition.fontSize; + _lineBreakMode = definition.lineBreakMode; + + // take care of shadow + if ([definition shadowEnabled]) + { + [self enableShadowWithOffset:[definition shadowOffset] opacity:0.5 blur:[definition shadowBlur] updateImage: false]; + } + else + { + [self disableShadowAndUpdateImage:false]; + } + + // take care of stroke + if ([definition strokeEnabled]) + { + [self enableStrokeWithColor:[definition strokeColor] size:[definition strokeSize] updateImage:false]; + } + else + { + [self disableStrokeAndUpdateImage:false]; + } + + + [self setFontFillColor: definition.fontFillColor updateImage:false]; + + + // actually update the string + [self setString:string]; + } + + return self; +} + + +/** enable or disable shadow for the label */ +- (void) enableShadowWithOffset:(CGSize)shadowOffset opacity:(float)shadowOpacity blur:(float)shadowBlur updateImage:(Boolean) mustUpdate +{ + bool valueChanged = false; + + if (false == _shadowEnabled) + { + _shadowEnabled = true; + valueChanged = true; + } + + if ( (_shadowOffset.width != shadowOffset.width) || (_shadowOffset.height!=shadowOffset.height) ) + { + _shadowOffset.width = shadowOffset.width; + _shadowOffset.height = shadowOffset.height; + + valueChanged = true; + } + + if (_shadowOpacity != shadowOpacity ) + { + _shadowOpacity = shadowOpacity; + valueChanged = true; + } + + if (_shadowBlur != shadowBlur) + { + _shadowBlur = shadowBlur; + valueChanged = true; + } + + if ( valueChanged && mustUpdate ) + { + [self updateTexture]; + } +} + +/** disable shadow rendering */ +- (void) disableShadowAndUpdateImage:(Boolean)mustUpdate +{ + if (_shadowEnabled) + { + _shadowEnabled = false; + + if ( mustUpdate ) + { + [self updateTexture]; + } + } +} + +/** enable or disable stroke */ +- (void) enableStrokeWithColor:(ccColor3B)strokeColor size:(float)strokeSize updateImage:(Boolean) mustUpdate +{ + bool valueChanged = false; + + if(_strokeEnabled == false) + { + _strokeEnabled = true; + valueChanged = true; + } + + if ( (_strokeColor.r != strokeColor.r) || (_strokeColor.g != strokeColor.g) || (_strokeColor.b != strokeColor.b) ) + { + _strokeColor = strokeColor; + valueChanged = true; + } + + if (_strokeSize!=strokeSize) + { + _strokeSize = strokeSize; + valueChanged = true; + } + + if ( valueChanged && mustUpdate ) + { + [self updateTexture]; + } + +} + +/** disable stroke */ +- (void) disableStrokeAndUpdateImage:(Boolean) mustUpdate +{ + + if ( _strokeEnabled ) + { + _strokeEnabled = false; + + if ( mustUpdate ) + { + [self updateTexture]; + } + } +} + +/** set fill color */ +- (void) setFontFillColor:(ccColor3B) tintColor updateImage:(Boolean) mustUpdate +{ + if (_textFillColor.r != tintColor.r || _textFillColor.g != tintColor.g || _textFillColor.b != tintColor.b) + { + _textFillColor = tintColor; + + if (mustUpdate) + { + [self updateTexture]; + } + } +} + +- (CCFontDefinition*) prepareFontDefinitionAndAdjustForResolution:(Boolean) resAdjust +{ + int tempFontSize = 0; + + if (resAdjust) + tempFontSize = _fontSize * CC_CONTENT_SCALE_FACTOR(); + else + tempFontSize = _fontSize; + + CCFontDefinition *retDefinition = [[CCFontDefinition alloc]initWithFontName:_fontName fontSize:tempFontSize]; + + if (retDefinition) + { + + [retDefinition autorelease]; + + retDefinition.lineBreakMode = _lineBreakMode; + retDefinition.alignment = _hAlignment; + retDefinition.vertAlignment = _vAlignment; + retDefinition.lineBreakMode = _lineBreakMode; + retDefinition.fontFillColor = _textFillColor; + + + // stroke + if ( _strokeEnabled ) + { + [retDefinition enableStroke: true]; + [retDefinition setStrokeColor: _strokeColor]; + + if (resAdjust) + [retDefinition setStrokeSize: _strokeSize * CC_CONTENT_SCALE_FACTOR()]; + else + [retDefinition setStrokeSize: _strokeSize]; + } + else + { + [retDefinition enableStroke: false]; + } + + + // shadow + if ( _shadowEnabled ) + { + [retDefinition enableShadow:true]; + [retDefinition setShadowBlur:_shadowBlur]; + + if (resAdjust) + { + [retDefinition setShadowOffset: CC_SIZE_POINTS_TO_PIXELS(_shadowOffset)]; + } + else + { + [retDefinition setShadowOffset: _shadowOffset]; + } + } + else + { + [retDefinition enableShadow:false]; + } + } + + return retDefinition; +} + +- (CCFontDefinition *) getFontDefinition +{ + return [self prepareFontDefinitionAndAdjustForResolution:false]; +} + +- (void) setFontDefinition: (CCFontDefinition *) fontDef +{ + if(_fontName) + { + [_fontName release]; + } + + _dimensions = fontDef.dimensions; + _hAlignment = fontDef.alignment; + _vAlignment = fontDef.vertAlignment; + _fontName = [fontDef.fontName copy]; + _fontSize = fontDef.fontSize; + _lineBreakMode = fontDef.lineBreakMode; + + // take care of shadow + if ([fontDef shadowEnabled]) + { + [self enableShadowWithOffset:[fontDef shadowOffset] opacity:0.5 blur:[fontDef shadowBlur] updateImage: false]; + } + else + { + [self disableShadowAndUpdateImage:false]; + } + + // take care of stroke + if ([fontDef strokeEnabled]) + { + [self enableStrokeWithColor:[fontDef strokeColor] size:[fontDef strokeSize] updateImage:false]; + } + else + { + [self disableStrokeAndUpdateImage:false]; + } + + + [self setFontFillColor: fontDef.fontFillColor updateImage:false]; + + + // actually update the texture + [self updateTexture]; +} + +@end diff --git "a/21451198\345\215\242\350\266\205/project5/MyPlane/libs/cocos2d/CCLayer.h" "b/21451198\345\215\242\350\266\205/project5/MyPlane/libs/cocos2d/CCLayer.h" new file mode 100644 index 00000000..cf1c359b --- /dev/null +++ "b/21451198\345\215\242\350\266\205/project5/MyPlane/libs/cocos2d/CCLayer.h" @@ -0,0 +1,308 @@ +/* + * cocos2d for iPhone: http://www.cocos2d-iphone.org + * + * Copyright (c) 2008-2010 Ricardo Quesada + * Copyright (c) 2011 Zynga Inc. + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + * THE SOFTWARE. + * + */ + + + +#import "ccMacros.h" + +#ifdef __CC_PLATFORM_IOS +#import // Needed for UIAccelerometerDelegate +#import "Platforms/iOS/CCTouchDelegateProtocol.h" // Touches only supported on iOS +#elif defined(__CC_PLATFORM_MAC) +#import "Platforms/Mac/CCEventDispatcher.h" +#endif + +#import "CCProtocols.h" +#import "CCNode.h" + +#pragma mark - CCLayer + +typedef enum { + kCCTouchesAllAtOnce, + kCCTouchesOneByOne, +} ccTouchesMode; + +/** CCLayer is a subclass of CCNode that implements the CCTouchEventsDelegate protocol. + + All features from CCNode are valid, plus the following new features: + - It can receive Touches both on iOS and Mac + - It can receive Accelerometer input on iOS + - It can receive Keyboard events on Mac + - It can receive Mouse events on Mac +*/ +#ifdef __CC_PLATFORM_IOS +@interface CCLayer : CCNode +{ + BOOL _touchEnabled; + NSInteger _touchPriority; + BOOL _touchMode; + BOOL _touchSwallow; + + BOOL _accelerometerEnabled; +} + +/** whether or not it will receive Accelerometer events + You can enable / disable accelerometer events with this property. + + Valid only on iOS. Not valid on Mac. + + @since v0.8.1 + */ +@property(nonatomic, assign, getter = isAccelerometerEnabled) BOOL accelerometerEnabled; + +/** whether or not it will receive Touch events + @since v0.8.1 + */ +@property(nonatomic, assign, getter = isTouchEnabled) BOOL touchEnabled; +/** priority of the touch events. Default is 0 */ +@property(nonatomic, assign) NSInteger touchPriority; +/** Touch modes. + - kCCTouchesAllAtOnce: Receives all the available touches at once. + - kCCTouchesOneByOne: Receives one touch at the time. + */ +@property(nonatomic, assign) ccTouchesMode touchMode; + +/** whether touch events are swallowed (in kCCTouchesOneByOne mode) */ +@property(nonatomic, assign) BOOL touchSwallow; + +/** sets the accelerometer's update frequency. A value of 1/2 means that the callback is going to be called twice per second. + @since v2.1 + */ +-(void) setAccelerometerInterval:(float)interval; + + +#elif defined(__CC_PLATFORM_MAC) + + +@interface CCLayer : CCNode +{ + BOOL _mouseEnabled; + NSInteger _mousePriority; + + BOOL _keyboardEnabled; + NSInteger _keyboardPriority; + + BOOL _touchEnabled; + NSInteger _touchPriority; + NSInteger _touchMode; + BOOL _touchSwallow; + + BOOL _gestureEnabled; + NSInteger _gesturePriority; +} + +/** whether or not it will receive touche events. */ +@property (nonatomic, readwrite, getter=isTouchEnabled) BOOL touchEnabled; +/** priority of the touch events. Default is 0 */ +@property(nonatomic, assign) NSInteger touchPriority; + +/** whether or not it will receive gesture events. */ +@property (nonatomic, readwrite, getter=isGestureEnabled) BOOL gestureEnabled; +/** priority of the gesture events. Default is 0 */ +@property(nonatomic, assign) NSInteger gesturePriority; + + +/** whether or not it will receive mouse events. + + Valid only on OS X. Not valid on iOS + */ +@property (nonatomic, readwrite, getter=isMouseEnabled) BOOL mouseEnabled; +/** priority of the mouse events. Default is 0 */ +@property (nonatomic, assign) NSInteger mousePriority; + +/** whether or not it will receive keyboard events. + + Valid only on OS X. Not valid on iOS + */ +@property (nonatomic, readwrite, getter = isKeyboardEnabled) BOOL keyboardEnabled; +/** Priority of keyboard events. Default is 0 */ +@property (nonatomic, assign) NSInteger keyboardPriority; + +#endif // mac + +@end + + +#pragma mark - +#pragma mark CCLayerRGBA + +/** CCLayerRGBA is a subclass of CCLayer that implements the CCRGBAProtocol protocol using a solid color as the background. + + All features from CCLayer are valid, plus the following new features that propagate into children that conform to the CCRGBAProtocol: + - opacity + - RGB colors + @since 2.1 + */ +@interface CCLayerRGBA : CCLayer +{ + GLubyte _displayedOpacity, _realOpacity; + ccColor3B _displayedColor, _realColor; + BOOL _cascadeOpacityEnabled, _cascadeColorEnabled; +} + +// XXX: To make BridgeSupport happy +-(GLubyte) opacity; +@end + + + +#pragma mark - +#pragma mark CCLayerColor + +/** CCLayerColor is a subclass of CCLayer that implements the CCRGBAProtocol protocol. + + All features from CCLayer are valid, plus the following new features: + - opacity + - RGB colors + */ +@interface CCLayerColor : CCLayerRGBA +{ + ccVertex2F _squareVertices[4]; + ccColor4F _squareColors[4]; + + ccBlendFunc _blendFunc; +} + +/** creates a CCLayer with color, width and height in Points*/ ++ (id) layerWithColor: (ccColor4B)color width:(GLfloat)w height:(GLfloat)h; +/** creates a CCLayer with color. Width and height are the window size. */ ++ (id) layerWithColor: (ccColor4B)color; + +/** initializes a CCLayer with color, width and height in Points. + This is the designated initializer. + */ +- (id) initWithColor:(ccColor4B)color width:(GLfloat)w height:(GLfloat)h; +/** initializes a CCLayer with color. Width and height are the window size. */ +- (id) initWithColor:(ccColor4B)color; + +/** change width in Points */ +-(void) changeWidth: (GLfloat)w; +/** change height in Points */ +-(void) changeHeight: (GLfloat)h; +/** change width and height in Points + @since v0.8 + */ +-(void) changeWidth:(GLfloat)w height:(GLfloat)h; + +/** BlendFunction. Conforms to CCBlendProtocol protocol */ +@property (nonatomic,readwrite) ccBlendFunc blendFunc; +@end + +#pragma mark - +#pragma mark CCLayerGradient + +/** CCLayerGradient is a subclass of CCLayerColor that draws gradients across +the background. + + All features from CCLayerColor are valid, plus the following new features: + - direction + - final color + - interpolation mode + + Color is interpolated between the startColor and endColor along the given + vector (starting at the origin, ending at the terminus). If no vector is + supplied, it defaults to (0, -1) -- a fade from top to bottom. + + If 'compressedInterpolation' is disabled, you will not see either the start or end color for + non-cardinal vectors; a smooth gradient implying both end points will be still + be drawn, however. + + If ' compressedInterpolation' is enabled (default mode) you will see both the start and end colors of the gradient. + + @since v0.99.5 + */ +@interface CCLayerGradient : CCLayerColor +{ + ccColor3B _endColor; + GLubyte _startOpacity; + GLubyte _endOpacity; + CGPoint _vector; + BOOL _compressedInterpolation; +} + +/** Creates a full-screen CCLayer with a gradient between start and end. */ ++ (id) layerWithColor: (ccColor4B) start fadingTo: (ccColor4B) end; +/** Creates a full-screen CCLayer with a gradient between start and end in the direction of v. */ ++ (id) layerWithColor: (ccColor4B) start fadingTo: (ccColor4B) end alongVector: (CGPoint) v; + +/** Initializes the CCLayer with a gradient between start and end. */ +- (id) initWithColor: (ccColor4B) start fadingTo: (ccColor4B) end; +/** Initializes the CCLayer with a gradient between start and end in the direction of v. */ +- (id) initWithColor: (ccColor4B) start fadingTo: (ccColor4B) end alongVector: (CGPoint) v; + +/** The starting color. */ +@property (nonatomic, readwrite) ccColor3B startColor; +/** The ending color. */ +@property (nonatomic, readwrite) ccColor3B endColor; +/** The starting opacity. */ +@property (nonatomic, readwrite) GLubyte startOpacity; +/** The ending color. */ +@property (nonatomic, readwrite) GLubyte endOpacity; +/** The vector along which to fade color. */ +@property (nonatomic, readwrite) CGPoint vector; +/** Whether or not the interpolation will be compressed in order to display all the colors of the gradient both in canonical and non canonical vectors + Default: YES + */ +@property (nonatomic, readwrite) BOOL compressedInterpolation; + +@end + +#pragma mark - +#pragma mark CCLayerMultiplex + +/** CCLayerMultiplex is a CCLayer with the ability to multiplex its children. + Features: + - It supports one or more children + - Only one children will be active a time + */ +@interface CCLayerMultiplex : CCLayer +{ + unsigned int _enabledLayer; + NSMutableArray *_layers; +} + +/** creates a CCMultiplexLayer with an array of layers. + @since v2.1 + */ ++(id) layerWithArray:(NSArray*)arrayOfLayers; +/** creates a CCMultiplexLayer with one or more layers using a variable argument list. */ ++(id) layerWithLayers: (CCLayer*) layer, ... NS_REQUIRES_NIL_TERMINATION; +/** initializes a CCMultiplexLayer with an array of layers + @since v2.1 + */ +-(id) initWithArray:(NSArray*)arrayOfLayers; +/** initializes a MultiplexLayer with one or more layers using a variable argument list. */ +-(id) initWithLayers: (CCLayer*) layer vaList:(va_list) params; +/** switches to a certain layer indexed by n. + The current (old) layer will be removed from its parent with 'cleanup:YES'. + */ +-(void) switchTo: (unsigned int) n; +/** release the current layer and switches to another layer indexed by n. + The current (old) layer will be removed from its parent with 'cleanup:YES'. + */ +-(void) switchToAndReleaseMe: (unsigned int) n; +@end + diff --git "a/21451198\345\215\242\350\266\205/project5/MyPlane/libs/cocos2d/CCLayer.m" "b/21451198\345\215\242\350\266\205/project5/MyPlane/libs/cocos2d/CCLayer.m" new file mode 100644 index 00000000..36158b0c --- /dev/null +++ "b/21451198\345\215\242\350\266\205/project5/MyPlane/libs/cocos2d/CCLayer.m" @@ -0,0 +1,890 @@ +/* + * cocos2d for iPhone: http://www.cocos2d-iphone.org + * + * Copyright (c) 2008-2010 Ricardo Quesada + * Copyright (c) 2011 Zynga Inc. + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + * THE SOFTWARE. + * + */ + + +#import + +#import "Platforms/CCGL.h" + +#import "CCLayer.h" +#import "CCDirector.h" +#import "ccMacros.h" +#import "CCShaderCache.h" +#import "CCGLProgram.h" +#import "ccGLStateCache.h" +#import "Support/TransformUtils.h" +#import "Support/CGPointExtension.h" + +#ifdef __CC_PLATFORM_IOS +#import "Platforms/iOS/CCTouchDispatcher.h" +#import "Platforms/iOS/CCDirectorIOS.h" +#elif defined(__CC_PLATFORM_MAC) +#import "Platforms/Mac/CCEventDispatcher.h" +#import "Platforms/Mac/CCDirectorMac.h" +#endif + +// extern +#import "kazmath/GL/matrix.h" + +#pragma mark - +#pragma mark Layer + +#if __CC_PLATFORM_IOS +@interface CCLayer () +-(void) registerWithTouchDispatcher; +@end +#endif // __CC_PLATFORM_IOS + +@implementation CCLayer + +#pragma mark Layer - Init +-(id) init +{ + if( (self=[super init]) ) { + + CGSize s = [[CCDirector sharedDirector] winSize]; + _anchorPoint = ccp(0.5f, 0.5f); + [self setContentSize:s]; + self.ignoreAnchorPointForPosition = YES; + + _touchEnabled = NO; + _touchPriority = 0; + _touchMode = kCCTouchesAllAtOnce; + _touchSwallow = YES; + +#ifdef __CC_PLATFORM_IOS + _accelerometerEnabled = NO; +#elif defined(__CC_PLATFORM_MAC) + _gestureEnabled = NO; + _gesturePriority = 0; + _mouseEnabled = NO; + _keyboardEnabled = NO; +#endif + } + + return self; +} + +#pragma mark Layer - iOS - Touch and Accelerometer related + +#ifdef __CC_PLATFORM_IOS +-(void) registerWithTouchDispatcher +{ + CCDirector *director = [CCDirector sharedDirector]; + + if( _touchMode == kCCTouchesAllAtOnce ) + [[director touchDispatcher] addStandardDelegate:self priority:_touchPriority]; + else /* one by one */ + [[director touchDispatcher] addTargetedDelegate:self priority:_touchPriority swallowsTouches:_touchSwallow]; +} + +-(BOOL) isAccelerometerEnabled +{ + return _accelerometerEnabled; +} + +-(void) setAccelerometerEnabled:(BOOL)enabled +{ + if( enabled != _accelerometerEnabled ) { + _accelerometerEnabled = enabled; + if( _isRunning ) { + if( enabled ) + [[UIAccelerometer sharedAccelerometer] setDelegate:(id)self]; + else + [[UIAccelerometer sharedAccelerometer] setDelegate:nil]; + } + } +} + +-(void) setAccelerometerInterval:(float)interval +{ + [[UIAccelerometer sharedAccelerometer] setUpdateInterval:interval]; +} + +-(BOOL) isTouchEnabled +{ + return _touchEnabled; +} + +-(void) setTouchEnabled:(BOOL)enabled +{ + if( _touchEnabled != enabled ) { + _touchEnabled = enabled; + if( _isRunning) { + if( enabled ) + [self registerWithTouchDispatcher]; + else { + CCDirector *director = [CCDirector sharedDirector]; + [[director touchDispatcher] removeDelegate:self]; + } + } + } +} + +-(NSInteger) touchPriority +{ + return _touchPriority; +} +-(void) setTouchPriority:(NSInteger)touchPriority +{ + if( _touchPriority != touchPriority ) { + _touchPriority = touchPriority; + + if( _touchEnabled) { + [self setTouchEnabled:NO]; + [self setTouchEnabled:YES]; + } + } +} + +-(ccTouchesMode) touchMode +{ + return _touchMode; +} +-(void) setTouchMode:(ccTouchesMode)touchMode +{ + if( _touchMode != touchMode ) { + _touchMode = touchMode; + if( _touchEnabled) { + [self setTouchEnabled:NO]; + [self setTouchEnabled:YES]; + } + } +} + +-(BOOL) touchSwallow +{ + return _touchSwallow; +} +-(void) setTouchSwallow:(BOOL)touchSwallow +{ + if( _touchSwallow != touchSwallow ) { + _touchSwallow = touchSwallow; + if( _touchEnabled) { + [self setTouchEnabled:NO]; + [self setTouchEnabled:YES]; + } + } +} + +#elif defined(__CC_PLATFORM_MAC) + +#pragma mark CCLayer - OS X - Mouse, Keyboard & Touch events + + +-(BOOL) isMouseEnabled +{ + return _mouseEnabled; +} + +-(void) setMouseEnabled:(BOOL)enabled +{ + if( _mouseEnabled != enabled ) { + _mouseEnabled = enabled; + + if( _isRunning ) { + CCDirector *director = [CCDirector sharedDirector]; + if( enabled ) + [[director eventDispatcher] addMouseDelegate:self priority:_mousePriority]; + else + [[director eventDispatcher] removeMouseDelegate:self]; + } + } +} + +-(NSInteger) mousePriority +{ + return _mousePriority; +} + +-(void) setMousePriority:(NSInteger)mousePriority +{ + if( _mousePriority != mousePriority ) { + _mousePriority = mousePriority; + if( _mouseEnabled ) { + [self setMouseEnabled:NO]; + [self setMouseEnabled:YES]; + } + } +} + +-(BOOL) isKeyboardEnabled +{ + return _keyboardEnabled; +} + +-(void) setKeyboardEnabled:(BOOL)enabled +{ + if( _keyboardEnabled != enabled ) { + _keyboardEnabled = enabled; + + if( _isRunning ) { + CCDirector *director = [CCDirector sharedDirector]; + if( enabled ) + [[director eventDispatcher] addKeyboardDelegate:self priority:_keyboardPriority ]; + else + [[director eventDispatcher] removeKeyboardDelegate:self]; + } + } +} + +-(NSInteger) keyboardPriority +{ + return _keyboardPriority; +} + +-(void) setKeyboardPriority:(NSInteger)keyboardPriority +{ + if( _keyboardPriority != keyboardPriority ) { + _keyboardPriority = keyboardPriority; + if( _keyboardEnabled ) { + [self setKeyboardEnabled:NO]; + [self setKeyboardEnabled:YES]; + } + } +} + +-(BOOL) isTouchEnabled +{ + return _touchEnabled; +} + +-(void) setTouchEnabled:(BOOL)enabled +{ + if( _touchEnabled != enabled ) { + _touchEnabled = enabled; + if( _isRunning ) { + CCDirector *director = [CCDirector sharedDirector]; + if( enabled ) + [[director eventDispatcher] addTouchDelegate:self priority:_touchPriority]; + else + [[director eventDispatcher] removeTouchDelegate:self]; + } + } +} + +-(NSInteger) touchPriority +{ + return _touchPriority; +} +-(void) setTouchPriority:(NSInteger)touchPriority +{ + if( _touchPriority != touchPriority ) { + _touchPriority = touchPriority; + + if( _touchEnabled) { + [self setTouchEnabled:NO]; + [self setTouchEnabled:YES]; + } + } +} + +-(BOOL) isGestureEnabled +{ + return _gestureEnabled; +} + +-(void) setGestureEnabled:(BOOL)enabled +{ + if( _gestureEnabled != enabled ) { + _gestureEnabled = enabled; + if( _isRunning ) { + CCDirector *director = [CCDirector sharedDirector]; + if( enabled ) + [[director eventDispatcher] addGestureDelegate:self priority:_gesturePriority]; + else + [[director eventDispatcher] removeGestureDelegate:self]; + } + } +} + +-(NSInteger) gesturePriority +{ + return _gesturePriority; +} + +-(void) setGesturePriority:(NSInteger)gesturePriority +{ + if( _gesturePriority != gesturePriority ) { + _gesturePriority = gesturePriority; + + if( _gestureEnabled) { + [self setGestureEnabled:NO]; + [self setGestureEnabled:YES]; + } + } +} + +#endif // Mac + + +#pragma mark Layer - Callbacks +-(void) onEnter +{ +#ifdef __CC_PLATFORM_IOS + // register 'parent' nodes first + // since events are propagated in reverse order + if (_touchEnabled) + [self registerWithTouchDispatcher]; + +#elif defined(__CC_PLATFORM_MAC) + CCDirector *director = [CCDirector sharedDirector]; + CCEventDispatcher *eventDispatcher = [director eventDispatcher]; + + if( _mouseEnabled ) + [eventDispatcher addMouseDelegate:self priority:_mousePriority]; + + if( _keyboardEnabled) + [eventDispatcher addKeyboardDelegate:self priority:_keyboardPriority]; + + if( _touchEnabled) + [eventDispatcher addTouchDelegate:self priority:_touchPriority]; + + if( _gestureEnabled) + [eventDispatcher addGestureDelegate:self priority:_gesturePriority]; + +#endif + + // then iterate over all the children + [super onEnter]; +} + +// issue #624. +// Can't register mouse, touches here because of #issue #1018, and #1021 +-(void) onEnterTransitionDidFinish +{ +#ifdef __CC_PLATFORM_IOS + if( _accelerometerEnabled ) + [[UIAccelerometer sharedAccelerometer] setDelegate:(id)self]; +#endif + + [super onEnterTransitionDidFinish]; +} + + +-(void) onExit +{ + CCDirector *director = [CCDirector sharedDirector]; + +#ifdef __CC_PLATFORM_IOS + if( _touchEnabled ) + [[director touchDispatcher] removeDelegate:self]; + + if( _accelerometerEnabled ) + [[UIAccelerometer sharedAccelerometer] setDelegate:nil]; + +#elif defined(__CC_PLATFORM_MAC) + CCEventDispatcher *eventDispatcher = [director eventDispatcher]; + if( _mouseEnabled ) + [eventDispatcher removeMouseDelegate:self]; + + if( _keyboardEnabled ) + [eventDispatcher removeKeyboardDelegate:self]; + + if( _touchEnabled ) + [eventDispatcher removeTouchDelegate:self]; + + if( _gestureEnabled ) + [eventDispatcher removeGestureDelegate:self]; + +#endif + + [super onExit]; +} + +#ifdef __CC_PLATFORM_IOS +-(BOOL) ccTouchBegan:(UITouch *)touch withEvent:(UIEvent *)event +{ + NSAssert(NO, @"Layer#ccTouchBegan override me"); + return YES; +} +#endif +@end + + +#pragma mark - LayerRGBA + +@implementation CCLayerRGBA + +@synthesize cascadeColorEnabled = _cascadeColorEnabled; +@synthesize cascadeOpacityEnabled = _cascadeOpacityEnabled; + +-(id) init +{ + if ( (self=[super init]) ) { + _displayedOpacity = _realOpacity = 255; + _displayedColor = _realColor = ccWHITE; + self.cascadeOpacityEnabled = NO; + self.cascadeColorEnabled = NO; + } + return self; +} + +-(GLubyte) opacity +{ + return _realOpacity; +} + +-(GLubyte) displayedOpacity +{ + return _displayedOpacity; +} + +/** Override synthesized setOpacity to recurse items */ +- (void) setOpacity:(GLubyte)opacity +{ + _displayedOpacity = _realOpacity = opacity; + + if( _cascadeOpacityEnabled ) { + GLubyte parentOpacity = 255; + if( [_parent conformsToProtocol:@protocol(CCRGBAProtocol)] && [(id)_parent isCascadeOpacityEnabled] ) + parentOpacity = [(id)_parent displayedOpacity]; + [self updateDisplayedOpacity:parentOpacity]; + } +} + +-(ccColor3B) color +{ + return _realColor; +} + +-(ccColor3B) displayedColor +{ + return _displayedColor; +} + +- (void) setColor:(ccColor3B)color +{ + _displayedColor = _realColor = color; + + if( _cascadeColorEnabled ) { + ccColor3B parentColor = ccWHITE; + if( [_parent conformsToProtocol:@protocol(CCRGBAProtocol)] && [(id)_parent isCascadeColorEnabled] ) + parentColor = [(id)_parent displayedColor]; + [self updateDisplayedColor:parentColor]; + } +} + +- (void)updateDisplayedOpacity:(GLubyte)parentOpacity +{ + _displayedOpacity = _realOpacity * parentOpacity/255.0; + + if (_cascadeOpacityEnabled) { + id item; + CCARRAY_FOREACH(_children, item) { + if ([item conformsToProtocol:@protocol(CCRGBAProtocol)]) { + [item updateDisplayedOpacity:_displayedOpacity]; + } + } + } +} + +- (void)updateDisplayedColor:(ccColor3B)parentColor +{ + _displayedColor.r = _realColor.r * parentColor.r/255.0; + _displayedColor.g = _realColor.g * parentColor.g/255.0; + _displayedColor.b = _realColor.b * parentColor.b/255.0; + + if (_cascadeColorEnabled) { + id item; + CCARRAY_FOREACH(_children, item) { + if ([item conformsToProtocol:@protocol(CCRGBAProtocol)]) { + [item updateDisplayedColor:_displayedColor]; + } + } + } +} + +@end + + +#pragma mark - +#pragma mark LayerColor + +@interface CCLayerColor (Private) +-(void) updateColor; +@end + +@implementation CCLayerColor + +// Opacity and RGB color protocol +@synthesize blendFunc = _blendFunc; + + ++ (id) layerWithColor:(ccColor4B)color width:(GLfloat)w height:(GLfloat) h +{ + return [[[self alloc] initWithColor:color width:w height:h] autorelease]; +} + ++ (id) layerWithColor:(ccColor4B)color +{ + return [[(CCLayerColor*)[self alloc] initWithColor:color] autorelease]; +} + +-(id) init +{ + CGSize s = [[CCDirector sharedDirector] winSize]; + return [self initWithColor:ccc4(0,0,0,0) width:s.width height:s.height]; +} + +// Designated initializer +- (id) initWithColor:(ccColor4B)color width:(GLfloat)w height:(GLfloat) h +{ + if( (self=[super init]) ) { + + // default blend function + _blendFunc = (ccBlendFunc) { GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA }; + + _displayedColor.r = _realColor.r = color.r; + _displayedColor.g = _realColor.g = color.g; + _displayedColor.b = _realColor.b = color.b; + _displayedOpacity = _realOpacity = color.a; + + for (NSUInteger i = 0; i= rowColumns) { + height += rowHeight + 5; + + columnsOccupied = 0; + rowHeight = 0; + ++row; + } + } + NSAssert( !columnsOccupied, @"Too many rows/columns for available menu items." ); + + CGSize winSize = [[CCDirector sharedDirector] winSize]; + + row = 0; rowHeight = 0; rowColumns = 0; + float w, x, y = height / 2; + CCARRAY_FOREACH(_children, item) { + if(rowColumns == 0) { + rowColumns = [(NSNumber *) [rows objectAtIndex:row] unsignedIntegerValue]; + w = winSize.width / (1 + rowColumns); + x = w; + } + + CGSize itemSize = item.contentSize; + rowHeight = fmaxf(rowHeight, itemSize.height); + [item setPosition:ccp(x - winSize.width / 2, + y - itemSize.height / 2)]; + + x += w; + ++columnsOccupied; + + if(columnsOccupied >= rowColumns) { + y -= rowHeight + 5; + + columnsOccupied = 0; + rowColumns = 0; + rowHeight = 0; + ++row; + } + } +} + +-(void) alignItemsInRows: (NSNumber *) rows, ... +{ + va_list args; + va_start(args, rows); + + [self alignItemsInRows:rows vaList:args]; + + va_end(args); +} + +-(void) alignItemsInRows: (NSNumber *) rows vaList: (va_list) args +{ + NSMutableArray *columns = [[NSMutableArray alloc] initWithObjects:rows, nil]; + rows = va_arg(args, NSNumber*); + while(rows) { + [columns addObject:rows]; + rows = va_arg(args, NSNumber*); + } + + [self alignItemsInRowsWithArray:columns]; + + [columns release]; +} + +-(void) alignItemsInRowsWithArray:(NSArray*) columns +{ + NSMutableArray *columnWidths = [[NSMutableArray alloc] init]; + NSMutableArray *columnHeights = [[NSMutableArray alloc] init]; + + int width = -10, columnHeight = -5; + NSUInteger column = 0, columnWidth = 0, rowsOccupied = 0, columnRows; + CCMenuItem *item; + CCARRAY_FOREACH(_children, item){ + NSAssert( column < [columns count], @"Too many menu items for the amount of rows/columns."); + + columnRows = [(NSNumber *) [columns objectAtIndex:column] unsignedIntegerValue]; + NSAssert( columnRows, @"Can't have zero rows on a column"); + + CGSize itemSize = item.contentSize; + columnWidth = fmaxf(columnWidth, itemSize.width); + columnHeight += itemSize.height + 5; + ++rowsOccupied; + + if(rowsOccupied >= columnRows) { + [columnWidths addObject:[NSNumber numberWithUnsignedInteger:columnWidth]]; + [columnHeights addObject:[NSNumber numberWithUnsignedInteger:columnHeight]]; + width += columnWidth + 10; + + rowsOccupied = 0; + columnWidth = 0; + columnHeight = -5; + ++column; + } + } + NSAssert( !rowsOccupied, @"Too many rows/columns for available menu items."); + + CGSize winSize = [[CCDirector sharedDirector] winSize]; + + column = 0; columnWidth = 0; columnRows = 0; + float x = -width / 2, y; + + CCARRAY_FOREACH(_children, item){ + if(columnRows == 0) { + columnRows = [(NSNumber *) [columns objectAtIndex:column] unsignedIntegerValue]; + y = ([(NSNumber *) [columnHeights objectAtIndex:column] intValue] + winSize.height) / 2; + } + + CGSize itemSize = item.contentSize; + columnWidth = fmaxf(columnWidth, itemSize.width); + [item setPosition:ccp(x + [(NSNumber *) [columnWidths objectAtIndex:column] unsignedIntegerValue] / 2, + y - winSize.height / 2)]; + + y -= itemSize.height + 10; + ++rowsOccupied; + + if(rowsOccupied >= columnRows) { + x += columnWidth + 5; + + rowsOccupied = 0; + columnRows = 0; + columnWidth = 0; + ++column; + } + } + + [columnWidths release]; + [columnHeights release]; +} +@end diff --git "a/21451198\345\215\242\350\266\205/project5/MyPlane/libs/cocos2d/CCMenuItem.h" "b/21451198\345\215\242\350\266\205/project5/MyPlane/libs/cocos2d/CCMenuItem.h" new file mode 100644 index 00000000..112a7078 --- /dev/null +++ "b/21451198\345\215\242\350\266\205/project5/MyPlane/libs/cocos2d/CCMenuItem.h" @@ -0,0 +1,429 @@ +/* + * cocos2d for iPhone: http://www.cocos2d-iphone.org + * + * Copyright (c) 2008-2011 Ricardo Quesada + * Copyright (c) 2011 Zynga Inc. + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + * THE SOFTWARE. + * + */ + +#import "CCNode.h" +#import "CCProtocols.h" + +@class CCSprite; +@class CCSpriteFrame; + +#define kCCItemSize 32 + +#pragma mark - +#pragma mark CCMenuItem +/** CCMenuItem base class + * + * Subclass CCMenuItem (or any subclass) to create your custom CCMenuItem objects. + */ +@interface CCMenuItem : CCNodeRGBA +{ + // used for menu items using a block + void (^_block)(id sender); + + BOOL _isEnabled; + BOOL _isSelected; + + BOOL _releaseBlockAtCleanup; + CGRect _activeArea; +} + +/** returns whether or not the item is selected +@since v0.8.2 +*/ +@property (nonatomic,readonly) BOOL isSelected; + +/** If enabled, it releases the block at cleanup time. + @since v2.1 + */ +@property (nonatomic) BOOL releaseBlockAtCleanup; + +/** the active area (relative to the current position) */ +@property (nonatomic,assign) CGRect activeArea; + +/** Creates a CCMenuItem with a target/selector. + target/selector will be implemented using blocks. + "target" won't be retained. + */ ++(id) itemWithTarget:(id)target selector:(SEL)selector; + +/** Creates a CCMenuItem with the specified block. + The block will be "copied". + */ ++(id) itemWithBlock:(void(^)(id sender))block; + +/** Initializes a CCMenuItem with a target/selector */ +-(id) initWithTarget:(id)target selector:(SEL)selector; + +/** Initializes a CCMenuItem with the specified block. + The block will be "copied". +*/ +-(id) initWithBlock:(void(^)(id sender))block; + +/** Activate the item */ +-(void) activate; + +/** The item was selected (not activated), similar to "mouse-over" */ +-(void) selected; + +/** The item was unselected */ +-(void) unselected; + +/** Enable or disabled the CCMenuItem */ +-(void) setIsEnabled:(BOOL)enabled; + +/** Returns whether or not the CCMenuItem is enabled */ +-(BOOL) isEnabled; + +/** Sets the block that is called when the item is tapped. + The block will be "copied". + */ +-(void) setBlock:(void(^)(id sender))block; + +/** Sets the target and selector that is called when the item is tapped. + target/selector will be implemented using blocks. + "target" won't be retained. + */ +-(void) setTarget:(id)target selector:(SEL)selector; + +/** cleanup event. It will release the block and call [super cleanup] */ +-(void) cleanup; + +@end + +#pragma mark - +#pragma mark CCMenuItemLabel + +/** An abstract class for "label" CCMenuItemLabel items + Any CCNode that supports the CCLabelProtocol protocol can be added. + Supported nodes: + - CCLabelBMFont + - CCLabelAtlas + - CCLabelTTF + */ +@interface CCMenuItemLabel : CCMenuItem +{ + CCNode *_label; + ccColor3B _colorBackup; + ccColor3B _disabledColor; + float _originalScale; +} + +/** the color that will be used to disable the item */ +@property (nonatomic,readwrite) ccColor3B disabledColor; + +/** Label that is rendered. It can be any CCNode that implements the CCLabelProtocol */ +@property (nonatomic,readwrite,assign) CCNode* label; + +/** creates a CCMenuItemLabel with a Label. */ ++(id) itemWithLabel:(CCNode*)label; + +/** creates a CCMenuItemLabel with a Label, target and selector. + The "target" won't be retained. + */ ++(id) itemWithLabel:(CCNode*)label target:(id)target selector:(SEL)selector; + +/** creates a CCMenuItemLabel with a Label and a block to execute. + The block will be "copied". + */ ++(id) itemWithLabel:(CCNode*)label block:(void(^)(id sender))block; + +/** initializes a CCMenuItemLabel with a Label, target and selector. + Internally it will create a block that executes the target/selector. + The "target" won't be retained. + */ +-(id) initWithLabel:(CCNode*)label target:(id)target selector:(SEL)selector; + +/** initializes a CCMenuItemLabel with a Label and a block to execute. + The block will be "copied". + This is the designated initializer. + */ +-(id) initWithLabel:(CCNode*)label block:(void(^)(id sender))block; + +/** sets a new string to the inner label */ +-(void) setString:(NSString*)label; + +/** Enable or disabled the CCMenuItemFont + @warning setIsEnabled changes the RGB color of the font + */ +-(void) setIsEnabled: (BOOL)enabled; +@end + +#pragma mark - +#pragma mark CCMenuItemAtlasFont + +/** A CCMenuItemAtlasFont + Helper class that creates a CCMenuItemLabel class with a CCLabelAtlas + */ +@interface CCMenuItemAtlasFont : CCMenuItemLabel +{ +} + +/** creates a menu item from a string and atlas with a target/selector */ ++(id) itemWithString: (NSString*) value charMapFile:(NSString*) charMapFile itemWidth:(int)itemWidth itemHeight:(int)itemHeight startCharMap:(char)startCharMap; + +/** creates a menu item from a string and atlas. Use it with CCMenuItemToggle. + The "target" won't be retained. + */ ++(id) itemWithString: (NSString*) value charMapFile:(NSString*) charMapFile itemWidth:(int)itemWidth itemHeight:(int)itemHeight startCharMap:(char)startCharMap target:(id)target selector:(SEL)selector; + +/** initializes a menu item from a string and atlas with a target/selector. + The "target" won't be retained. + */ +-(id) initWithString: (NSString*) value charMapFile:(NSString*) charMapFile itemWidth:(int)itemWidth itemHeight:(int)itemHeight startCharMap:(char)startCharMap target:(id)target selector:(SEL)selector; + +/** creates a menu item from a string and atlas. Use it with CCMenuItemToggle. + The block will be "copied". + */ ++(id) itemWithString: (NSString*) value charMapFile:(NSString*) charMapFile itemWidth:(int)itemWidth itemHeight:(int)itemHeight startCharMap:(char)startCharMap block:(void(^)(id sender))block; + +/** initializes a menu item from a string and atlas with a block. + The block will be "copied". + */ +-(id) initWithString: (NSString*) value charMapFile:(NSString*) charMapFile itemWidth:(int)itemWidth itemHeight:(int)itemHeight startCharMap:(char)startCharMap block:(void(^)(id sender))block; + +@end + +#pragma mark - +#pragma mark CCMenuItemFont + +/** A CCMenuItemFont + Helper class that creates a CCMenuItemLabel class with a Label + */ +@interface CCMenuItemFont : CCMenuItemLabel +{ + NSUInteger _fontSize; + NSString *_fontName; +} +/** set default font size */ ++(void) setFontSize: (NSUInteger) s; + +/** get default font size */ ++(NSUInteger) fontSize; + +/** set default font name */ ++(void) setFontName: (NSString*) n; + +/** get default font name */ ++(NSString*) fontName; + +/** creates a menu item from a string without target/selector. To be used with CCMenuItemToggle */ ++(id) itemWithString: (NSString*) value; + +/** creates a menu item from a string with a target/selector. + The "target" won't be retained. + */ ++(id) itemWithString: (NSString*) value target:(id) r selector:(SEL) s; + +/** creates a menu item from a string with the specified block. + The block will be "copied". + */ ++(id) itemWithString: (NSString*) value block:(void(^)(id sender))block; + +/** initializes a menu item from a string with a target/selector + The "target" won't be retained. + */ +-(id) initWithString: (NSString*) value target:(id) r selector:(SEL) s; + +/** set font size */ +-(void) setFontSize: (NSUInteger) s; + +/** get font size */ +-(NSUInteger) fontSize; + +/** set the font name */ +-(void) setFontName: (NSString*) n; + +/** get the font name */ +-(NSString*) fontName; + +/** initializes a menu item from a string with the specified block. + The block will be "copied". + */ +-(id) initWithString: (NSString*) value block:(void(^)(id sender))block; + +@end + +#pragma mark - +#pragma mark CCMenuItemSprite + +/** CCMenuItemSprite accepts CCNode objects as items. + The images has 3 different states: + - unselected image + - selected image + - disabled image + + @since v0.8.0 + */ +@interface CCMenuItemSprite : CCMenuItem +{ + CCNode *_normalImage, *_selectedImage, *_disabledImage; +} + +// weak references + +/** the image used when the item is not selected */ +@property (nonatomic,readwrite,assign) CCNode *normalImage; +/** the image used when the item is selected */ +@property (nonatomic,readwrite,assign) CCNode *selectedImage; +/** the image used when the item is disabled */ +@property (nonatomic,readwrite,assign) CCNode *disabledImage; + +/** creates a menu item with a normal and selected image*/ ++(id) itemWithNormalSprite:(CCNode*)normalSprite selectedSprite:(CCNode*)selectedSprite; +/** creates a menu item with a normal and selected image with target/selector. + The "target" won't be retained. + */ ++(id) itemWithNormalSprite:(CCNode*)normalSprite selectedSprite:(CCNode*)selectedSprite target:(id)target selector:(SEL)selector; + +/** creates a menu item with a normal, selected and disabled image with target/selector. + The "target" won't be retained. + */ ++(id) itemWithNormalSprite:(CCNode*)normalSprite selectedSprite:(CCNode*)selectedSprite disabledSprite:(CCNode*)disabledSprite target:(id)target selector:(SEL)selector; + +/** creates a menu item with a normal and selected image with a block. + The block will be "copied". + */ ++(id) itemWithNormalSprite:(CCNode*)normalSprite selectedSprite:(CCNode*)selectedSprite block:(void(^)(id sender))block; + +/** creates a menu item with a normal, selected and disabled image with a block. + The block will be "copied". + */ ++(id) itemWithNormalSprite:(CCNode*)normalSprite selectedSprite:(CCNode*)selectedSprite disabledSprite:(CCNode*)disabledSprite block:(void(^)(id sender))block; + +/** initializes a menu item with a normal, selected and disabled image with target/selector. + The "target" won't be retained. + */ +-(id) initWithNormalSprite:(CCNode*)normalSprite selectedSprite:(CCNode*)selectedSprite disabledSprite:(CCNode*)disabledSprite target:(id)target selector:(SEL)selector; + +/** initializes a menu item with a normal, selected and disabled image with a block. + The block will be "copied". + */ +-(id) initWithNormalSprite:(CCNode*)normalSprite selectedSprite:(CCNode*)selectedSprite disabledSprite:(CCNode*)disabledSprite block:(void(^)(id sender))block; + +@end + +#pragma mark - +#pragma mark CCMenuItemImage + +/** CCMenuItemImage accepts images as items. + The images has 3 different states: + - unselected image + - selected image + - disabled image + + For best results try that all images are of the same size + */ +@interface CCMenuItemImage : CCMenuItemSprite +{ +} + +/** creates a menu item with a normal and selected image*/ ++(id) itemWithNormalImage: (NSString*)value selectedImage:(NSString*) value2; + +/** creates a menu item with a normal, selected and disabled image */ ++(id) itemWithNormalImage: (NSString*)value selectedImage:(NSString*) value2 disabledImage: (NSString*) value3; + +/** creates a menu item with a normal and selected image with target/selector */ ++(id) itemWithNormalImage: (NSString*)value selectedImage:(NSString*) value2 target:(id) r selector:(SEL) s; + +/** creates a menu item with a normal, selected and disabled image with target/selector. + The "target" won't be retained. + */ ++(id) itemWithNormalImage: (NSString*)value selectedImage:(NSString*) value2 disabledImage:(NSString*) value3 target:(id) r selector:(SEL) s; + +/** creates a menu item with a normal and selected image with a block. + The block will be "copied". + */ ++(id) itemWithNormalImage: (NSString*)value selectedImage:(NSString*) value2 block:(void(^)(id sender))block; + +/** creates a menu item with a normal, selected and disabled image with a block. + The block will be "copied". +*/ ++(id) itemWithNormalImage: (NSString*)value selectedImage:(NSString*) value2 disabledImage:(NSString*) value3 block:(void(^)(id sender))block; + +/** initializes a menu item with a normal, selected and disabled image with target/selector. + The "target" won't be retained. + */ +-(id) initWithNormalImage: (NSString*) value selectedImage:(NSString*)value2 disabledImage:(NSString*) value3 target:(id) r selector:(SEL) s; + +/** initializes a menu item with a normal, selected and disabled image with a block. + The block will be "copied". +*/ +-(id) initWithNormalImage: (NSString*) value selectedImage:(NSString*)value2 disabledImage:(NSString*) value3 block:(void(^)(id sender))block; + +/** sets the sprite frame for the normal image */ +- (void) setNormalSpriteFrame:(CCSpriteFrame*)frame; + +/** sets the sprite frame for the selected image */ +- (void) setSelectedSpriteFrame:(CCSpriteFrame*)frame; + +/** sets the sprite frame for the disabled image */ +- (void) setDisabledSpriteFrame:(CCSpriteFrame*)frame; + +@end + +#pragma mark - +#pragma mark CCMenuItemToggle + +/** A CCMenuItemToggle + A simple container class that "toggles" its inner items + The inner itmes can be any MenuItem + */ +@interface CCMenuItemToggle : CCMenuItem +{ + NSUInteger _selectedIndex; + NSMutableArray* _subItems; + CCMenuItem* _currentItem; +} + +/** returns the selected item */ +@property (nonatomic,readwrite) NSUInteger selectedIndex; +/** NSMutableArray that contains the subitems. You can add/remove items in runtime, and you can replace the array with a new one. + @since v0.7.2 + */ +@property (nonatomic,readwrite,retain) NSMutableArray *subItems; + +/** creates a menu item from a list of items with a target/selector */ ++(id) itemWithTarget:(id)target selector:(SEL)selector items:(CCMenuItem*) item, ... NS_REQUIRES_NIL_TERMINATION; ++(id) itemWithTarget:(id)target selector:(SEL)selector items:(CCMenuItem*) item vaList:(va_list)args; + +/** creates a menu item from a list of items. */ ++(id) itemWithItems:(NSArray*)arrayOfItems; + +/** creates a menu item from a list of items and executes the given block when the item is selected. + The block will be "copied". + */ ++(id) itemWithItems:(NSArray*)arrayOfItems block:(void(^)(id sender))block; + +/** initializes a menu item from a list of items with a block. + The block will be "copied". + */ +-(id) initWithItems:(NSArray*)arrayOfItems block:(void (^)(id))block; + +/** return the selected item */ +-(CCMenuItem*) selectedItem; +@end + diff --git "a/21451198\345\215\242\350\266\205/project5/MyPlane/libs/cocos2d/CCMenuItem.m" "b/21451198\345\215\242\350\266\205/project5/MyPlane/libs/cocos2d/CCMenuItem.m" new file mode 100644 index 00000000..557ae0dd --- /dev/null +++ "b/21451198\345\215\242\350\266\205/project5/MyPlane/libs/cocos2d/CCMenuItem.m" @@ -0,0 +1,845 @@ +/* + * cocos2d for iPhone: http://www.cocos2d-iphone.org + * + * Copyright (c) 2008-2011 Ricardo Quesada + * Copyright (c) 2011 Zynga Inc. + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + * THE SOFTWARE. + * + */ + +#import "CCMenuItem.h" +#import "CCLabelTTF.h" +#import "CCLabelAtlas.h" +#import "CCActionInterval.h" +#import "CCSprite.h" +#import "Support/CGPointExtension.h" + +static NSUInteger _globalFontSize = kCCItemSize; +static NSString *_globalFontName = @"Marker Felt"; +static BOOL _globalFontNameRelease = NO; + + +const NSInteger kCCCurrentItemTag = 0xc0c05001; +const NSInteger kCCZoomActionTag = 0xc0c05002; + + +#pragma mark - +#pragma mark CCMenuItem + +@implementation CCMenuItem + +@synthesize isSelected=_isSelected; +@synthesize releaseBlockAtCleanup=_releaseBlockAtCleanup; +@synthesize activeArea=_activeArea; + ++(id) itemWithTarget:(id) r selector:(SEL) s +{ + return [[[self alloc] initWithTarget:r selector:s] autorelease]; +} + ++(id) itemWithBlock:(void(^)(id sender))block { + return [[[self alloc] initWithBlock:block] autorelease]; +} + +-(id) init +{ + return [self initWithBlock:nil]; +} + +-(id) initWithTarget:(id)target selector:(SEL)selector +{ + // avoid retain cycle + __block id t = target; + return [self initWithBlock:^(id sender) { + + [t performSelector:selector withObject:sender]; + }]; + +} + + +// Designated initializer +-(id) initWithBlock:(void (^)(id))block +{ + if((self=[super init]) ) { + + if( block ) + _block = [block copy]; + + self.anchorPoint = ccp(0.5f, 0.5f); + _isEnabled = YES; + _isSelected = NO; + + // WARNING: Will be disabled in v2.2 + _releaseBlockAtCleanup = YES; + + } + return self; +} + +-(void) setContentSize:(CGSize)contentSize { + [super setContentSize:contentSize]; + + // Reset touch area to match the outside box + _activeArea = CGRectMake(0, 0, contentSize.width, contentSize.height); +} + + +-(void) dealloc +{ + [_block release]; + + [super dealloc]; +} + +-(void) cleanup +{ + if( _releaseBlockAtCleanup ) { + [_block release]; + _block = nil; + } + + [super cleanup]; +} + +-(void) selected +{ + _isSelected = YES; +} + +-(void) unselected +{ + _isSelected = NO; +} + +-(void) activate +{ + if(_isEnabled && _block ) + _block(self); +} + +-(void) setIsEnabled: (BOOL)enabled +{ + _isEnabled = enabled; +} + +-(BOOL) isEnabled +{ + return _isEnabled; +} + +-(void) setBlock:(void(^)(id sender))block +{ + [_block release]; + _block = [block copy]; +} + +-(void) setTarget:(id)target selector:(SEL)selector +{ + __block id weakTarget = target; // avoid retain cycle + [self setBlock:^(id sender) { + [weakTarget performSelector:selector withObject:sender]; + }]; +} + +@end + + +#pragma mark - +#pragma mark CCMenuItemLabel + +@implementation CCMenuItemLabel + +@synthesize disabledColor = _disabledColor; + ++(id) itemWithLabel:(CCNode*)label +{ + return [[[self alloc] initWithLabel:label block:nil] autorelease]; +} + ++(id) itemWithLabel:(CCNode*)label target:(id)target selector:(SEL)selector +{ + return [[[self alloc] initWithLabel:label target:target selector:selector] autorelease]; +} + ++(id) itemWithLabel:(CCNode*)label block:(void(^)(id sender))block { + return [[[self alloc] initWithLabel:label block:block] autorelease]; +} + + +-(id) initWithLabel:(CCNode*)label target:(id)target selector:(SEL)selector +{ + // avoid retain cycle + __block id t = target; + + self = [self initWithLabel:label block: ^(id sender) { + [t performSelector:selector withObject:sender]; + } + ]; + return self; +} + +// +// Designated initializer +// +-(id) initWithLabel:(CCNode *)label block:(void (^)(id))block +{ + if( (self=[self initWithBlock:block]) ) { + _originalScale = 1; + _colorBackup = ccWHITE; + self.disabledColor = ccc3( 126,126,126); + self.label = label; + + self.cascadeColorEnabled = YES; + self.cascadeOpacityEnabled = YES; + } + + return self; +} + +-(CCNode*) label +{ + return _label; +} +-(void) setLabel:(CCNode*) label +{ + if( label != _label ) { + [self removeChild:_label cleanup:YES]; + [self addChild:label]; + + _label = label; + _label.anchorPoint = ccp(0,0); + + [self setContentSize:[_label contentSize]]; + } +} + +-(void) setString:(NSString *)string +{ + [_label setString:string]; + [self setContentSize: [_label contentSize]]; +} + +-(void) activate { + if(_isEnabled) { + [self stopAllActions]; + + self.scale = _originalScale; + + [super activate]; + } +} + +-(void) selected +{ + // subclass to change the default action + if(_isEnabled) { + [super selected]; + + CCAction *action = [self getActionByTag:kCCZoomActionTag]; + if( action ) + [self stopAction:action]; + else + _originalScale = self.scale; + + CCAction *zoomAction = [CCScaleTo actionWithDuration:0.1f scale:_originalScale * 1.2f]; + zoomAction.tag = kCCZoomActionTag; + [self runAction:zoomAction]; + } +} + +-(void) unselected +{ + // subclass to change the default action + if(_isEnabled) { + [super unselected]; + [self stopActionByTag:kCCZoomActionTag]; + CCAction *zoomAction = [CCScaleTo actionWithDuration:0.1f scale:_originalScale]; + zoomAction.tag = kCCZoomActionTag; + [self runAction:zoomAction]; + } +} + +-(void) setIsEnabled: (BOOL)enabled +{ + if( _isEnabled != enabled ) { + if(enabled == NO) { + _colorBackup = [_label color]; + [_label setColor: _disabledColor]; + } + else + [_label setColor:_colorBackup]; + } + + [super setIsEnabled:enabled]; +} +@end + +#pragma mark - CCMenuItemAtlasFont + +@implementation CCMenuItemAtlasFont + ++(id) itemWithString: (NSString*) value charMapFile:(NSString*) charMapFile itemWidth:(int)itemWidth itemHeight:(int)itemHeight startCharMap:(char)startCharMap +{ + return [CCMenuItemAtlasFont itemWithString:value charMapFile:charMapFile itemWidth:itemWidth itemHeight:itemHeight startCharMap:startCharMap target:nil selector:nil]; +} + ++(id) itemWithString: (NSString*) value charMapFile:(NSString*) charMapFile itemWidth:(int)itemWidth itemHeight:(int)itemHeight startCharMap:(char)startCharMap target:(id)target selector:(SEL)selector +{ + return [[[self alloc] initWithString:value charMapFile:charMapFile itemWidth:itemWidth itemHeight:itemHeight startCharMap:startCharMap target:target selector:selector] autorelease]; +} + ++(id) itemWithString:(NSString*)value charMapFile:(NSString*)charMapFile itemWidth:(int)itemWidth itemHeight:(int)itemHeight startCharMap:(char)startCharMap block:(void(^)(id sender))block +{ + return [[[self alloc] initWithString:value charMapFile:charMapFile itemWidth:itemWidth itemHeight:itemHeight startCharMap:startCharMap block:block] autorelease]; +} + +-(id) initWithString: (NSString*) value charMapFile:(NSString*) charMapFile itemWidth:(int)itemWidth itemHeight:(int)itemHeight startCharMap:(char)startCharMap target:(id)target selector:(SEL)selector +{ + // avoid retain cycle + __block id t = target; + + return [self initWithString:value charMapFile:charMapFile itemWidth:itemWidth itemHeight:itemHeight startCharMap:startCharMap block:^(id sender) { + [t performSelector:selector withObject:sender]; + } ]; +} + +// +// Designated initializer +// +-(id) initWithString:(NSString*)value charMapFile:(NSString*)charMapFile itemWidth:(int)itemWidth itemHeight:(int)itemHeight startCharMap:(char)startCharMap block:(void(^)(id sender))block +{ + NSAssert( [value length] > 0, @"value length must be greater than 0"); + + CCLabelAtlas *label = [[CCLabelAtlas alloc] initWithString:value charMapFile:charMapFile itemWidth:itemWidth itemHeight:itemHeight startCharMap:startCharMap]; + + id ret = [self initWithLabel:label block:block]; + + [label release]; + + return ret; + +} + +-(void) dealloc +{ + [super dealloc]; +} +@end + + +#pragma mark - CCMenuItemFont + +@implementation CCMenuItemFont + ++(void) setFontSize: (NSUInteger) s +{ + _globalFontSize = s; +} + ++(NSUInteger) fontSize +{ + return _globalFontSize; +} + ++(void) setFontName: (NSString*) n +{ + if( _globalFontNameRelease ) + [_globalFontName release]; + + _globalFontName = [n retain]; + _globalFontNameRelease = YES; +} + ++(NSString*) fontName +{ + return _globalFontName; +} + ++(id) itemWithString: (NSString*) value target:(id) r selector:(SEL) s +{ + return [[[self alloc] initWithString: value target:r selector:s] autorelease]; +} + ++(id) itemWithString: (NSString*) value +{ + return [[[self alloc] initWithString: value target:nil selector:nil] autorelease]; +} + ++(id) itemWithString: (NSString*) value block:(void(^)(id sender))block +{ + return [[[self alloc] initWithString:value block:block] autorelease]; +} + +-(id) initWithString: (NSString*) value target:(id)target selector:(SEL)selector +{ + // avoid retain cycle + __block id t = target; + + return [self initWithString:value block:^(id sender) { + [t performSelector:selector withObject:sender]; + }]; +} + +// +// Designated initializer +// +-(id) initWithString: (NSString*)string block:(void(^)(id sender))block +{ + NSAssert( [string length] > 0, @"Value length must be greater than 0"); + + _fontName = [_globalFontName copy]; + _fontSize = _globalFontSize; + + CCLabelTTF *label = [CCLabelTTF labelWithString:string fontName:_fontName fontSize:_fontSize]; + + if((self=[super initWithLabel:label block:block]) ) { + // do something ? + } + + return self; +} + +-(void) recreateLabel +{ + CCLabelTTF *label = [[CCLabelTTF alloc] initWithString:[_label string] fontName:_fontName fontSize:_fontSize]; + self.label = label; + [label release]; +} + +-(void) setFontSize: (NSUInteger) size +{ + _fontSize = size; + [self recreateLabel]; +} + +-(NSUInteger) fontSize +{ + return _fontSize; +} + +-(void) setFontName: (NSString*) fontName +{ + if (_fontName) + [_fontName release]; + + _fontName = [fontName copy]; + [self recreateLabel]; +} + +-(NSString*) fontName +{ + return _fontName; +} +@end + +#pragma mark - CCMenuItemSprite + +@interface CCMenuItemSprite() +-(void) updateImagesVisibility; +@end + +@implementation CCMenuItemSprite + +@synthesize normalImage=_normalImage, selectedImage=_selectedImage, disabledImage=_disabledImage; + ++(id) itemWithNormalSprite:(CCNode*)normalSprite selectedSprite:(CCNode*)selectedSprite +{ + return [self itemWithNormalSprite:normalSprite selectedSprite:selectedSprite disabledSprite:nil target:nil selector:nil]; +} + ++(id) itemWithNormalSprite:(CCNode*)normalSprite selectedSprite:(CCNode*)selectedSprite target:(id)target selector:(SEL)selector +{ + return [self itemWithNormalSprite:normalSprite selectedSprite:selectedSprite disabledSprite:nil target:target selector:selector]; +} + ++(id) itemWithNormalSprite:(CCNode*)normalSprite selectedSprite:(CCNode*)selectedSprite disabledSprite:(CCNode*)disabledSprite target:(id)target selector:(SEL)selector +{ + return [[[self alloc] initWithNormalSprite:normalSprite selectedSprite:selectedSprite disabledSprite:disabledSprite target:target selector:selector] autorelease]; +} + ++(id) itemWithNormalSprite:(CCNode*)normalSprite selectedSprite:(CCNode*)selectedSprite block:(void(^)(id sender))block +{ + return [self itemWithNormalSprite:normalSprite selectedSprite:selectedSprite disabledSprite:nil block:block]; +} + ++(id) itemWithNormalSprite:(CCNode*)normalSprite selectedSprite:(CCNode*)selectedSprite disabledSprite:(CCNode*)disabledSprite block:(void(^)(id sender))block +{ + return [[[self alloc] initWithNormalSprite:normalSprite selectedSprite:selectedSprite disabledSprite:disabledSprite block:block] autorelease]; +} + +-(id) initWithNormalSprite:(CCNode*)normalSprite selectedSprite:(CCNode*)selectedSprite disabledSprite:(CCNode*)disabledSprite target:(id)target selector:(SEL)selector +{ + // avoid retain cycle + __block id t = target; + + return [self initWithNormalSprite:normalSprite selectedSprite:selectedSprite disabledSprite:disabledSprite block:^(id sender) { + [t performSelector:selector withObject:sender]; + } ]; +} + +// +// Designated initializer +// +-(id) initWithNormalSprite:(CCNode*)normalSprite selectedSprite:(CCNode*)selectedSprite disabledSprite:(CCNode*)disabledSprite block:(void(^)(id sender))block +{ + if ( (self = [super initWithBlock:block] ) ) { + + self.normalImage = normalSprite; + self.selectedImage = selectedSprite; + self.disabledImage = disabledSprite; + + [self setContentSize: [_normalImage contentSize]]; + + self.cascadeColorEnabled = YES; + self.cascadeOpacityEnabled = YES; + } + return self; +} + +-(void) setNormalImage:(CCNode *)image +{ + if( image != _normalImage ) { + image.anchorPoint = ccp(0,0); + + [self removeChild:_normalImage cleanup:YES]; + [self addChild:image]; + + _normalImage = image; + + [self setContentSize: [_normalImage contentSize]]; + + [self updateImagesVisibility]; + } +} + +-(void) setSelectedImage:(CCNode *)image +{ + if( image != _selectedImage ) { + image.anchorPoint = ccp(0,0); + + [self removeChild:_selectedImage cleanup:YES]; + [self addChild:image]; + + _selectedImage = image; + + [self updateImagesVisibility]; + } +} + +-(void) setDisabledImage:(CCNode *)image +{ + if( image != _disabledImage ) { + image.anchorPoint = ccp(0,0); + + [self removeChild:_disabledImage cleanup:YES]; + [self addChild:image]; + + _disabledImage = image; + + [self updateImagesVisibility]; + } +} + +-(void) selected +{ + [super selected]; + + if( _selectedImage ) { + [_normalImage setVisible:NO]; + [_selectedImage setVisible:YES]; + [_disabledImage setVisible:NO]; + + } else { // there is not selected image + + [_normalImage setVisible:YES]; + [_selectedImage setVisible:NO]; + [_disabledImage setVisible:NO]; + } +} + +-(void) unselected +{ + [super unselected]; + [_normalImage setVisible:YES]; + [_selectedImage setVisible:NO]; + [_disabledImage setVisible:NO]; +} + +-(void) setIsEnabled:(BOOL)enabled +{ + if( _isEnabled != enabled ) { + [super setIsEnabled:enabled]; + + [self updateImagesVisibility]; + } +} + + +// Helper +-(void) updateImagesVisibility +{ + if( _isEnabled ) { + [_normalImage setVisible:YES]; + [_selectedImage setVisible:NO]; + [_disabledImage setVisible:NO]; + + } else { + if( _disabledImage ) { + [_normalImage setVisible:NO]; + [_selectedImage setVisible:NO]; + [_disabledImage setVisible:YES]; + } else { + [_normalImage setVisible:YES]; + [_selectedImage setVisible:NO]; + [_disabledImage setVisible:NO]; + } + } +} + +@end + +#pragma mark - CCMenuItemImage + +@implementation CCMenuItemImage + ++(id) itemWithNormalImage: (NSString*)value selectedImage:(NSString*) value2 +{ + return [self itemWithNormalImage:value selectedImage:value2 disabledImage: nil target:nil selector:nil]; +} + ++(id) itemWithNormalImage: (NSString*)value selectedImage:(NSString*) value2 target:(id) t selector:(SEL) s +{ + return [self itemWithNormalImage:value selectedImage:value2 disabledImage: nil target:t selector:s]; +} + ++(id) itemWithNormalImage: (NSString*)value selectedImage:(NSString*) value2 disabledImage: (NSString*) value3 +{ + return [[[self alloc] initWithNormalImage:value selectedImage:value2 disabledImage:value3 target:nil selector:nil] autorelease]; +} + ++(id) itemWithNormalImage: (NSString*)value selectedImage:(NSString*) value2 disabledImage: (NSString*) value3 target:(id) t selector:(SEL) s +{ + return [[[self alloc] initWithNormalImage:value selectedImage:value2 disabledImage:value3 target:t selector:s] autorelease]; +} + ++(id) itemWithNormalImage: (NSString*)value selectedImage:(NSString*) value2 block:(void(^)(id sender))block +{ + return [self itemWithNormalImage:value selectedImage:value2 disabledImage:nil block:block]; +} + ++(id) itemWithNormalImage: (NSString*)value selectedImage:(NSString*) value2 disabledImage:(NSString*) value3 block:(void(^)(id sender))block +{ + return [[[self alloc] initWithNormalImage:value selectedImage:value2 disabledImage:value3 block:block] autorelease]; +} + +-(id) initWithNormalImage: (NSString*) normalI selectedImage:(NSString*)selectedI disabledImage: (NSString*) disabledI target:(id)target selector:(SEL)selector +{ + // avoid retain cycle + __block id t = target; + + return [self initWithNormalImage:normalI selectedImage:selectedI disabledImage:disabledI block:^(id sender) { + [t performSelector:selector withObject:sender]; + }]; +} + + +// +// Designated initializer +// +-(id) initWithNormalImage:(NSString*)normalI selectedImage:(NSString*)selectedI disabledImage:(NSString*)disabledI block:(void(^)(id sender))block +{ + CCNode *normalImage = [CCSprite spriteWithFile:normalI]; + CCNode *selectedImage = nil; + CCNode *disabledImage = nil; + + if( selectedI ) + selectedImage = [CCSprite spriteWithFile:selectedI]; + if(disabledI) + disabledImage = [CCSprite spriteWithFile:disabledI]; + + return [super initWithNormalSprite:normalImage selectedSprite:selectedImage disabledSprite:disabledImage block:block]; +} + +// +// Setter of sprite frames +// +-(void) setNormalSpriteFrame:(CCSpriteFrame *)frame +{ + [self setNormalImage:[CCSprite spriteWithSpriteFrame:frame]]; +} + +-(void) setSelectedSpriteFrame:(CCSpriteFrame *)frame +{ + [self setSelectedImage:[CCSprite spriteWithSpriteFrame:frame]]; +} + +-(void) setDisabledSpriteFrame:(CCSpriteFrame *)frame +{ + [self setDisabledImage:[CCSprite spriteWithSpriteFrame:frame]]; +} + +@end + +#pragma mark - CCMenuItemToggle + +// +// MenuItemToggle +// +@interface CCMenuItemToggle () +/** + Reference to the current display item. + */ +@property (nonatomic, assign) CCMenuItem *currentItem; +@end + +@implementation CCMenuItemToggle +@synthesize currentItem = _currentItem; +@synthesize subItems = _subItems; + ++(id) itemWithTarget: (id)t selector: (SEL)sel items: (CCMenuItem*) item, ... +{ + va_list args; + va_start(args, item); + + id s = [self itemWithTarget: t selector:sel items: item vaList:args]; + + va_end(args); + return s; +} + ++(id) itemWithTarget:(id)target selector:(SEL)selector items:(CCMenuItem*) item vaList: (va_list) args +{ + NSMutableArray *array = [NSMutableArray arrayWithCapacity:2]; + + int z = 0; + CCMenuItem *i = item; + while(i) { + z++; + [array addObject:i]; + i = va_arg(args, CCMenuItem*); + } + + // avoid retain cycle + __block id t = target; + + return [[[self alloc] initWithItems:array block:^(id sender) { + [t performSelector:selector withObject:sender]; + } + ] autorelease]; +} + + ++(id) itemWithItems:(NSArray*)arrayOfItems +{ + return [[[self alloc] initWithItems:arrayOfItems block:NULL] autorelease]; +} + ++(id) itemWithItems:(NSArray*)arrayOfItems block:(void(^)(id))block +{ + return [[[self alloc] initWithItems:arrayOfItems block:block] autorelease]; +} + +-(id) initWithItems:(NSArray*)arrayOfItems block:(void(^)(id sender))block +{ + if( (self=[super initWithBlock:block] ) ) { + + self.subItems = [NSMutableArray arrayWithArray:arrayOfItems]; + + _currentItem = nil; + _selectedIndex = NSUIntegerMax; + [self setSelectedIndex:0]; + + self.cascadeColorEnabled = YES; + self.cascadeOpacityEnabled = YES; + } + + return self; +} + +-(void) dealloc +{ + [_subItems release]; + [super dealloc]; +} + +-(void)setSelectedIndex:(NSUInteger)index +{ + if( index != _selectedIndex ) { + _selectedIndex=index; + + if( _currentItem ) + [_currentItem removeFromParentAndCleanup:NO]; + + CCMenuItem *item = [_subItems objectAtIndex:_selectedIndex]; + [self addChild:item z:0]; + self.currentItem = item; + + CGSize s = [item contentSize]; + [self setContentSize: s]; + item.position = ccp( s.width/2, s.height/2 ); + } +} + +-(NSUInteger) selectedIndex +{ + return _selectedIndex; +} + + +-(void) selected +{ + [super selected]; + [[_subItems objectAtIndex:_selectedIndex] selected]; +} + +-(void) unselected +{ + [super unselected]; + [[_subItems objectAtIndex:_selectedIndex] unselected]; +} + +-(void) activate +{ + // update index + if( _isEnabled ) { + NSUInteger newIndex = (_selectedIndex + 1) % [_subItems count]; + [self setSelectedIndex:newIndex]; + + } + + [super activate]; +} + +-(void) setIsEnabled: (BOOL)enabled +{ + if( _isEnabled != enabled ) { + [super setIsEnabled:enabled]; + for(CCMenuItem* item in _subItems) + [item setIsEnabled:enabled]; + } +} + +-(CCMenuItem*) selectedItem +{ + return [_subItems objectAtIndex:_selectedIndex]; +} + +@end diff --git "a/21451198\345\215\242\350\266\205/project5/MyPlane/libs/cocos2d/CCMotionStreak.h" "b/21451198\345\215\242\350\266\205/project5/MyPlane/libs/cocos2d/CCMotionStreak.h" new file mode 100644 index 00000000..791d5466 --- /dev/null +++ "b/21451198\345\215\242\350\266\205/project5/MyPlane/libs/cocos2d/CCMotionStreak.h" @@ -0,0 +1,86 @@ +/* + * cocos2d for iPhone: http://www.cocos2d-iphone.org + * + * Copyright (c) 2011 ForzeField Studios S.L. http://forzefield.com + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + * THE SOFTWARE. + * + */ + + +#import +#import "CCTexture2D.h" +#import "ccTypes.h" +#import "CCNode.h" + +/** MotionStreak. + Creates a trailing path. + */ +@interface CCMotionStreak : CCNodeRGBA +{ + CCTexture2D *_texture; + CGPoint _positionR; + ccBlendFunc _blendFunc; + float _stroke; + float _fadeDelta; + float _minSeg; + + NSUInteger _maxPoints; + NSUInteger _nuPoints; + NSUInteger _previousNuPoints; + + /** Pointers */ + CGPoint *_pointVertexes; + float *_pointState; + + // Opengl + ccVertex2F *_vertices; + unsigned char *_colorPointer; + ccTex2F *_texCoords; + + BOOL _fastMode; + + BOOL _startingPositionInitialized; +} +/** blending function */ +@property (nonatomic, readwrite, assign) ccBlendFunc blendFunc; + +/** When fast mode is enabled, new points are added faster but with lower precision */ +@property (nonatomic, readwrite, assign, getter = isFastMode) BOOL fastMode; + +/** texture used for the motion streak */ +@property (nonatomic, retain) CCTexture2D *texture; + +/** creates and initializes a motion streak with fade in seconds, minimum segments, stroke's width, color, texture filename */ ++ (id) streakWithFade:(float)fade minSeg:(float)minSeg width:(float)stroke color:(ccColor3B)color textureFilename:(NSString*)path; +/** creates and initializes a motion streak with fade in seconds, minimum segments, stroke's width, color, texture */ ++ (id) streakWithFade:(float)fade minSeg:(float)minSeg width:(float)stroke color:(ccColor3B)color texture:(CCTexture2D*)texture; + +/** initializes a motion streak with fade in seconds, minimum segments, stroke's width, color and texture filename */ +- (id) initWithFade:(float)fade minSeg:(float)minSeg width:(float)stroke color:(ccColor3B)color textureFilename:(NSString*)path; +/** initializes a motion streak with fade in seconds, minimum segments, stroke's width, color and texture */ +- (id) initWithFade:(float)fade minSeg:(float)minSeg width:(float)stroke color:(ccColor3B)color texture:(CCTexture2D*)texture; + +/** color used for the tint */ +- (void) tintWithColor:(ccColor3B)colors; + +/** Remove all living segments of the ribbon */ +- (void) reset; + +@end diff --git "a/21451198\345\215\242\350\266\205/project5/MyPlane/libs/cocos2d/CCMotionStreak.m" "b/21451198\345\215\242\350\266\205/project5/MyPlane/libs/cocos2d/CCMotionStreak.m" new file mode 100644 index 00000000..e28c1665 --- /dev/null +++ "b/21451198\345\215\242\350\266\205/project5/MyPlane/libs/cocos2d/CCMotionStreak.m" @@ -0,0 +1,280 @@ +/* + * cocos2d for iPhone: http://www.cocos2d-iphone.org + * + * Copyright (c) 2011 ForzeField Studios S.L. http://forzefield.com + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + * THE SOFTWARE. + * + */ + +#import "CCMotionStreak.h" +#import "CCTextureCache.h" +#import "ccGLStateCache.h" +#import "CCGLProgram.h" +#import "CCShaderCache.h" +#import "ccMacros.h" + +#import "Support/CCVertex.h" +#import "Support/CGPointExtension.h" + + +@implementation CCMotionStreak +@synthesize texture = _texture; +@synthesize blendFunc = _blendFunc; +@synthesize fastMode = _fastMode; + ++ (id) streakWithFade:(float)fade minSeg:(float)minSeg width:(float)stroke color:(ccColor3B)color textureFilename:(NSString*)path +{ + return [[[self alloc] initWithFade:fade minSeg:minSeg width:stroke color:color textureFilename:path] autorelease]; +} + ++ (id) streakWithFade:(float)fade minSeg:(float)minSeg width:(float)stroke color:(ccColor3B)color texture:(CCTexture2D*)texture +{ + return [[[self alloc] initWithFade:fade minSeg:minSeg width:stroke color:color texture:texture] autorelease]; +} + +- (id) initWithFade:(float)fade minSeg:(float)minSeg width:(float)stroke color:(ccColor3B)color textureFilename:(NSString*)path +{ + NSAssert(path != nil, @"Invalid filename"); + + CCTexture2D *texture = [[CCTextureCache sharedTextureCache] addImage:path]; + return [self initWithFade:fade minSeg:minSeg width:stroke color:color texture:texture]; +} + +- (id) initWithFade:(float)fade minSeg:(float)minSeg width:(float)stroke color:(ccColor3B)color texture:(CCTexture2D*)texture +{ + self = [super init]; + if (self) + { + [super setPosition:CGPointZero]; + [self setAnchorPoint:CGPointZero]; + [self setIgnoreAnchorPointForPosition:YES]; + + _startingPositionInitialized = NO; + _positionR = CGPointZero; + _fastMode = YES; + _minSeg = (minSeg == -1.0f) ? stroke/5.0f : minSeg; + _minSeg *= _minSeg; + + _stroke = stroke; + _fadeDelta = 1.0f/fade; + + _maxPoints = (int)(fade*60.0f)+2; + _nuPoints = _previousNuPoints = 0; + _pointState = malloc(sizeof(float) * _maxPoints); + _pointVertexes = malloc(sizeof(CGPoint) * _maxPoints); + + _vertices = malloc(sizeof(ccVertex2F) * _maxPoints * 2); + _texCoords = malloc(sizeof(ccTex2F) * _maxPoints * 2); + _colorPointer = malloc(sizeof(GLubyte) * _maxPoints * 2 * 4); + + // Set blend mode + _blendFunc.src = GL_SRC_ALPHA; + _blendFunc.dst = GL_ONE_MINUS_SRC_ALPHA; + + // shader program + self.shaderProgram = [[CCShaderCache sharedShaderCache] programForKey:kCCShader_PositionTextureColor]; + + [self setTexture:texture]; + [self setColor:color]; + [self scheduleUpdate]; + + } + return self; +} + +#pragma mark - + +- (void) setPosition:(CGPoint)position +{ + _startingPositionInitialized = YES; + _positionR = position; +} + +- (void) tintWithColor:(ccColor3B)colors +{ + [self setColor:colors]; + + // Fast assignation + for(int i = 0; i<_nuPoints*2; i++) + *((ccColor3B*) (_colorPointer+i*4)) = colors; +} + +- (void) setOpacity:(GLubyte)opacity +{ + NSAssert(NO, @"Set opacity no supported"); +} + +- (GLubyte) opacity +{ + NSAssert(NO, @"Opacity no supported"); + return 0; +} + +#pragma mark - + +- (void) update:(ccTime)delta +{ + if( !_startingPositionInitialized ) + return; + + delta *= _fadeDelta; + + NSUInteger newIdx, newIdx2, i, i2; + NSUInteger mov = 0; + + // Update current points + for(i = 0; i<_nuPoints; i++) + { + _pointState[i]-=delta; + + if(_pointState[i] <= 0) + mov++; + else + { + newIdx = i-mov; + + if(mov>0) + { + // Move data + _pointState[newIdx] = _pointState[i]; + + // Move point + _pointVertexes[newIdx] = _pointVertexes[i]; + + // Move vertices + i2 = i*2; + newIdx2 = newIdx*2; + _vertices[newIdx2] = _vertices[i2]; + _vertices[newIdx2+1] = _vertices[i2+1]; + + // Move color + i2 *= 4; + newIdx2 *= 4; + _colorPointer[newIdx2+0] = _colorPointer[i2+0]; + _colorPointer[newIdx2+1] = _colorPointer[i2+1]; + _colorPointer[newIdx2+2] = _colorPointer[i2+2]; + _colorPointer[newIdx2+4] = _colorPointer[i2+4]; + _colorPointer[newIdx2+5] = _colorPointer[i2+5]; + _colorPointer[newIdx2+6] = _colorPointer[i2+6]; + }else + newIdx2 = newIdx*8; + + const GLubyte op = _pointState[newIdx] * 255.0f; + _colorPointer[newIdx2+3] = op; + _colorPointer[newIdx2+7] = op; + } + } + _nuPoints-=mov; + + // Append new point + BOOL appendNewPoint = YES; + if(_nuPoints >= _maxPoints) + appendNewPoint = NO; + + else if(_nuPoints>0) + { + BOOL a1 = ccpDistanceSQ(_pointVertexes[_nuPoints-1], _positionR) < _minSeg; + BOOL a2 = (_nuPoints == 1) ? NO : (ccpDistanceSQ(_pointVertexes[_nuPoints-2], _positionR) < (_minSeg * 2.0f)); + if(a1 || a2) + appendNewPoint = NO; + } + + if(appendNewPoint) + { + _pointVertexes[_nuPoints] = _positionR; + _pointState[_nuPoints] = 1.0f; + + // Color asignation + const NSUInteger offset = _nuPoints*8; + *((ccColor3B*)(_colorPointer + offset)) = _displayedColor; + *((ccColor3B*)(_colorPointer + offset+4)) = _displayedColor; + + // Opacity + _colorPointer[offset+3] = 255; + _colorPointer[offset+7] = 255; + + // Generate polygon + if(_nuPoints > 0 && _fastMode ) + { + if(_nuPoints > 1) + ccVertexLineToPolygon(_pointVertexes, _stroke, _vertices, _nuPoints, 1); + else + ccVertexLineToPolygon(_pointVertexes, _stroke, _vertices, 0, 2); + } + + _nuPoints ++; + } + + if( ! _fastMode ) + ccVertexLineToPolygon(_pointVertexes, _stroke, _vertices, 0, _nuPoints); + + + // Updated Tex Coords only if they are different than previous step + if( _nuPoints && _previousNuPoints != _nuPoints ) { + float texDelta = 1.0f / _nuPoints; + for( i=0; i < _nuPoints; i++ ) { + _texCoords[i*2] = (ccTex2F) {0, texDelta*i}; + _texCoords[i*2+1] = (ccTex2F) {1, texDelta*i}; + } + + _previousNuPoints = _nuPoints; + } +} + +- (void) reset +{ + _nuPoints = 0; +} + +- (void) draw +{ + if(_nuPoints <= 1) + return; + + CC_NODE_DRAW_SETUP(); + + ccGLEnableVertexAttribs(kCCVertexAttribFlag_PosColorTex ); + ccGLBlendFunc( _blendFunc.src, _blendFunc.dst ); + + ccGLBindTexture2D( [_texture name] ); + + glVertexAttribPointer(kCCVertexAttrib_Position, 2, GL_FLOAT, GL_FALSE, 0, _vertices); + glVertexAttribPointer(kCCVertexAttrib_TexCoords, 2, GL_FLOAT, GL_FALSE, 0, _texCoords); + glVertexAttribPointer(kCCVertexAttrib_Color, 4, GL_UNSIGNED_BYTE, GL_TRUE, 0, _colorPointer); + + glDrawArrays(GL_TRIANGLE_STRIP, 0, (GLsizei)_nuPoints*2); + + CC_INCREMENT_GL_DRAWS(1); +} + +- (void)dealloc +{ + [_texture release]; + + free(_pointState); + free(_pointVertexes); + free(_vertices); + free(_colorPointer); + free(_texCoords); + + [super dealloc]; +} + +@end diff --git "a/21451198\345\215\242\350\266\205/project5/MyPlane/libs/cocos2d/CCNode+Debug.h" "b/21451198\345\215\242\350\266\205/project5/MyPlane/libs/cocos2d/CCNode+Debug.h" new file mode 100644 index 00000000..f2e08fe5 --- /dev/null +++ "b/21451198\345\215\242\350\266\205/project5/MyPlane/libs/cocos2d/CCNode+Debug.h" @@ -0,0 +1,39 @@ +/* + * cocos2d for iPhone: http://www.cocos2d-iphone.org + * + * Copyright (c) 2012 Zynga Inc. + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + * THE SOFTWARE. + */ + +#import "CCNode.h" + +#ifdef DEBUG + +/** Debugging extensions of CCNode. + They are available when the DEBUG macro is defined at compile time + */ +@interface CCNode (Debug) + +/** prints on the debug console the scene graph */ +-(void) walkSceneGraph:(NSUInteger)level; + +@end + +#endif // DEBUG diff --git "a/21451198\345\215\242\350\266\205/project5/MyPlane/libs/cocos2d/CCNode+Debug.m" "b/21451198\345\215\242\350\266\205/project5/MyPlane/libs/cocos2d/CCNode+Debug.m" new file mode 100644 index 00000000..8dc49689 --- /dev/null +++ "b/21451198\345\215\242\350\266\205/project5/MyPlane/libs/cocos2d/CCNode+Debug.m" @@ -0,0 +1,71 @@ +/* + * cocos2d for iPhone: http://www.cocos2d-iphone.org + * + * Copyright (c) 2012 Zynga Inc. + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + * THE SOFTWARE. + */ + +#import "CCNode+Debug.h" + +#ifdef DEBUG + +@implementation CCNode (Debug) + +-(void) walkSceneGraph:(NSUInteger)level +{ + char buf[64]; + NSUInteger i=0; + for( i=0; idata; + i = 0; + + // draw children zOrder < 0 + for( ; i < arrayData->num; i++ ) { + CCNode *child = arrayData->arr[i]; + if ( [child zOrder] < 0 ) + [child walkSceneGraph:level+1]; + else + break; + } + + // self draw + NSLog(@"walk tree: %s> %@ %p", buf, self, self); + + // draw children zOrder >= 0 + for( ; i < arrayData->num; i++ ) { + CCNode *child = arrayData->arr[i]; + [child walkSceneGraph:level+1]; + } + + } else + NSLog(@"walk tree: %s> %@ %p", buf, self, self); + +} +@end + +#endif // DEBUG diff --git "a/21451198\345\215\242\350\266\205/project5/MyPlane/libs/cocos2d/CCNode.h" "b/21451198\345\215\242\350\266\205/project5/MyPlane/libs/cocos2d/CCNode.h" new file mode 100644 index 00000000..e84f8fbe --- /dev/null +++ "b/21451198\345\215\242\350\266\205/project5/MyPlane/libs/cocos2d/CCNode.h" @@ -0,0 +1,619 @@ +/* + * cocos2d for iPhone: http://www.cocos2d-iphone.org + * + * Copyright (c) 2009 Valentin Milea + * + * Copyright (c) 2008-2010 Ricardo Quesada + * Copyright (c) 2011 Zynga Inc. + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + * THE SOFTWARE. + */ + +#import "Platforms/CCGL.h" +#import "ccTypes.h" +#import "CCProtocols.h" +#import "ccConfig.h" +#import "ccGLStateCache.h" +#import "Support/CCArray.h" +#import "kazmath/kazmath.h" + +enum { + kCCNodeTagInvalid = -1, +}; + +@class CCCamera; +@class CCGridBase; +@class CCGLProgram; +@class CCScheduler; +@class CCActionManager; +@class CCAction; + +/** CCNode is the main element. Anything thats gets drawn or contains things that get drawn is a CCNode. + The most popular CCNodes are: CCScene, CCLayer, CCSprite, CCMenu. + + The main features of a CCNode are: + - They can contain other CCNode nodes (addChild, getChildByTag, removeChild, etc) + - They can schedule periodic callback (schedule, unschedule, etc) + - They can execute actions (runAction, stopAction, etc) + + Some CCNode nodes provide extra functionality for them or their children. + + Subclassing a CCNode usually means (one/all) of: + - overriding init to initialize resources and schedule callbacks + - create callbacks to handle the advancement of time + - overriding draw to render the node + + Features of CCNode: + - position + - scale (x, y) + - rotation (in degrees, clockwise) + - CCCamera (an interface to gluLookAt ) + - CCGridBase (to do mesh transformations) + - anchor point + - size + - visible + - z-order + - openGL z position + + Default values: + - rotation: 0 + - position: (x=0,y=0) + - scale: (x=1,y=1) + - contentSize: (x=0,y=0) + - anchorPoint: (x=0,y=0) + + Limitations: + - A CCNode is a "void" object. It doesn't have a texture + + Order in transformations with grid disabled + -# The node will be translated (position) + -# The node will be rotated (rotation) + -# The node will be skewed (skewX, skewY) + -# The node will be scaled (scale, scaleX, scaleY) + -# The node will be moved according to the camera values (camera) + + Order in transformations with grid enabled + -# The node will be translated (position) + -# The node will be rotated (rotation, rotationX, rotationY) + -# The node will be skewed (skewX, skewY) + -# The node will be scaled (scale, scaleX, scaleY) + -# The grid will capture the screen + -# The node will be moved according to the camera values (camera) + -# The grid will render the captured screen + + Camera: + - Each node has a camera. By default it points to the center of the CCNode. + */ +@interface CCNode : NSObject +{ + // rotation angle + float _rotationX, _rotationY; + + // scaling factors + float _scaleX, _scaleY; + + // openGL real Z vertex + float _vertexZ; + + // position of the node + CGPoint _position; + + // skew angles + float _skewX, _skewY; + + // anchor point in points + CGPoint _anchorPointInPoints; + // anchor point normalized (NOT in points) + CGPoint _anchorPoint; + + // untransformed size of the node + CGSize _contentSize; + + // transform + CGAffineTransform _transform, _inverse; + BOOL _isTransformDirty; + BOOL _isInverseDirty; + + // a Camera + CCCamera *_camera; + + // a Grid + CCGridBase *_grid; + + // z-order value + NSInteger _zOrder; + + // array of children + CCArray *_children; + + // weak ref to parent + CCNode *_parent; + + // a tag. any number you want to assign to the node + NSInteger _tag; + + // user data field + void *_userData; + id _userObject; + + // Shader + CCGLProgram *_shaderProgram; + + // Server side state + ccGLServerState _glServerState; + + // used to preserve sequence while sorting children with the same zOrder + NSUInteger _orderOfArrival; + + // scheduler used to schedule timers and updates + CCScheduler *_scheduler; + + // ActionManager used to handle all the actions + CCActionManager *_actionManager; + + // Is running + BOOL _isRunning; + + // is visible + BOOL _visible; + // If YES, the Anchor Point will be (0,0) when you position the CCNode. + // Used by CCLayer and CCScene + BOOL _ignoreAnchorPointForPosition; + + BOOL _isReorderChildDirty; +} + +/** The z order of the node relative to its "siblings": children of the same parent */ +@property(nonatomic,assign) NSInteger zOrder; +/** The real openGL Z vertex. + Differences between openGL Z vertex and cocos2d Z order: + - OpenGL Z modifies the Z vertex, and not the Z order in the relation between parent-children + - OpenGL Z might require to set 2D projection + - cocos2d Z order works OK if all the nodes uses the same openGL Z vertex. eg: vertexZ = 0 + @warning: Use it at your own risk since it might break the cocos2d parent-children z order + @since v0.8 + */ +@property (nonatomic,readwrite) float vertexZ; + +/** The X skew angle of the node in degrees. + This angle describes the shear distortion in the X direction. + Thus, it is the angle between the Y axis and the left edge of the shape + The default skewX angle is 0. Positive values distort the node in a CW direction. + */ +@property(nonatomic,readwrite,assign) float skewX; + +/** The Y skew angle of the node in degrees. + This angle describes the shear distortion in the Y direction. + Thus, it is the angle between the X axis and the bottom edge of the shape + The default skewY angle is 0. Positive values distort the node in a CCW direction. + */ +@property(nonatomic,readwrite,assign) float skewY; +/** The rotation (angle) of the node in degrees. 0 is the default rotation angle. Positive values rotate node CW. */ +@property(nonatomic,readwrite,assign) float rotation; +/** The rotation (angle) of the node in degrees. 0 is the default rotation angle. Positive values rotate node CW. It only modifies the X rotation performing a horizontal rotational skew . */ +@property(nonatomic,readwrite,assign) float rotationX; +/** The rotation (angle) of the node in degrees. 0 is the default rotation angle. Positive values rotate node CW. It only modifies the Y rotation performing a vertical rotational skew . */ +@property(nonatomic,readwrite,assign) float rotationY; + +/** The scale factor of the node. 1.0 is the default scale factor. It modifies the X and Y scale at the same time. */ +@property(nonatomic,readwrite,assign) float scale; +/** The scale factor of the node. 1.0 is the default scale factor. It only modifies the X scale factor. */ +@property(nonatomic,readwrite,assign) float scaleX; +/** The scale factor of the node. 1.0 is the default scale factor. It only modifies the Y scale factor. */ +@property(nonatomic,readwrite,assign) float scaleY; +/** Position (x,y) of the node in points. (0,0) is the left-bottom corner. */ +@property(nonatomic,readwrite,assign) CGPoint position; +/** A CCCamera object that lets you move the node using a gluLookAt */ +@property(nonatomic,readonly) CCCamera* camera; +/** Array of children */ +@property(nonatomic,readonly) CCArray *children; +/** A CCGrid object that is used when applying effects */ +@property(nonatomic,readwrite,retain) CCGridBase* grid; +/** Whether of not the node is visible. Default is YES */ +@property(nonatomic,readwrite,assign) BOOL visible; +/** anchorPoint is the point around which all transformations and positioning manipulations take place. + It's like a pin in the node where it is "attached" to its parent. + The anchorPoint is normalized, like a percentage. (0,0) means the bottom-left corner and (1,1) means the top-right corner. + But you can use values higher than (1,1) and lower than (0,0) too. + The default anchorPoint is (0,0). It starts in the bottom-left corner. CCSprite and other subclasses have a different default anchorPoint. + @since v0.8 + */ +@property(nonatomic,readwrite) CGPoint anchorPoint; +/** The anchorPoint in absolute pixels. + Since v0.8 you can only read it. If you wish to modify it, use anchorPoint instead + */ +@property(nonatomic,readonly) CGPoint anchorPointInPoints; + +/** The untransformed size of the node in Points + The contentSize remains the same no matter the node is scaled or rotated. + All nodes has a size. Layer and Scene has the same size of the screen. + @since v0.8 + */ +@property (nonatomic,readwrite) CGSize contentSize; + +/** whether or not the node is running */ +@property(nonatomic,readonly) BOOL isRunning; +/** A weak reference to the parent */ +@property(nonatomic,readwrite,assign) CCNode* parent; +/** If YES, the Anchor Point will be (0,0) when you position the CCNode. + Used by CCLayer and CCScene. + */ +@property(nonatomic,readwrite,assign) BOOL ignoreAnchorPointForPosition; +/** A tag used to identify the node easily */ +@property(nonatomic,readwrite,assign) NSInteger tag; +/** A custom user data pointer */ +@property(nonatomic,readwrite,assign) void* userData; +/** Similar to userData, but instead of holding a void* it holds an id */ +@property(nonatomic,readwrite,retain) id userObject; + +/** Shader Program + @since v2.0 + */ +@property(nonatomic,readwrite,retain) CCGLProgram *shaderProgram; + +/** used internally for zOrder sorting, don't change this manually */ +@property(nonatomic,readwrite) NSUInteger orderOfArrival; + +/** GL server side state + @since v2.0 +*/ +@property (nonatomic, readwrite) ccGLServerState glServerState; + +/** CCActionManager used by all the actions. + IMPORTANT: If you set a new CCActionManager, then previously created actions are going to be removed. + @since v2.0 + */ +@property (nonatomic, readwrite, retain) CCActionManager *actionManager; + +/** CCScheduler used to schedule all "updates" and timers. + IMPORTANT: If you set a new CCScheduler, then previously created timers/update are going to be removed. + @since v2.0 + */ +@property (nonatomic, readwrite, retain) CCScheduler *scheduler; + +// initializators +/** allocates and initializes a node. + The node will be created as "autorelease". + */ ++(id) node; +/** initializes the node */ +-(id) init; + +// scene management + +/** Event that is called every time the CCNode enters the 'stage'. + If the CCNode enters the 'stage' with a transition, this event is called when the transition starts. + During onEnter you can't access a sibling node. + If you override onEnter, you shall call [super onEnter]. + */ +-(void) onEnter; + +/** Event that is called when the CCNode enters in the 'stage'. + If the CCNode enters the 'stage' with a transition, this event is called when the transition finishes. + If you override onEnterTransitionDidFinish, you shall call [super onEnterTransitionDidFinish]. + @since v0.8 + */ +-(void) onEnterTransitionDidFinish; + +/** Event that is called every time the CCNode leaves the 'stage'. + If the CCNode leaves the 'stage' with a transition, this event is called when the transition finishes. + During onExit you can't access a sibling node. + If you override onExit, you shall call [super onExit]. + */ +-(void) onExit; + +/** callback that is called every time the CCNode leaves the 'stage'. + If the CCNode leaves the 'stage' with a transition, this callback is called when the transition starts. + */ +-(void) onExitTransitionDidStart; + +// composition: ADD + +/** Adds a child to the container with z-order as 0. + If the child is added to a 'running' node, then 'onEnter' and 'onEnterTransitionDidFinish' will be called immediately. + @since v0.7.1 + */ +-(void) addChild: (CCNode*)node; + +/** Adds a child to the container with a z-order. + If the child is added to a 'running' node, then 'onEnter' and 'onEnterTransitionDidFinish' will be called immediately. + @since v0.7.1 + */ +-(void) addChild: (CCNode*)node z:(NSInteger)z; + +/** Adds a child to the container with z order and tag. + If the child is added to a 'running' node, then 'onEnter' and 'onEnterTransitionDidFinish' will be called immediately. + @since v0.7.1 + */ +-(void) addChild: (CCNode*)node z:(NSInteger)z tag:(NSInteger)tag; + +// composition: REMOVE + +/** Remove itself from its parent node forcing a cleanup. + If the node orphan, then nothing happens. + @since v2.1 + */ +-(void) removeFromParent; + +/** Remove itself from its parent node. If cleanup is YES, then also remove all actions and callbacks. + If the node orphan, then nothing happens. + @since v0.99.3 + */ +-(void) removeFromParentAndCleanup:(BOOL)cleanup; + +/** Removes a child from the container forcing a cleanup + @since v2.1 + */ +-(void) removeChild:(CCNode*)child; + +/** Removes a child from the container. It will also cleanup all running actions depending on the cleanup parameter. + @since v0.7.1 + */ +-(void) removeChild: (CCNode*)node cleanup:(BOOL)cleanup; + +/** Removes a child from the container by tag value forcing a cleanup. + @since v2.1 + */ +-(void) removeChildByTag:(NSInteger) tag; + +/** Removes a child from the container by tag value. It will also cleanup all running actions depending on the cleanup parameter + @since v0.7.1 + */ +-(void) removeChildByTag:(NSInteger) tag cleanup:(BOOL)cleanup; + +/** Removes all children from the container forcing a cleanup. + @since v2.1 + */ +-(void) removeAllChildren; + +/** Removes all children from the container and do a cleanup all running actions depending on the cleanup parameter. + @since v0.7.1 + */ +-(void) removeAllChildrenWithCleanup:(BOOL)cleanup; + +// composition: GET +/** Gets a child from the container given its tag + @return returns a CCNode object + @since v0.7.1 + */ +-(CCNode*) getChildByTag:(NSInteger) tag; + +/** Reorders a child according to a new z value. + * The child MUST be already added. + */ +-(void) reorderChild:(CCNode*)child z:(NSInteger)zOrder; + +/** performance improvement, Sort the children array once before drawing, instead of every time when a child is added or reordered + don't call this manually unless a child added needs to be removed in the same frame */ +- (void) sortAllChildren; + +/** Event that is called when the running node is no longer running (eg: its CCScene is being removed from the "stage" ). + On cleanup you should break any possible circular references. + CCNode's cleanup removes any possible scheduled timer and/or any possible action. + If you override cleanup, you shall call [super cleanup] + @since v0.8 + */ +-(void) cleanup; + +// draw + +/** Override this method to draw your own node. + You should use cocos2d's GL API to enable/disable the GL state / shaders. + For further info, please see ccGLstate.h. + You shall NOT call [super draw]; + */ +-(void) draw; + +/** recursive method that visit its children and draw them */ +-(void) visit; + +// transformations + +/** performs OpenGL view-matrix transformation based on position, scale, rotation and other attributes. */ +-(void) transform; + +/** performs OpenGL view-matrix transformation of its ancestors. + Generally the ancestors are already transformed, but in certain cases (eg: attaching a FBO) it is necessary to transform the ancestors again. + @since v0.7.2 + */ +-(void) transformAncestors; + +/** returns a "local" axis aligned bounding box of the node in points. + The returned box is relative only to its parent. + The returned box is in Points. + + @since v0.8.2 + */ +- (CGRect) boundingBox; + +// actions + +/** Executes an action, and returns the action that is executed. + The node becomes the action's target. + @warning Starting from v0.8 actions don't retain their target anymore. + @since v0.7.1 + @return An Action pointer + */ +-(CCAction*) runAction: (CCAction*) action; +/** Removes all actions from the running action list */ +-(void) stopAllActions; +/** Removes an action from the running action list */ +-(void) stopAction: (CCAction*) action; +/** Removes an action from the running action list given its tag + @since v0.7.1 +*/ +-(void) stopActionByTag:(NSInteger) tag; +/** Gets an action from the running action list given its tag + @since v0.7.1 + @return the Action the with the given tag + */ +-(CCAction*) getActionByTag:(NSInteger) tag; +/** Returns the numbers of actions that are running plus the ones that are schedule to run (actions in actionsToAdd and actions arrays). + * Composable actions are counted as 1 action. Example: + * If you are running 1 Sequence of 7 actions, it will return 1. + * If you are running 7 Sequences of 2 actions, it will return 7. + */ +-(NSUInteger) numberOfRunningActions; + +// timers + +/** check whether a selector is scheduled. */ +//-(BOOL) isScheduled: (SEL) selector; + +/** schedules the "update" method. It will use the order number 0. This method will be called every frame. + Scheduled methods with a lower order value will be called before the ones that have a higher order value. + Only one "update" method could be scheduled per node. + + @since v0.99.3 + */ +-(void) scheduleUpdate; + +/** schedules the "update" selector with a custom priority. This selector will be called every frame. + Scheduled selectors with a lower priority will be called before the ones that have a higher value. + Only one "update" selector could be scheduled per node (You can't have 2 'update' selectors). + + @since v0.99.3 + */ +-(void) scheduleUpdateWithPriority:(NSInteger)priority; + +/* unschedules the "update" method. + + @since v0.99.3 + */ +-(void) unscheduleUpdate; + +/** schedules a selector. + The scheduled selector will be ticked every frame + */ +-(void) schedule: (SEL) s; +/** schedules a custom selector with an interval time in seconds. + If time is 0 it will be ticked every frame. + If time is 0, it is recommended to use 'scheduleUpdate' instead. + + If the selector is already scheduled, then the interval parameter will be updated without scheduling it again. + */ +-(void) schedule: (SEL) s interval:(ccTime)seconds; +/** + repeat will execute the action repeat + 1 times, for a continues action use kCCRepeatForever + delay is the amount of time the action will wait before execution + */ +-(void) schedule:(SEL)selector interval:(ccTime)interval repeat: (uint) repeat delay:(ccTime) delay; + +/** + Schedules a selector that runs only once, with a delay of 0 or larger +*/ +- (void) scheduleOnce:(SEL) selector delay:(ccTime) delay; + +/** unschedules a custom selector.*/ +-(void) unschedule: (SEL) s; + +/** unschedule all scheduled selectors: custom selectors, and the 'update' selector. + Actions are not affected by this method. +@since v0.99.3 + */ +-(void) unscheduleAllSelectors; + +/** resumes all scheduled selectors and actions. + Called internally by onEnter + */ +-(void) resumeSchedulerAndActions; +/** pauses all scheduled selectors and actions. + Called internally by onExit + */ +-(void) pauseSchedulerAndActions; + +/* Update will be called automatically every frame if "scheduleUpdate" is called, and the node is "live" + */ +-(void) update:(ccTime)delta; + +// transformation methods + +/** Returns the matrix that transform the node's (local) space coordinates into the parent's space coordinates. + The matrix is in Pixels. + @since v0.7.1 + */ +- (CGAffineTransform)nodeToParentTransform; +/** Returns the matrix that transform parent's space coordinates to the node's (local) space coordinates. + The matrix is in Pixels. + @since v0.7.1 + */ +- (CGAffineTransform)parentToNodeTransform; +/** Returns the world affine transform matrix. The matrix is in Pixels. + @since v0.7.1 + */ +- (CGAffineTransform)nodeToWorldTransform; +/** Returns the inverse world affine transform matrix. The matrix is in Pixels. + @since v0.7.1 + */ +- (CGAffineTransform)worldToNodeTransform; +/** Converts a Point to node (local) space coordinates. The result is in Points. + @since v0.7.1 + */ +- (CGPoint)convertToNodeSpace:(CGPoint)worldPoint; +/** Converts a Point to world space coordinates. The result is in Points. + @since v0.7.1 + */ +- (CGPoint)convertToWorldSpace:(CGPoint)nodePoint; +/** Converts a Point to node (local) space coordinates. The result is in Points. + treating the returned/received node point as anchor relative. + @since v0.7.1 + */ +- (CGPoint)convertToNodeSpaceAR:(CGPoint)worldPoint; +/** Converts a local Point to world space coordinates.The result is in Points. + treating the returned/received node point as anchor relative. + @since v0.7.1 + */ +- (CGPoint)convertToWorldSpaceAR:(CGPoint)nodePoint; + +#ifdef __CC_PLATFORM_IOS +/** Converts a UITouch to node (local) space coordinates. The result is in Points. + @since v0.7.1 + */ +- (CGPoint)convertTouchToNodeSpace:(UITouch *)touch; +/** Converts a UITouch to node (local) space coordinates. The result is in Points. + This method is AR (Anchor Relative).. + @since v0.7.1 + */ +- (CGPoint)convertTouchToNodeSpaceAR:(UITouch *)touch; +#endif // __CC_PLATFORM_IOS +@end + + +#pragma mark - CCNodeRGBA + +/** CCNodeRGBA is a subclass of CCNode that implements the CCRGBAProtocol protocol. + + All features from CCNode are valid, plus the following new features: + - opacity + - RGB colors + + Opacity/Color propagates into children that conform to the CCRGBAProtocol if cascadeOpacity/cascadeColor is enabled. + @since v2.1 + */ +@interface CCNodeRGBA : CCNode +{ + GLubyte _displayedOpacity, _realOpacity; + ccColor3B _displayedColor, _realColor; + BOOL _cascadeColorEnabled, _cascadeOpacityEnabled; +} + +// XXX To make BridgeSupport happy +-(GLubyte) opacity; + +@end diff --git "a/21451198\345\215\242\350\266\205/project5/MyPlane/libs/cocos2d/CCNode.m" "b/21451198\345\215\242\350\266\205/project5/MyPlane/libs/cocos2d/CCNode.m" new file mode 100644 index 00000000..e926e871 --- /dev/null +++ "b/21451198\345\215\242\350\266\205/project5/MyPlane/libs/cocos2d/CCNode.m" @@ -0,0 +1,1032 @@ +/* + * cocos2d for iPhone: http://www.cocos2d-iphone.org + * + * Copyright (c) 2009 Valentin Milea + * + * Copyright (c) 2008-2010 Ricardo Quesada + * Copyright (c) 2011 Zynga Inc. + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + * THE SOFTWARE. + */ + +#import "CCNode.h" +#import "CCGrid.h" +#import "CCDirector.h" +#import "CCActionManager.h" +#import "CCCamera.h" +#import "CCScheduler.h" +#import "ccConfig.h" +#import "ccMacros.h" +#import "Support/CGPointExtension.h" +#import "Support/ccCArray.h" +#import "Support/TransformUtils.h" +#import "ccMacros.h" +#import "CCGLProgram.h" + +// externals +#import "kazmath/GL/matrix.h" + +#ifdef __CC_PLATFORM_IOS +#import "Platforms/iOS/CCDirectorIOS.h" +#endif + + +#if CC_NODE_RENDER_SUBPIXEL +#define RENDER_IN_SUBPIXEL +#else +#define RENDER_IN_SUBPIXEL(__ARGS__) (ceil(__ARGS__)) +#endif + + +#pragma mark - Node + +@interface CCNode () +// lazy allocs +-(void) childrenAlloc; +// helper that reorder a child +-(void) insertChild:(CCNode*)child z:(NSInteger)z; +// used internally to alter the zOrder variable. DON'T call this method manually +-(void) _setZOrder:(NSInteger) z; +-(void) detachChild:(CCNode *)child cleanup:(BOOL)doCleanup; +@end + +@implementation CCNode + +// XXX: Yes, nodes might have a sort problem once every 15 days if the game runs at 60 FPS and each frame sprites are reordered. +static NSUInteger globalOrderOfArrival = 1; + +@synthesize children = _children; +@synthesize visible = _visible; +@synthesize parent = _parent; +@synthesize grid = _grid; +@synthesize zOrder = _zOrder; +@synthesize tag = _tag; +@synthesize vertexZ = _vertexZ; +@synthesize isRunning = _isRunning; +@synthesize userData = _userData, userObject = _userObject; +@synthesize shaderProgram = _shaderProgram; +@synthesize orderOfArrival = _orderOfArrival; +@synthesize glServerState = _glServerState; + +#pragma mark CCNode - Transform related properties + +@synthesize rotationX = _rotationX, rotationY = _rotationY, scaleX = _scaleX, scaleY = _scaleY; +@synthesize position = _position; +@synthesize anchorPoint = _anchorPoint, anchorPointInPoints = _anchorPointInPoints; +@synthesize contentSize = _contentSize; +@synthesize ignoreAnchorPointForPosition = _ignoreAnchorPointForPosition; +@synthesize skewX = _skewX, skewY = _skewY; + +#pragma mark CCNode - Init & cleanup + ++(id) node +{ + return [[[self alloc] init] autorelease]; +} + +-(id) init +{ + if ((self=[super init]) ) { + + _isRunning = NO; + + _skewX = _skewY = 0.0f; + _rotationX = _rotationY = 0.0f; + _scaleX = _scaleY = 1.0f; + _position = CGPointZero; + _contentSize = CGSizeZero; + _anchorPointInPoints = _anchorPoint = CGPointZero; + + + // "whole screen" objects. like Scenes and Layers, should set ignoreAnchorPointForPosition to YES + _ignoreAnchorPointForPosition = NO; + + _isTransformDirty = _isInverseDirty = YES; + + _vertexZ = 0; + + _grid = nil; + + _visible = YES; + + _tag = kCCNodeTagInvalid; + + _zOrder = 0; + + // lazy alloc + _camera = nil; + + // children (lazy allocs) + _children = nil; + + // userData is always inited as nil + _userData = NULL; + _userObject = nil; + + //initialize parent to nil + _parent = nil; + + _shaderProgram = nil; + + _orderOfArrival = 0; + + _glServerState = 0; + + // set default scheduler and actionManager + CCDirector *director = [CCDirector sharedDirector]; + self.actionManager = [director actionManager]; + self.scheduler = [director scheduler]; + } + + return self; +} + +- (void)cleanup +{ + // actions + [self stopAllActions]; + [self unscheduleAllSelectors]; + + // timers + [_children makeObjectsPerformSelector:@selector(cleanup)]; +} + +- (NSString*) description +{ + return [NSString stringWithFormat:@"<%@ = %p | Tag = %ld>", [self class], self, (long)_tag]; +} + +- (void) dealloc +{ + CCLOGINFO( @"cocos2d: deallocing %@", self); + + [_actionManager release]; + [_scheduler release]; + [_camera release]; + [_grid release]; + [_shaderProgram release]; + [_userObject release]; + + // children + CCNode *child; + CCARRAY_FOREACH(_children, child) + child.parent = nil; + + [_children release]; + + [super dealloc]; +} + +#pragma mark Setters + +// getters synthesized, setters explicit +-(void) setRotation: (float)newRotation +{ + _rotationX = _rotationY = newRotation; + _isTransformDirty = _isInverseDirty = YES; +} + +-(float) rotation +{ + NSAssert( _rotationX == _rotationY, @"CCNode#rotation. RotationX != RotationY. Don't know which one to return"); + return _rotationX; +} + +-(void) setRotationX: (float)newX +{ + _rotationX = newX; + _isTransformDirty = _isInverseDirty = YES; +} + +-(void) setRotationY: (float)newY +{ + _rotationY = newY; + _isTransformDirty = _isInverseDirty = YES; +} + +-(void) setScaleX: (float)newScaleX +{ + _scaleX = newScaleX; + _isTransformDirty = _isInverseDirty = YES; +} + +-(void) setScaleY: (float)newScaleY +{ + _scaleY = newScaleY; + _isTransformDirty = _isInverseDirty = YES; +} + +-(void) setSkewX:(float)newSkewX +{ + _skewX = newSkewX; + _isTransformDirty = _isInverseDirty = YES; +} + +-(void) setSkewY:(float)newSkewY +{ + _skewY = newSkewY; + _isTransformDirty = _isInverseDirty = YES; +} + +-(void) setPosition: (CGPoint)newPosition +{ + _position = newPosition; + _isTransformDirty = _isInverseDirty = YES; +} + +-(void) setIgnoreAnchorPointForPosition: (BOOL)newValue +{ + if( newValue != _ignoreAnchorPointForPosition ) { + _ignoreAnchorPointForPosition = newValue; + _isTransformDirty = _isInverseDirty = YES; + } +} + +-(void) setAnchorPoint:(CGPoint)point +{ + if( ! CGPointEqualToPoint(point, _anchorPoint) ) { + _anchorPoint = point; + _anchorPointInPoints = ccp( _contentSize.width * _anchorPoint.x, _contentSize.height * _anchorPoint.y ); + _isTransformDirty = _isInverseDirty = YES; + } +} + +-(void) setContentSize:(CGSize)size +{ + if( ! CGSizeEqualToSize(size, _contentSize) ) { + _contentSize = size; + + _anchorPointInPoints = ccp( _contentSize.width * _anchorPoint.x, _contentSize.height * _anchorPoint.y ); + _isTransformDirty = _isInverseDirty = YES; + } +} + +- (CGRect) boundingBox +{ + CGRect rect = CGRectMake(0, 0, _contentSize.width, _contentSize.height); + return CGRectApplyAffineTransform(rect, [self nodeToParentTransform]); +} + +-(void) setVertexZ:(float)vertexZ +{ + _vertexZ = vertexZ; +} + +-(float) scale +{ + NSAssert( _scaleX == _scaleY, @"CCNode#scale. ScaleX != ScaleY. Don't know which one to return"); + return _scaleX; +} + +-(void) setScale:(float) s +{ + _scaleX = _scaleY = s; + _isTransformDirty = _isInverseDirty = YES; +} + +- (void) setZOrder:(NSInteger)zOrder +{ + [self _setZOrder:zOrder]; + + if (_parent) + [_parent reorderChild:self z:zOrder]; +} + +#pragma mark CCNode Composition + +-(void) childrenAlloc +{ + _children = [[CCArray alloc] initWithCapacity:4]; +} + +// camera: lazy alloc +-(CCCamera*) camera +{ + if( ! _camera ) { + _camera = [[CCCamera alloc] init]; + + // by default, center camera at the Sprite's anchor point +// [_camera setCenterX:_anchorPointInPoints.x centerY:_anchorPointInPoints.y centerZ:0]; +// [_camera setEyeX:_anchorPointInPoints.x eyeY:_anchorPointInPoints.y eyeZ:1]; + +// [_camera setCenterX:0 centerY:0 centerZ:0]; +// [_camera setEyeX:0 eyeY:0 eyeZ:1]; + } + + return _camera; +} + +-(CCNode*) getChildByTag:(NSInteger) aTag +{ + NSAssert( aTag != kCCNodeTagInvalid, @"Invalid tag"); + + CCNode *node; + CCARRAY_FOREACH(_children, node){ + if( node.tag == aTag ) + return node; + } + // not found + return nil; +} + +/* "add" logic MUST only be on this method + * If a class want's to extend the 'addChild' behaviour it only needs + * to override this method + */ +-(void) addChild: (CCNode*) child z:(NSInteger)z tag:(NSInteger) aTag +{ + NSAssert( child != nil, @"Argument must be non-nil"); + NSAssert( child.parent == nil, @"child already added. It can't be added again"); + + if( ! _children ) + [self childrenAlloc]; + + [self insertChild:child z:z]; + + child.tag = aTag; + + [child setParent: self]; + + [child setOrderOfArrival: globalOrderOfArrival++]; + + if( _isRunning ) { + [child onEnter]; + [child onEnterTransitionDidFinish]; + } +} + +-(void) addChild: (CCNode*) child z:(NSInteger)z +{ + NSAssert( child != nil, @"Argument must be non-nil"); + [self addChild:child z:z tag:child.tag]; +} + +-(void) addChild: (CCNode*) child +{ + NSAssert( child != nil, @"Argument must be non-nil"); + [self addChild:child z:child.zOrder tag:child.tag]; +} + +-(void) removeFromParent +{ + [self removeFromParentAndCleanup:YES]; +} + +-(void) removeFromParentAndCleanup:(BOOL)cleanup +{ + [_parent removeChild:self cleanup:cleanup]; +} + +-(void) removeChild: (CCNode*)child +{ + [self removeChild:child cleanup:YES]; +} + +/* "remove" logic MUST only be on this method + * If a class wants to extend the 'removeChild' behavior it only needs + * to override this method + */ +-(void) removeChild: (CCNode*)child cleanup:(BOOL)cleanup +{ + // explicit nil handling + if (child == nil) + return; + + if ( [_children containsObject:child] ) + [self detachChild:child cleanup:cleanup]; +} + +-(void) removeChildByTag:(NSInteger)aTag +{ + [self removeChildByTag:aTag cleanup:YES]; +} + +-(void) removeChildByTag:(NSInteger)aTag cleanup:(BOOL)cleanup +{ + NSAssert( aTag != kCCNodeTagInvalid, @"Invalid tag"); + + CCNode *child = [self getChildByTag:aTag]; + + if (child == nil) + CCLOG(@"cocos2d: removeChildByTag: child not found!"); + else + [self removeChild:child cleanup:cleanup]; +} + +-(void) removeAllChildren +{ + [self removeAllChildrenWithCleanup:YES]; +} + +-(void) removeAllChildrenWithCleanup:(BOOL)cleanup +{ + // not using detachChild improves speed here + CCNode *c; + CCARRAY_FOREACH(_children, c) + { + // IMPORTANT: + // -1st do onExit + // -2nd cleanup + if (_isRunning) + { + [c onExitTransitionDidStart]; + [c onExit]; + } + + if (cleanup) + [c cleanup]; + + // set parent nil at the end (issue #476) + [c setParent:nil]; + } + + [_children removeAllObjects]; +} + +-(void) detachChild:(CCNode *)child cleanup:(BOOL)doCleanup +{ + // IMPORTANT: + // -1st do onExit + // -2nd cleanup + if (_isRunning) + { + [child onExitTransitionDidStart]; + [child onExit]; + } + + // If you don't do cleanup, the child's actions will not get removed and the + // its scheduledSelectors_ dict will not get released! + if (doCleanup) + [child cleanup]; + + // set parent nil at the end (issue #476) + [child setParent:nil]; + + [_children removeObject:child]; +} + +// used internally to alter the zOrder variable. DON'T call this method manually +-(void) _setZOrder:(NSInteger) z +{ + _zOrder = z; +} + +// helper used by reorderChild & add +-(void) insertChild:(CCNode*)child z:(NSInteger)z +{ + _isReorderChildDirty=YES; + + ccArrayAppendObjectWithResize(_children->data, child); + [child _setZOrder:z]; +} + +-(void) reorderChild:(CCNode*) child z:(NSInteger)z +{ + NSAssert( child != nil, @"Child must be non-nil"); + + _isReorderChildDirty = YES; + + [child setOrderOfArrival: globalOrderOfArrival++]; + [child _setZOrder:z]; +} + +- (void) sortAllChildren +{ + if (_isReorderChildDirty) + { + NSInteger i,j,length = _children->data->num; + CCNode ** x = _children->data->arr; + CCNode *tempItem; + + // insertion sort + for(i=1; i=0 && ( tempItem.zOrder < x[j].zOrder || ( tempItem.zOrder== x[j].zOrder && tempItem.orderOfArrival < x[j].orderOfArrival ) ) ) + { + x[j+1] = x[j]; + j = j-1; + } + x[j+1] = tempItem; + } + + //don't need to check children recursively, that's done in visit of each child + + _isReorderChildDirty = NO; + } +} + +#pragma mark CCNode Draw + +-(void) draw +{ +} + +-(void) visit +{ + // quick return if not visible. children won't be drawn. + if (!_visible) + return; + + kmGLPushMatrix(); + + if ( _grid && _grid.active) + [_grid beforeDraw]; + + [self transform]; + + if(_children) { + + [self sortAllChildren]; + + ccArray *arrayData = _children->data; + NSUInteger i = 0; + + // draw children zOrder < 0 + for( ; i < arrayData->num; i++ ) { + CCNode *child = arrayData->arr[i]; + if ( [child zOrder] < 0 ) + [child visit]; + else + break; + } + + // self draw + [self draw]; + + // draw children zOrder >= 0 + for( ; i < arrayData->num; i++ ) { + CCNode *child = arrayData->arr[i]; + [child visit]; + } + + } else + [self draw]; + + // reset for next frame + _orderOfArrival = 0; + + if ( _grid && _grid.active) + [_grid afterDraw:self]; + + kmGLPopMatrix(); +} + +#pragma mark CCNode - Transformations + +-(void) transformAncestors +{ + if( _parent ) { + [_parent transformAncestors]; + [_parent transform]; + } +} + +-(void) transform +{ + kmMat4 transfrom4x4; + + // Convert 3x3 into 4x4 matrix + CGAffineTransform tmpAffine = [self nodeToParentTransform]; + CGAffineToGL(&tmpAffine, transfrom4x4.mat); + + // Update Z vertex manually + transfrom4x4.mat[14] = _vertexZ; + + kmGLMultMatrix( &transfrom4x4 ); + + + // XXX: Expensive calls. Camera should be integrated into the cached affine matrix + if ( _camera && !(_grid && _grid.active) ) + { + BOOL translate = (_anchorPointInPoints.x != 0.0f || _anchorPointInPoints.y != 0.0f); + + if( translate ) + kmGLTranslatef(RENDER_IN_SUBPIXEL(_anchorPointInPoints.x), RENDER_IN_SUBPIXEL(_anchorPointInPoints.y), 0 ); + + [_camera locate]; + + if( translate ) + kmGLTranslatef(RENDER_IN_SUBPIXEL(-_anchorPointInPoints.x), RENDER_IN_SUBPIXEL(-_anchorPointInPoints.y), 0 ); + } +} + +#pragma mark CCNode SceneManagement + +-(void) onEnter +{ + [_children makeObjectsPerformSelector:@selector(onEnter)]; + [self resumeSchedulerAndActions]; + + _isRunning = YES; +} + +-(void) onEnterTransitionDidFinish +{ + [_children makeObjectsPerformSelector:@selector(onEnterTransitionDidFinish)]; +} + +-(void) onExitTransitionDidStart +{ + [_children makeObjectsPerformSelector:@selector(onExitTransitionDidStart)]; +} + +-(void) onExit +{ + [self pauseSchedulerAndActions]; + _isRunning = NO; + + [_children makeObjectsPerformSelector:@selector(onExit)]; +} + +#pragma mark CCNode Actions + +-(void) setActionManager:(CCActionManager *)actionManager +{ + if( actionManager != _actionManager ) { + [self stopAllActions]; + [_actionManager release]; + + _actionManager = [actionManager retain]; + } +} + +-(CCActionManager*) actionManager +{ + return _actionManager; +} + +-(CCAction*) runAction:(CCAction*) action +{ + NSAssert( action != nil, @"Argument must be non-nil"); + + [_actionManager addAction:action target:self paused:!_isRunning]; + return action; +} + +-(void) stopAllActions +{ + [_actionManager removeAllActionsFromTarget:self]; +} + +-(void) stopAction: (CCAction*) action +{ + [_actionManager removeAction:action]; +} + +-(void) stopActionByTag:(NSInteger)aTag +{ + NSAssert( aTag != kCCActionTagInvalid, @"Invalid tag"); + [_actionManager removeActionByTag:aTag target:self]; +} + +-(CCAction*) getActionByTag:(NSInteger) aTag +{ + NSAssert( aTag != kCCActionTagInvalid, @"Invalid tag"); + return [_actionManager getActionByTag:aTag target:self]; +} + +-(NSUInteger) numberOfRunningActions +{ + return [_actionManager numberOfRunningActionsInTarget:self]; +} + +#pragma mark CCNode - Scheduler + +-(void) setScheduler:(CCScheduler *)scheduler +{ + if( scheduler != _scheduler ) { + [self unscheduleAllSelectors]; + [_scheduler release]; + + _scheduler = [scheduler retain]; + } +} + +-(CCScheduler*) scheduler +{ + return _scheduler; +} + +-(void) scheduleUpdate +{ + [self scheduleUpdateWithPriority:0]; +} + +-(void) scheduleUpdateWithPriority:(NSInteger)priority +{ + [_scheduler scheduleUpdateForTarget:self priority:priority paused:!_isRunning]; +} + +-(void) unscheduleUpdate +{ + [_scheduler unscheduleUpdateForTarget:self]; +} + +-(void) schedule:(SEL)selector +{ + [self schedule:selector interval:0 repeat:kCCRepeatForever delay:0]; +} + +-(void) schedule:(SEL)selector interval:(ccTime)interval +{ + [self schedule:selector interval:interval repeat:kCCRepeatForever delay:0]; +} + +-(void) schedule:(SEL)selector interval:(ccTime)interval repeat: (uint) repeat delay:(ccTime) delay +{ + NSAssert( selector != nil, @"Argument must be non-nil"); + NSAssert( interval >=0, @"Arguemnt must be positive"); + + [_scheduler scheduleSelector:selector forTarget:self interval:interval repeat:repeat delay:delay paused:!_isRunning]; +} + +- (void) scheduleOnce:(SEL) selector delay:(ccTime) delay +{ + [self schedule:selector interval:0.f repeat:0 delay:delay]; +} + +-(void) unschedule:(SEL)selector +{ + // explicit nil handling + if (selector == nil) + return; + + [_scheduler unscheduleSelector:selector forTarget:self]; +} + +-(void) unscheduleAllSelectors +{ + [_scheduler unscheduleAllForTarget:self]; +} +- (void) resumeSchedulerAndActions +{ + [_scheduler resumeTarget:self]; + [_actionManager resumeTarget:self]; +} + +- (void) pauseSchedulerAndActions +{ + [_scheduler pauseTarget:self]; + [_actionManager pauseTarget:self]; +} + +/* override me */ +-(void) update:(ccTime)delta +{ +} + +#pragma mark CCNode Transform + +- (CGAffineTransform)nodeToParentTransform +{ + if ( _isTransformDirty ) { + + // Translate values + float x = _position.x; + float y = _position.y; + + if ( _ignoreAnchorPointForPosition ) { + x += _anchorPointInPoints.x; + y += _anchorPointInPoints.y; + } + + // Rotation values + // Change rotation code to handle X and Y + // If we skew with the exact same value for both x and y then we're simply just rotating + float cx = 1, sx = 0, cy = 1, sy = 0; + if( _rotationX || _rotationY ) { + float radiansX = -CC_DEGREES_TO_RADIANS(_rotationX); + float radiansY = -CC_DEGREES_TO_RADIANS(_rotationY); + cx = cosf(radiansX); + sx = sinf(radiansX); + cy = cosf(radiansY); + sy = sinf(radiansY); + } + + BOOL needsSkewMatrix = ( _skewX || _skewY ); + + // optimization: + // inline anchor point calculation if skew is not needed + // Adjusted transform calculation for rotational skew + if( !needsSkewMatrix && !CGPointEqualToPoint(_anchorPointInPoints, CGPointZero) ) { + x += cy * -_anchorPointInPoints.x * _scaleX + -sx * -_anchorPointInPoints.y * _scaleY; + y += sy * -_anchorPointInPoints.x * _scaleX + cx * -_anchorPointInPoints.y * _scaleY; + } + + + // Build Transform Matrix + // Adjusted transfor m calculation for rotational skew + _transform = CGAffineTransformMake( cy * _scaleX, sy * _scaleX, + -sx * _scaleY, cx * _scaleY, + x, y ); + + // XXX: Try to inline skew + // If skew is needed, apply skew and then anchor point + if( needsSkewMatrix ) { + CGAffineTransform skewMatrix = CGAffineTransformMake(1.0f, tanf(CC_DEGREES_TO_RADIANS(_skewY)), + tanf(CC_DEGREES_TO_RADIANS(_skewX)), 1.0f, + 0.0f, 0.0f ); + _transform = CGAffineTransformConcat(skewMatrix, _transform); + + // adjust anchor point + if( ! CGPointEqualToPoint(_anchorPointInPoints, CGPointZero) ) + _transform = CGAffineTransformTranslate(_transform, -_anchorPointInPoints.x, -_anchorPointInPoints.y); + } + + _isTransformDirty = NO; + } + + return _transform; +} + +- (CGAffineTransform)parentToNodeTransform +{ + if ( _isInverseDirty ) { + _inverse = CGAffineTransformInvert([self nodeToParentTransform]); + _isInverseDirty = NO; + } + + return _inverse; +} + +- (CGAffineTransform)nodeToWorldTransform +{ + CGAffineTransform t = [self nodeToParentTransform]; + + for (CCNode *p = _parent; p != nil; p = p.parent) + t = CGAffineTransformConcat(t, [p nodeToParentTransform]); + + return t; +} + +- (CGAffineTransform)worldToNodeTransform +{ + return CGAffineTransformInvert([self nodeToWorldTransform]); +} + +- (CGPoint)convertToNodeSpace:(CGPoint)worldPoint +{ + CGPoint ret = CGPointApplyAffineTransform(worldPoint, [self worldToNodeTransform]); + return ret; +} + +- (CGPoint)convertToWorldSpace:(CGPoint)nodePoint +{ + CGPoint ret = CGPointApplyAffineTransform(nodePoint, [self nodeToWorldTransform]); + return ret; +} + +- (CGPoint)convertToNodeSpaceAR:(CGPoint)worldPoint +{ + CGPoint nodePoint = [self convertToNodeSpace:worldPoint]; + return ccpSub(nodePoint, _anchorPointInPoints); +} + +- (CGPoint)convertToWorldSpaceAR:(CGPoint)nodePoint +{ + nodePoint = ccpAdd(nodePoint, _anchorPointInPoints); + return [self convertToWorldSpace:nodePoint]; +} + +- (CGPoint)convertToWindowSpace:(CGPoint)nodePoint +{ + CGPoint worldPoint = [self convertToWorldSpace:nodePoint]; + return [[CCDirector sharedDirector] convertToUI:worldPoint]; +} + +// convenience methods which take a UITouch instead of CGPoint + +#ifdef __CC_PLATFORM_IOS + +- (CGPoint)convertTouchToNodeSpace:(UITouch *)touch +{ + CGPoint point = [touch locationInView: [touch view]]; + point = [[CCDirector sharedDirector] convertToGL: point]; + return [self convertToNodeSpace:point]; +} + +- (CGPoint)convertTouchToNodeSpaceAR:(UITouch *)touch +{ + CGPoint point = [touch locationInView: [touch view]]; + point = [[CCDirector sharedDirector] convertToGL: point]; + return [self convertToNodeSpaceAR:point]; +} + +#endif // __CC_PLATFORM_IOS + +@end + + +#pragma mark - NodeRGBA + +@implementation CCNodeRGBA + +@synthesize cascadeColorEnabled=_cascadeColorEnabled; +@synthesize cascadeOpacityEnabled=_cascadeOpacityEnabled; + +-(id) init +{ + if ((self=[super init]) ) { + _displayedOpacity = _realOpacity = 255; + _displayedColor = _realColor = ccWHITE; + _cascadeOpacityEnabled = NO; + _cascadeColorEnabled = NO; + } + return self; +} + +-(GLubyte) opacity +{ + return _realOpacity; +} + +-(GLubyte) displayedOpacity +{ + return _displayedOpacity; +} + +- (void) setOpacity:(GLubyte)opacity +{ + _displayedOpacity = _realOpacity = opacity; + + if( _cascadeOpacityEnabled ) { + GLubyte parentOpacity = 255; + if( [_parent conformsToProtocol:@protocol(CCRGBAProtocol)] && [(id)_parent isCascadeOpacityEnabled] ) + parentOpacity = [(id)_parent displayedOpacity]; + [self updateDisplayedOpacity:parentOpacity]; + } +} + +- (void)updateDisplayedOpacity:(GLubyte)parentOpacity +{ + _displayedOpacity = _realOpacity * parentOpacity/255.0; + + if (_cascadeOpacityEnabled) { + id item; + CCARRAY_FOREACH(_children, item) { + if ([item conformsToProtocol:@protocol(CCRGBAProtocol)]) { + [item updateDisplayedOpacity:_displayedOpacity]; + } + } + } +} + +-(ccColor3B) color +{ + return _realColor; +} + +-(ccColor3B) displayedColor +{ + return _displayedColor; +} + +- (void) setColor:(ccColor3B)color +{ + _displayedColor = _realColor = color; + + if( _cascadeColorEnabled ) { + ccColor3B parentColor = ccWHITE; + if( [_parent conformsToProtocol:@protocol(CCRGBAProtocol)] && [(id)_parent isCascadeColorEnabled] ) + parentColor = [(id)_parent displayedColor]; + [self updateDisplayedColor:parentColor]; + } +} + +- (void)updateDisplayedColor:(ccColor3B)parentColor +{ + _displayedColor.r = _realColor.r * parentColor.r/255.0; + _displayedColor.g = _realColor.g * parentColor.g/255.0; + _displayedColor.b = _realColor.b * parentColor.b/255.0; + + if (_cascadeColorEnabled) { + id item; + CCARRAY_FOREACH(_children, item) { + if ([item conformsToProtocol:@protocol(CCRGBAProtocol)]) { + [item updateDisplayedColor:_displayedColor]; + } + } + } +} + +@end diff --git "a/21451198\345\215\242\350\266\205/project5/MyPlane/libs/cocos2d/CCParallaxNode.h" "b/21451198\345\215\242\350\266\205/project5/MyPlane/libs/cocos2d/CCParallaxNode.h" new file mode 100644 index 00000000..338e3ff7 --- /dev/null +++ "b/21451198\345\215\242\350\266\205/project5/MyPlane/libs/cocos2d/CCParallaxNode.h" @@ -0,0 +1,50 @@ +/* + * cocos2d for iPhone: http://www.cocos2d-iphone.org + * + * Copyright (c) 2009-2010 Ricardo Quesada + * Copyright (c) 2011 Zynga Inc. + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + * THE SOFTWARE. + * + */ + +#import "CCNode.h" +#import "Support/ccCArray.h" + +/** CCParallaxNode: A node that simulates a parallax scroller + + The children will be moved faster / slower than the parent according the the parallax ratio. + + */ +@interface CCParallaxNode : CCNode +{ + ccArray *_parallaxArray; + CGPoint _lastPosition; +} + +/** array that holds the offset / ratio of the children */ +@property (nonatomic,readwrite) ccArray * parallaxArray; + +/** Adds a child to the container with a z-order, a parallax ratio and a position offset + It returns self, so you can chain several addChilds. + @since v0.8 + */ +-(void) addChild: (CCNode*)node z:(NSInteger)z parallaxRatio:(CGPoint)c positionOffset:(CGPoint)positionOffset; + +@end diff --git "a/21451198\345\215\242\350\266\205/project5/MyPlane/libs/cocos2d/CCParallaxNode.m" "b/21451198\345\215\242\350\266\205/project5/MyPlane/libs/cocos2d/CCParallaxNode.m" new file mode 100644 index 00000000..77ba93ee --- /dev/null +++ "b/21451198\345\215\242\350\266\205/project5/MyPlane/libs/cocos2d/CCParallaxNode.m" @@ -0,0 +1,161 @@ +/* + * cocos2d for iPhone: http://www.cocos2d-iphone.org + * + * Copyright (c) 2009-2010 Ricardo Quesada + * Copyright (c) 2011 Zynga Inc. + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + * THE SOFTWARE. + * + */ + +#import "CCParallaxNode.h" +#import "Support/CGPointExtension.h" +#import "Support/ccCArray.h" + +@interface CGPointObject : NSObject +{ + CGPoint _ratio; + CGPoint _offset; + CCNode *_child; // weak ref +} +@property (nonatomic,readwrite) CGPoint ratio; +@property (nonatomic,readwrite) CGPoint offset; +@property (nonatomic,readwrite,assign) CCNode *child; ++(id) pointWithCGPoint:(CGPoint)point offset:(CGPoint)offset; +-(id) initWithCGPoint:(CGPoint)point offset:(CGPoint)offset; +@end +@implementation CGPointObject +@synthesize ratio = _ratio; +@synthesize offset = _offset; +@synthesize child = _child; + ++(id) pointWithCGPoint:(CGPoint)ratio offset:(CGPoint)offset +{ + return [[[self alloc] initWithCGPoint:ratio offset:offset] autorelease]; +} +-(id) initWithCGPoint:(CGPoint)ratio offset:(CGPoint)offset +{ + if( (self=[super init])) { + _ratio = ratio; + _offset = offset; + } + return self; +} +@end + +@implementation CCParallaxNode + +@synthesize parallaxArray = _parallaxArray; + +-(id) init +{ + if( (self=[super init]) ) { + _parallaxArray = ccArrayNew(5); + _lastPosition = CGPointMake(-100,-100); + } + return self; +} + +- (void) dealloc +{ + if( _parallaxArray ) { + ccArrayFree(_parallaxArray); + _parallaxArray = nil; + } + [super dealloc]; +} + +-(void) addChild:(CCNode*)child z:(NSInteger)z tag:(NSInteger)tag +{ + NSAssert(NO,@"ParallaxNode: use addChild:z:parallaxRatio:positionOffset instead"); +} + +-(void) addChild: (CCNode*) child z:(NSInteger)z parallaxRatio:(CGPoint)ratio positionOffset:(CGPoint)offset +{ + NSAssert( child != nil, @"Argument must be non-nil"); + CGPointObject *obj = [CGPointObject pointWithCGPoint:ratio offset:offset]; + obj.child = child; + ccArrayAppendObjectWithResize(_parallaxArray, obj); + + CGPoint pos = self.position; + pos.x = pos.x * ratio.x + offset.x; + pos.y = pos.y * ratio.y + offset.y; + child.position = pos; + + [super addChild: child z:z tag:child.tag]; +} + +-(void) removeChild:(CCNode*)node cleanup:(BOOL)cleanup +{ + for( unsigned int i=0;i < _parallaxArray->num;i++) { + CGPointObject *point = _parallaxArray->arr[i]; + if( [point.child isEqual:node] ) { + ccArrayRemoveObjectAtIndex(_parallaxArray, i); + break; + } + } + [super removeChild:node cleanup:cleanup]; +} + +-(void) removeAllChildrenWithCleanup:(BOOL)cleanup +{ + ccArrayRemoveAllObjects(_parallaxArray); + [super removeAllChildrenWithCleanup:cleanup]; +} + +-(CGPoint) absolutePosition_ +{ + CGPoint ret = _position; + + CCNode *cn = self; + + while (cn.parent != nil) { + cn = cn.parent; + ret = ccpAdd( ret, cn.position ); + } + + return ret; +} + +/* + The positions are updated at visit because: + - using a timer is not guaranteed that it will called after all the positions were updated + - overriding "draw" will only be precise if the children have a z > 0 +*/ +-(void) visit +{ +// CGPoint pos = _position; +// CGPoint pos = [self convertToWorldSpace:CGPointZero]; + CGPoint pos = [self absolutePosition_]; + if( ! CGPointEqualToPoint(pos, _lastPosition) ) { + + for(unsigned int i=0; i < _parallaxArray->num; i++ ) { + + CGPointObject *point = _parallaxArray->arr[i]; + float x = -pos.x + pos.x * point.ratio.x + point.offset.x; + float y = -pos.y + pos.y * point.ratio.y + point.offset.y; + point.child.position = ccp(x,y); + } + + _lastPosition = pos; + } + + [super visit]; +} +@end diff --git "a/21451198\345\215\242\350\266\205/project5/MyPlane/libs/cocos2d/CCParticleBatchNode.h" "b/21451198\345\215\242\350\266\205/project5/MyPlane/libs/cocos2d/CCParticleBatchNode.h" new file mode 100644 index 00000000..30f943a8 --- /dev/null +++ "b/21451198\345\215\242\350\266\205/project5/MyPlane/libs/cocos2d/CCParticleBatchNode.h" @@ -0,0 +1,99 @@ +/* + * cocos2d for iPhone: http://www.cocos2d-iphone.org + * + * Copyright (C) 2009 Matt Oswald + * + * Copyright (c) 2009-2010 Ricardo Quesada + * Copyright (c) 2011 Zynga Inc. + * + * Copyright (c) 2011 Marco Tillemans + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + * THE SOFTWARE. + * + */ + +#import "CCNode.h" +@class CCTextureAtlas; +@class CCParticleSystem; + +//don't use lazy sorting for particle systems +@interface CCNode (extension) +-(void) setZOrder:(NSUInteger) z; +@end + +/** CCParticleBatchNode is like a batch node: if it contains children, it will draw them in 1 single OpenGL call + * (often known as "batch draw"). + * + * A CCParticleBatchNode can reference one and only one texture (one image file, one texture atlas). + * Only the CCParticleSystems that are contained in that texture can be added to the CCSpriteBatchNode. + * All CCParticleSystems added to a CCSpriteBatchNode are drawn in one OpenGL ES draw call. + * If the CCParticleSystems are not added to a CCParticleBatchNode then an OpenGL ES draw call will be needed for each one, which is less efficient. + * + * + * Limitations: + * - At the moment only CCParticleSystemQuad is supported + * - All systems need to be drawn with the same parameters, blend function, aliasing, texture + * + * Most efficient usage + * - Initialize the ParticleBatchNode with the texture and enough capacity for all the particle systems + * - Initialize all particle systems and add them as child to the batch node + * @since v1.1 + */ + +@interface CCParticleBatchNode : CCNode { + + CCTextureAtlas *_textureAtlas; + ccBlendFunc _blendFunc; +} + +/** the texture atlas used for drawing the quads */ +@property (nonatomic, retain) CCTextureAtlas* textureAtlas; +/** the blend function used for drawing the quads */ +@property (nonatomic, readwrite) ccBlendFunc blendFunc; + +/** initializes the particle system with CCTexture2D, a default capacity of 500 */ ++(id)batchNodeWithTexture:(CCTexture2D *)tex; + +/** initializes the particle system with the name of a file on disk (for a list of supported formats look at the CCTexture2D class), a default capacity of 500 particles */ ++(id)batchNodeWithFile:(NSString*) imageFile; + +/** initializes the particle system with CCTexture2D, a capacity of particles, which particle system to use */ ++(id)batchNodeWithTexture:(CCTexture2D *)tex capacity:(NSUInteger) capacity; + +/** initializes the particle system with the name of a file on disk (for a list of supported formats look at the CCTexture2D class), a capacity of particles */ ++(id)batchNodeWithFile:(NSString*)fileImage capacity:(NSUInteger)capacity; + +/** initializes the particle system with CCTexture2D, a capacity of particles */ +-(id)initWithTexture:(CCTexture2D *)tex capacity:(NSUInteger)capacity; + +/** initializes the particle system with the name of a file on disk (for a list of supported formats look at the CCTexture2D class), a capacity of particles */ +-(id)initWithFile:(NSString *)fileImage capacity:(NSUInteger)capacity; + +/** Add a child into the CCParticleBatchNode */ +-(void) addChild:(CCParticleSystem*)child z:(NSInteger)z tag:(NSInteger) aTag; + +/** Inserts a child into the CCParticleBatchNode */ +-(void) insertChild:(CCParticleSystem*) pSystem inAtlasAtIndex:(NSUInteger)index; + +/** remove child from the CCParticleBatchNode */ +-(void) removeChild:(CCParticleSystem*) pSystem cleanup:(BOOL)doCleanUp; + +/** disables a particle by inserting a 0'd quad into the texture atlas */ +-(void) disableParticle:(NSUInteger) particleIndex; +@end diff --git "a/21451198\345\215\242\350\266\205/project5/MyPlane/libs/cocos2d/CCParticleBatchNode.m" "b/21451198\345\215\242\350\266\205/project5/MyPlane/libs/cocos2d/CCParticleBatchNode.m" new file mode 100644 index 00000000..942e4587 --- /dev/null +++ "b/21451198\345\215\242\350\266\205/project5/MyPlane/libs/cocos2d/CCParticleBatchNode.m" @@ -0,0 +1,473 @@ +/* + * cocos2d for iPhone: http://www.cocos2d-iphone.org + * + * Copyright (C) 2009 Matt Oswald + * + * Copyright (c) 2009-2010 Ricardo Quesada + * Copyright (c) 2011 Zynga Inc. + * + * Copyright (c) 2011 Marco Tillemans + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + * THE SOFTWARE. + * + */ + +#import "CCParticleBatchNode.h" +#import "CCTextureCache.h" +#import "CCTextureAtlas.h" +#import "ccConfig.h" +#import "ccMacros.h" +#import "CCGrid.h" +#import "Support/CGPointExtension.h" +#import "CCParticleSystem.h" +#import "CCParticleSystem.h" +#import "CCShaderCache.h" +#import "CCGLProgram.h" +#import "ccGLStateCache.h" + +#import "Support/base64.h" +#import "Support/ZipUtils.h" +#import "Support/CCFileUtils.h" + +#import "kazmath/GL/matrix.h" + +#define kCCParticleDefaultCapacity 500 + +@interface CCNode() +-(void) _setZOrder:(NSInteger)z; +@end + +@interface CCParticleBatchNode (private) +-(void) updateAllAtlasIndexes; +-(void) increaseAtlasCapacityTo:(NSUInteger) quantity; +-(NSUInteger) searchNewPositionInChildrenForZ:(NSInteger)z; +-(void) getCurrentIndex:(NSUInteger*)oldIndex newIndex:(NSUInteger*)newIndex forChild:(CCNode*)child z:(NSInteger)z; +-(NSUInteger) addChildHelper: (CCNode*) child z:(NSInteger)z tag:(NSInteger) aTag; +@end + +@implementation CCParticleBatchNode + +@synthesize textureAtlas = _textureAtlas; +@synthesize blendFunc = _blendFunc; + +/* + * creation with CCTexture2D + */ ++(id)batchNodeWithTexture:(CCTexture2D *)tex +{ + return [[[self alloc] initWithTexture:tex capacity:kCCParticleDefaultCapacity] autorelease]; +} + ++(id)batchNodeWithTexture:(CCTexture2D *)tex capacity:(NSUInteger) capacity +{ + return [[[self alloc] initWithTexture:tex capacity:capacity] autorelease]; +} + +/* + * creation with File Image + */ ++(id)batchNodeWithFile:(NSString*)fileImage capacity:(NSUInteger)capacity +{ + return [[[self alloc] initWithFile:fileImage capacity:capacity] autorelease]; +} + ++(id)batchNodeWithFile:(NSString*) imageFile +{ + return [[[self alloc] initWithFile:imageFile capacity:kCCParticleDefaultCapacity] autorelease]; +} + +/* + * init with CCTexture2D + */ +-(id)initWithTexture:(CCTexture2D *)tex capacity:(NSUInteger)capacity +{ + if (self = [super init]) + { + _textureAtlas = [[CCTextureAtlas alloc] initWithTexture:tex capacity:capacity]; + + // no lazy alloc in this node + _children = [[CCArray alloc] initWithCapacity:capacity]; + + _blendFunc.src = CC_BLEND_SRC; + _blendFunc.dst = CC_BLEND_DST; + + self.shaderProgram = [[CCShaderCache sharedShaderCache] programForKey:kCCShader_PositionTextureColor]; + } + + return self; +} + +/* + * init with FileImage + */ +-(id)initWithFile:(NSString *)fileImage capacity:(NSUInteger)capacity +{ + CCTexture2D *tex = [[CCTextureCache sharedTextureCache] addImage:fileImage]; + return [self initWithTexture:tex capacity:capacity]; +} + +-(NSString*) description +{ + return [NSString stringWithFormat:@"<%@ = %p | Tag = %ld>", [self class], self, (long)_tag ]; +} + +-(void)dealloc +{ + [_textureAtlas release]; + [super dealloc]; +} + +#pragma mark CCParticleBatchNode - composition + +// override visit. +// Don't call visit on it's children +-(void) visit +{ + // CAREFUL: + // This visit is almost identical to CCNode#visit + // with the exception that it doesn't call visit on it's children + // + // The alternative is to have a void CCSprite#visit, but + // although this is less mantainable, is faster + // + if (!_visible) + return; + + kmGLPushMatrix(); + + if ( _grid && _grid.active) { + [_grid beforeDraw]; + [self transformAncestors]; + } + + [self transform]; + + [self draw]; + + if ( _grid && _grid.active) + [_grid afterDraw:self]; + + kmGLPopMatrix(); +} + +// override addChild: +-(void) addChild:(CCParticleSystem*)child z:(NSInteger)z tag:(NSInteger) aTag +{ + NSAssert( child != nil, @"Argument must be non-nil"); + NSAssert( [child isKindOfClass:[CCParticleSystem class]], @"CCParticleBatchNode only supports CCQuadParticleSystems as children"); + NSAssert( child.texture.name == _textureAtlas.texture.name, @"CCParticleSystem is not using the same texture id"); + + // If this is the 1st children, then copy blending function + if( [_children count] == 0 ) + _blendFunc = [child blendFunc]; + + NSAssert( _blendFunc.src == child.blendFunc.src && _blendFunc.dst == child.blendFunc.dst, @"Can't add a PaticleSystem that uses a differnt blending function"); + + //no lazy sorting, so don't call super addChild, call helper instead + NSUInteger pos = [self addChildHelper:child z:z tag:aTag]; + + //get new atlasIndex + NSUInteger atlasIndex; + + if (pos != 0) + atlasIndex = [[_children objectAtIndex:pos-1] atlasIndex] + [[_children objectAtIndex:pos-1] totalParticles]; + else + atlasIndex = 0; + + [self insertChild:child inAtlasAtIndex:atlasIndex]; + + // update quad info + [child setBatchNode:self]; +} + +// don't use lazy sorting, reordering the particle systems quads afterwards would be too complex +// XXX research whether lazy sorting + freeing current quads and calloc a new block with size of capacity would be faster +// XXX or possibly using vertexZ for reordering, that would be fastest +// this helper is almost equivalent to CCNode's addChild, but doesn't make use of the lazy sorting +-(NSUInteger) addChildHelper: (CCNode*) child z:(NSInteger)z tag:(NSInteger) aTag +{ + NSAssert( child != nil, @"Argument must be non-nil"); + NSAssert( child.parent == nil, @"child already added. It can't be added again"); + + if( ! _children ) + _children = [[CCArray alloc] initWithCapacity:4]; + + //don't use a lazy insert + NSUInteger pos = [self searchNewPositionInChildrenForZ:z]; + + [_children insertObject:child atIndex:pos]; + + child.tag = aTag; + [child _setZOrder:z]; + + [child setParent: self]; + + if( _isRunning ) { + [child onEnter]; + [child onEnterTransitionDidFinish]; + } + return pos; +} + +// Reorder will be done in this function, no "lazy" reorder to particles +-(void) reorderChild:(CCParticleSystem*)child z:(NSInteger)z +{ + NSAssert( child != nil, @"Child must be non-nil"); + NSAssert( [_children containsObject:child], @"Child doesn't belong to batch" ); + + if( z == child.zOrder ) + return; + + // no reordering if only 1 child + if( [_children count] > 1) + { + NSUInteger newIndex, oldIndex; + + [self getCurrentIndex:&oldIndex newIndex:&newIndex forChild:child z:z]; + + if( oldIndex != newIndex ) { + + // reorder _children array + [child retain]; + [_children removeObjectAtIndex:oldIndex]; + [_children insertObject:child atIndex:newIndex]; + [child release]; + + // save old altasIndex + NSUInteger oldAtlasIndex = child.atlasIndex; + + // update atlas index + [self updateAllAtlasIndexes]; + + // Find new AtlasIndex + NSUInteger newAtlasIndex = 0; + for( NSUInteger i=0;i < [_children count];i++) { + CCParticleSystem *node = [_children objectAtIndex:i]; + if( node == child ) { + newAtlasIndex = [child atlasIndex]; + break; + } + } + + // reorder textureAtlas quads + [_textureAtlas moveQuadsFromIndex:oldAtlasIndex amount:child.totalParticles atIndex:newAtlasIndex]; + + [child updateWithNoTime]; + } + } + + [child _setZOrder:z]; +} + +-(void) getCurrentIndex:(NSUInteger*)oldIndex newIndex:(NSUInteger*)newIndex forChild:(CCNode*)child z:(NSInteger)z +{ + BOOL foundCurrentIdx = NO; + BOOL foundNewIdx = NO; + + NSInteger minusOne = 0; + NSUInteger count = [_children count]; + + for( NSUInteger i=0; i < count; i++ ) { + + CCNode *node = [_children objectAtIndex:i]; + + // new index + if( node.zOrder > z && ! foundNewIdx ) { + *newIndex = i; + foundNewIdx = YES; + + if( foundCurrentIdx && foundNewIdx ) + break; + } + + // current index + if( child == node ) { + *oldIndex = i; + foundCurrentIdx = YES; + + if( ! foundNewIdx ) + minusOne = -1; + + if( foundCurrentIdx && foundNewIdx ) + break; + + } + + } + + if( ! foundNewIdx ) + *newIndex = count; + + *newIndex += minusOne; +} + +-(NSUInteger) searchNewPositionInChildrenForZ: (NSInteger) z +{ + NSUInteger count = [_children count]; + + for( NSUInteger i=0; i < count; i++ ) { + CCNode *child = [_children objectAtIndex:i]; + if (child.zOrder > z) + return i; + } + return count; +} + +// override removeChild: +-(void)removeChild: (CCParticleSystem*) child cleanup:(BOOL)doCleanup +{ + // explicit nil handling + if (child == nil) + return; + + NSAssert([_children containsObject:child], @"CCParticleBatchNode doesn't contain the sprite. Can't remove it"); + + [super removeChild:child cleanup:doCleanup]; + + // remove child helper + [_textureAtlas removeQuadsAtIndex:child.atlasIndex amount:child.totalParticles]; + + // after memmove of data, empty the quads at the end of array + [_textureAtlas fillWithEmptyQuadsFromIndex:_textureAtlas.totalQuads amount:child.totalParticles]; + + // paticle could be reused for self rendering + [child setBatchNode:nil]; + + [self updateAllAtlasIndexes]; +} + +-(void)removeChildAtIndex:(NSUInteger)index cleanup:(BOOL) doCleanup +{ + [self removeChild:(CCParticleSystem *)[_children objectAtIndex:index] cleanup:doCleanup]; +} + +-(void)removeAllChildrenWithCleanup:(BOOL)doCleanup +{ + [_children makeObjectsPerformSelector:@selector(setBatchNode:) withObject:nil]; + + [super removeAllChildrenWithCleanup:doCleanup]; + + [_textureAtlas removeAllQuads]; +} + +#pragma mark CCParticleBatchNode - Node overrides +-(void) draw +{ + CC_PROFILER_STOP(@"CCParticleBatchNode - draw"); + + if( _textureAtlas.totalQuads == 0 ) + return; + + CC_NODE_DRAW_SETUP(); + + ccGLBlendFunc( _blendFunc.src, _blendFunc.dst ); + + [_textureAtlas drawQuads]; + + CC_PROFILER_STOP(@"CCParticleBatchNode - draw"); +} + +#pragma mark CCParticleBatchNode - private + +-(void) increaseAtlasCapacityTo:(NSUInteger) quantity +{ + CCLOG(@"cocos2d: CCParticleBatchNode: resizing TextureAtlas capacity from [%lu] to [%lu].", + (long)_textureAtlas.capacity, + (long)quantity); + + if( ! [_textureAtlas resizeCapacity:quantity] ) { + // serious problems + CCLOGWARN(@"cocos2d: WARNING: Not enough memory to resize the atlas"); + NSAssert(NO,@"XXX: CCParticleBatchNode #increaseAtlasCapacity SHALL handle this assert"); + } +} + +//sets a 0'd quad into the quads array +-(void) disableParticle:(NSUInteger)particleIndex +{ + ccV3F_C4B_T2F_Quad* quad = &((_textureAtlas.quads)[particleIndex]); + quad->br.vertices.x = quad->br.vertices.y = quad->tr.vertices.x = quad->tr.vertices.y = quad->tl.vertices.x = quad->tl.vertices.y = quad->bl.vertices.x = quad->bl.vertices.y = 0.0f; +} + +#pragma mark CCParticleBatchNode - add / remove / reorder helper methods + +// add child helper +-(void) insertChild:(CCParticleSystem*) pSystem inAtlasAtIndex:(NSUInteger)index +{ + pSystem.atlasIndex = index; + + if(_textureAtlas.totalQuads + pSystem.totalParticles > _textureAtlas.capacity) + { + [self increaseAtlasCapacityTo:_textureAtlas.totalQuads + pSystem.totalParticles]; + + // after a realloc empty quads of textureAtlas can be filled with gibberish (realloc doesn't perform calloc), insert empty quads to prevent it + [_textureAtlas fillWithEmptyQuadsFromIndex:_textureAtlas.capacity - pSystem.totalParticles amount:pSystem.totalParticles]; + } + + // make room for quads, not necessary for last child + if (pSystem.atlasIndex + pSystem.totalParticles != _textureAtlas.totalQuads) + [_textureAtlas moveQuadsFromIndex:index to:index+pSystem.totalParticles]; + + // increase totalParticles here for new particles, update method of particlesystem will fill the quads + [_textureAtlas increaseTotalQuadsWith:pSystem.totalParticles]; + + [self updateAllAtlasIndexes]; +} + +//rebuild atlas indexes +-(void) updateAllAtlasIndexes +{ + CCParticleSystem *child; + NSUInteger index = 0; + + CCARRAY_FOREACH(_children,child) + { + child.atlasIndex = index; + index += child.totalParticles; + } +} + +#pragma mark CCParticleBatchNode - CocosNodeTexture protocol + +-(void) updateBlendFunc +{ + if( ! [_textureAtlas.texture hasPremultipliedAlpha] ) { + _blendFunc.src = GL_SRC_ALPHA; + _blendFunc.dst = GL_ONE_MINUS_SRC_ALPHA; + } +} + +-(void) setTexture:(CCTexture2D*)texture +{ + _textureAtlas.texture = texture; + + // If the new texture has No premultiplied alpha, AND the blendFunc hasn't been changed, then update it + if( texture && ! [texture hasPremultipliedAlpha] && ( _blendFunc.src == CC_BLEND_SRC && _blendFunc.dst == CC_BLEND_DST ) ) + { + _blendFunc.src = GL_SRC_ALPHA; + _blendFunc.dst = GL_ONE_MINUS_SRC_ALPHA; + } +} + +-(CCTexture2D*) texture +{ + return _textureAtlas.texture; +} + +@end diff --git "a/21451198\345\215\242\350\266\205/project5/MyPlane/libs/cocos2d/CCParticleExamples.h" "b/21451198\345\215\242\350\266\205/project5/MyPlane/libs/cocos2d/CCParticleExamples.h" new file mode 100644 index 00000000..747c92aa --- /dev/null +++ "b/21451198\345\215\242\350\266\205/project5/MyPlane/libs/cocos2d/CCParticleExamples.h" @@ -0,0 +1,117 @@ +/* + * cocos2d for iPhone: http://www.cocos2d-iphone.org + * + * Copyright (c) 2008-2010 Ricardo Quesada + * Copyright (c) 2011 Zynga Inc. + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + * THE SOFTWARE. + * + */ + + +#import "ccMacros.h" +#import "CCParticleSystemQuad.h" + +//! A fire particle system +@interface CCParticleFire: CCParticleSystemQuad +{ +} +// needed for BridgeSupport +-(id) init; +@end + +//! A fireworks particle system +@interface CCParticleFireworks : CCParticleSystemQuad +{ +} +// needed for BridgeSupport +-(id) init; +@end + +//! A sun particle system +@interface CCParticleSun : CCParticleSystemQuad +{ +} +// needed for BridgeSupport +-(id) init; +@end + +//! A galaxy particle system +@interface CCParticleGalaxy : CCParticleSystemQuad +{ +} +// needed for BridgeSupport +-(id) init; +@end + +//! A flower particle system +@interface CCParticleFlower : CCParticleSystemQuad +{ +} +// needed for BridgeSupport +-(id) init; +@end + +//! A meteor particle system +@interface CCParticleMeteor : CCParticleSystemQuad +{ +} +// needed for BridgeSupport +-(id) init; +@end + +//! An spiral particle system +@interface CCParticleSpiral : CCParticleSystemQuad +{ +} +// needed for BridgeSupport +-(id) init; +@end + +//! An explosion particle system +@interface CCParticleExplosion : CCParticleSystemQuad +{ +} +// needed for BridgeSupport +-(id) init; +@end + +//! An smoke particle system +@interface CCParticleSmoke : CCParticleSystemQuad +{ +} +// needed for BridgeSupport +-(id) init; +@end + +//! An snow particle system +@interface CCParticleSnow : CCParticleSystemQuad +{ +} +// needed for BridgeSupport +-(id) init; +@end + +//! A rain particle system +@interface CCParticleRain : CCParticleSystemQuad +{ +} +// needed for BridgeSupport +-(id) init; +@end diff --git "a/21451198\345\215\242\350\266\205/project5/MyPlane/libs/cocos2d/CCParticleExamples.m" "b/21451198\345\215\242\350\266\205/project5/MyPlane/libs/cocos2d/CCParticleExamples.m" new file mode 100644 index 00000000..7cfcfa86 --- /dev/null +++ "b/21451198\345\215\242\350\266\205/project5/MyPlane/libs/cocos2d/CCParticleExamples.m" @@ -0,0 +1,926 @@ +/* + * cocos2d for iPhone: http://www.cocos2d-iphone.org + * + * Copyright (c) 2008-2010 Ricardo Quesada + * Copyright (c) 2011 Zynga Inc. + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + * THE SOFTWARE. + * + */ + + +// cocos2d +#import "CCParticleExamples.h" +#import "CCTextureCache.h" +#import "CCDirector.h" +#import "Support/CGPointExtension.h" + +// +// ParticleFireworks +// +@implementation CCParticleFireworks +-(id) init +{ + return [self initWithTotalParticles:1500]; +} + +-(id) initWithTotalParticles:(NSUInteger)p +{ + if( (self=[super initWithTotalParticles:p]) ) { + // _duration + _duration = kCCParticleDurationInfinity; + + // Gravity Mode + self.emitterMode = kCCParticleModeGravity; + + // Gravity Mode: gravity + self.gravity = ccp(0,-90); + + // Gravity Mode: radial + self.radialAccel = 0; + self.radialAccelVar = 0; + + // Gravity Mode: speed of particles + self.speed = 180; + self.speedVar = 50; + + // emitter position + CGSize winSize = [[CCDirector sharedDirector] winSize]; + self.position = ccp(winSize.width/2, winSize.height/2); + + // angle + _angle = 90; + _angleVar = 20; + + // life of particles + _life = 3.5f; + _lifeVar = 1; + + // emits per frame + _emissionRate = _totalParticles/_life; + + // color of particles + _startColor.r = 0.5f; + _startColor.g = 0.5f; + _startColor.b = 0.5f; + _startColor.a = 1.0f; + _startColorVar.r = 0.5f; + _startColorVar.g = 0.5f; + _startColorVar.b = 0.5f; + _startColorVar.a = 0.1f; + _endColor.r = 0.1f; + _endColor.g = 0.1f; + _endColor.b = 0.1f; + _endColor.a = 0.2f; + _endColorVar.r = 0.1f; + _endColorVar.g = 0.1f; + _endColorVar.b = 0.1f; + _endColorVar.a = 0.2f; + + // size, in pixels + _startSize = 8.0f; + _startSizeVar = 2.0f; + _endSize = kCCParticleStartSizeEqualToEndSize; + + self.texture = [[CCTextureCache sharedTextureCache] addImage: @"fire.png"]; + + // additive + self.blendAdditive = NO; + } + + return self; +} +@end + +// +// ParticleFire +// +@implementation CCParticleFire +-(id) init +{ + return [self initWithTotalParticles:250]; +} + +-(id) initWithTotalParticles:(NSUInteger) p +{ + if( (self=[super initWithTotalParticles:p]) ) { + + // _duration + _duration = kCCParticleDurationInfinity; + + // Gravity Mode + self.emitterMode = kCCParticleModeGravity; + + // Gravity Mode: gravity + self.gravity = ccp(0,0); + + // Gravity Mode: radial acceleration + self.radialAccel = 0; + self.radialAccelVar = 0; + + // Gravity Mode: speed of particles + self.speed = 60; + self.speedVar = 20; + + // starting _angle + _angle = 90; + _angleVar = 10; + + // emitter position + CGSize winSize = [[CCDirector sharedDirector] winSize]; + self.position = ccp(winSize.width/2, 60); + self.posVar = ccp(40, 20); + + // _life of particles + _life = 3; + _lifeVar = 0.25f; + + + // size, in pixels + _startSize = 54.0f; + _startSizeVar = 10.0f; + _endSize = kCCParticleStartSizeEqualToEndSize; + + // emits per frame + _emissionRate = _totalParticles/_life; + + // color of particles + _startColor.r = 0.76f; + _startColor.g = 0.25f; + _startColor.b = 0.12f; + _startColor.a = 1.0f; + _startColorVar.r = 0.0f; + _startColorVar.g = 0.0f; + _startColorVar.b = 0.0f; + _startColorVar.a = 0.0f; + _endColor.r = 0.0f; + _endColor.g = 0.0f; + _endColor.b = 0.0f; + _endColor.a = 1.0f; + _endColorVar.r = 0.0f; + _endColorVar.g = 0.0f; + _endColorVar.b = 0.0f; + _endColorVar.a = 0.0f; + + self.texture = [[CCTextureCache sharedTextureCache] addImage: @"fire.png"]; + + // additive + self.blendAdditive = YES; + } + + return self; +} +@end + +// +// ParticleSun +// +@implementation CCParticleSun +-(id) init +{ + return [self initWithTotalParticles:350]; +} + +-(id) initWithTotalParticles:(NSUInteger) p +{ + if( (self=[super initWithTotalParticles:p]) ) { + + // additive + self.blendAdditive = YES; + + // _duration + _duration = kCCParticleDurationInfinity; + + // Gravity Mode + self.emitterMode = kCCParticleModeGravity; + + // Gravity Mode: gravity + self.gravity = ccp(0,0); + + // Gravity mode: radial acceleration + self.radialAccel = 0; + self.radialAccelVar = 0; + + // Gravity mode: speed of particles + self.speed = 20; + self.speedVar = 5; + + + // _angle + _angle = 90; + _angleVar = 360; + + // emitter position + CGSize winSize = [[CCDirector sharedDirector] winSize]; + self.position = ccp(winSize.width/2, winSize.height/2); + self.posVar = CGPointZero; + + // _life of particles + _life = 1; + _lifeVar = 0.5f; + + // size, in pixels + _startSize = 30.0f; + _startSizeVar = 10.0f; + _endSize = kCCParticleStartSizeEqualToEndSize; + + // emits per seconds + _emissionRate = _totalParticles/_life; + + // color of particles + _startColor.r = 0.76f; + _startColor.g = 0.25f; + _startColor.b = 0.12f; + _startColor.a = 1.0f; + _startColorVar.r = 0.0f; + _startColorVar.g = 0.0f; + _startColorVar.b = 0.0f; + _startColorVar.a = 0.0f; + _endColor.r = 0.0f; + _endColor.g = 0.0f; + _endColor.b = 0.0f; + _endColor.a = 1.0f; + _endColorVar.r = 0.0f; + _endColorVar.g = 0.0f; + _endColorVar.b = 0.0f; + _endColorVar.a = 0.0f; + + self.texture = [[CCTextureCache sharedTextureCache] addImage: @"fire.png"]; + } + + return self; +} +@end + +// +// ParticleGalaxy +// +@implementation CCParticleGalaxy +-(id) init +{ + return [self initWithTotalParticles:200]; +} + +-(id) initWithTotalParticles:(NSUInteger)p +{ + if( (self=[super initWithTotalParticles:p]) ) { + + // _duration + _duration = kCCParticleDurationInfinity; + + // Gravity Mode + self.emitterMode = kCCParticleModeGravity; + + // Gravity Mode: gravity + self.gravity = ccp(0,0); + + // Gravity Mode: speed of particles + self.speed = 60; + self.speedVar = 10; + + // Gravity Mode: radial + self.radialAccel = -80; + self.radialAccelVar = 0; + + // Gravity Mode: tagential + self.tangentialAccel = 80; + self.tangentialAccelVar = 0; + + // _angle + _angle = 90; + _angleVar = 360; + + // emitter position + CGSize winSize = [[CCDirector sharedDirector] winSize]; + self.position = ccp(winSize.width/2, winSize.height/2); + self.posVar = CGPointZero; + + // _life of particles + _life = 4; + _lifeVar = 1; + + // size, in pixels + _startSize = 37.0f; + _startSizeVar = 10.0f; + _endSize = kCCParticleStartSizeEqualToEndSize; + + // emits per second + _emissionRate = _totalParticles/_life; + + // color of particles + _startColor.r = 0.12f; + _startColor.g = 0.25f; + _startColor.b = 0.76f; + _startColor.a = 1.0f; + _startColorVar.r = 0.0f; + _startColorVar.g = 0.0f; + _startColorVar.b = 0.0f; + _startColorVar.a = 0.0f; + _endColor.r = 0.0f; + _endColor.g = 0.0f; + _endColor.b = 0.0f; + _endColor.a = 1.0f; + _endColorVar.r = 0.0f; + _endColorVar.g = 0.0f; + _endColorVar.b = 0.0f; + _endColorVar.a = 0.0f; + + self.texture = [[CCTextureCache sharedTextureCache] addImage: @"fire.png"]; + + // additive + self.blendAdditive = YES; + } + + return self; +} +@end + +// +// ParticleFlower +// +@implementation CCParticleFlower +-(id) init +{ + return [self initWithTotalParticles:250]; +} + +-(id) initWithTotalParticles:(NSUInteger) p +{ + if( (self=[super initWithTotalParticles:p]) ) { + + // _duration + _duration = kCCParticleDurationInfinity; + + // Gravity Mode + self.emitterMode = kCCParticleModeGravity; + + // Gravity Mode: gravity + self.gravity = ccp(0,0); + + // Gravity Mode: speed of particles + self.speed = 80; + self.speedVar = 10; + + // Gravity Mode: radial + self.radialAccel = -60; + self.radialAccelVar = 0; + + // Gravity Mode: tagential + self.tangentialAccel = 15; + self.tangentialAccelVar = 0; + + // _angle + _angle = 90; + _angleVar = 360; + + // emitter position + CGSize winSize = [[CCDirector sharedDirector] winSize]; + self.position = ccp(winSize.width/2, winSize.height/2); + self.posVar = CGPointZero; + + // _life of particles + _life = 4; + _lifeVar = 1; + + // size, in pixels + _startSize = 30.0f; + _startSizeVar = 10.0f; + _endSize = kCCParticleStartSizeEqualToEndSize; + + // emits per second + _emissionRate = _totalParticles/_life; + + // color of particles + _startColor.r = 0.50f; + _startColor.g = 0.50f; + _startColor.b = 0.50f; + _startColor.a = 1.0f; + _startColorVar.r = 0.5f; + _startColorVar.g = 0.5f; + _startColorVar.b = 0.5f; + _startColorVar.a = 0.5f; + _endColor.r = 0.0f; + _endColor.g = 0.0f; + _endColor.b = 0.0f; + _endColor.a = 1.0f; + _endColorVar.r = 0.0f; + _endColorVar.g = 0.0f; + _endColorVar.b = 0.0f; + _endColorVar.a = 0.0f; + + self.texture = [[CCTextureCache sharedTextureCache] addImage: @"fire.png"]; + + // additive + self.blendAdditive = YES; + } + + return self; +} +@end + +// +// ParticleMeteor +// +@implementation CCParticleMeteor +-(id) init +{ + return [self initWithTotalParticles:150]; +} + +-(id) initWithTotalParticles:(NSUInteger) p +{ + if( (self=[super initWithTotalParticles:p]) ) { + + // _duration + _duration = kCCParticleDurationInfinity; + + // Gravity Mode + self.emitterMode = kCCParticleModeGravity; + + // Gravity Mode: gravity + self.gravity = ccp(-200,200); + + // Gravity Mode: speed of particles + self.speed = 15; + self.speedVar = 5; + + // Gravity Mode: radial + self.radialAccel = 0; + self.radialAccelVar = 0; + + // Gravity Mode: tagential + self.tangentialAccel = 0; + self.tangentialAccelVar = 0; + + // _angle + _angle = 90; + _angleVar = 360; + + // emitter position + CGSize winSize = [[CCDirector sharedDirector] winSize]; + self.position = ccp(winSize.width/2, winSize.height/2); + self.posVar = CGPointZero; + + // _life of particles + _life = 2; + _lifeVar = 1; + + // size, in pixels + _startSize = 60.0f; + _startSizeVar = 10.0f; + _endSize = kCCParticleStartSizeEqualToEndSize; + + // emits per second + _emissionRate = _totalParticles/_life; + + // color of particles + _startColor.r = 0.2f; + _startColor.g = 0.4f; + _startColor.b = 0.7f; + _startColor.a = 1.0f; + _startColorVar.r = 0.0f; + _startColorVar.g = 0.0f; + _startColorVar.b = 0.2f; + _startColorVar.a = 0.1f; + _endColor.r = 0.0f; + _endColor.g = 0.0f; + _endColor.b = 0.0f; + _endColor.a = 1.0f; + _endColorVar.r = 0.0f; + _endColorVar.g = 0.0f; + _endColorVar.b = 0.0f; + _endColorVar.a = 0.0f; + + self.texture = [[CCTextureCache sharedTextureCache] addImage: @"fire.png"]; + + // additive + self.blendAdditive = YES; + } + + return self; +} +@end + +// +// ParticleSpiral +// +@implementation CCParticleSpiral +-(id) init +{ + return [self initWithTotalParticles:500]; +} + +-(id) initWithTotalParticles:(NSUInteger) p +{ + if( (self=[super initWithTotalParticles:p]) ) { + + // _duration + _duration = kCCParticleDurationInfinity; + + // Gravity Mode + self.emitterMode = kCCParticleModeGravity; + + // Gravity Mode: gravity + self.gravity = ccp(0,0); + + // Gravity Mode: speed of particles + self.speed = 150; + self.speedVar = 0; + + // Gravity Mode: radial + self.radialAccel = -380; + self.radialAccelVar = 0; + + // Gravity Mode: tagential + self.tangentialAccel = 45; + self.tangentialAccelVar = 0; + + // _angle + _angle = 90; + _angleVar = 0; + + // emitter position + CGSize winSize = [[CCDirector sharedDirector] winSize]; + self.position = ccp(winSize.width/2, winSize.height/2); + self.posVar = CGPointZero; + + // _life of particles + _life = 12; + _lifeVar = 0; + + // size, in pixels + _startSize = 20.0f; + _startSizeVar = 0.0f; + _endSize = kCCParticleStartSizeEqualToEndSize; + + // emits per second + _emissionRate = _totalParticles/_life; + + // color of particles + _startColor.r = 0.5f; + _startColor.g = 0.5f; + _startColor.b = 0.5f; + _startColor.a = 1.0f; + _startColorVar.r = 0.5f; + _startColorVar.g = 0.5f; + _startColorVar.b = 0.5f; + _startColorVar.a = 0.0f; + _endColor.r = 0.5f; + _endColor.g = 0.5f; + _endColor.b = 0.5f; + _endColor.a = 1.0f; + _endColorVar.r = 0.5f; + _endColorVar.g = 0.5f; + _endColorVar.b = 0.5f; + _endColorVar.a = 0.0f; + + self.texture = [[CCTextureCache sharedTextureCache] addImage: @"fire.png"]; + + // additive + self.blendAdditive = NO; + } + + return self; +} +@end + +// +// ParticleExplosion +// +@implementation CCParticleExplosion +-(id) init +{ + return [self initWithTotalParticles:700]; +} + +-(id) initWithTotalParticles:(NSUInteger)p +{ + if( (self=[super initWithTotalParticles:p]) ) { + + // _duration + _duration = 0.1f; + + self.emitterMode = kCCParticleModeGravity; + + // Gravity Mode: gravity + self.gravity = ccp(0,0); + + // Gravity Mode: speed of particles + self.speed = 70; + self.speedVar = 40; + + // Gravity Mode: radial + self.radialAccel = 0; + self.radialAccelVar = 0; + + // Gravity Mode: tagential + self.tangentialAccel = 0; + self.tangentialAccelVar = 0; + + // _angle + _angle = 90; + _angleVar = 360; + + // emitter position + CGSize winSize = [[CCDirector sharedDirector] winSize]; + self.position = ccp(winSize.width/2, winSize.height/2); + self.posVar = CGPointZero; + + // _life of particles + _life = 5.0f; + _lifeVar = 2; + + // size, in pixels + _startSize = 15.0f; + _startSizeVar = 10.0f; + _endSize = kCCParticleStartSizeEqualToEndSize; + + // emits per second + _emissionRate = _totalParticles/_duration; + + // color of particles + _startColor.r = 0.7f; + _startColor.g = 0.1f; + _startColor.b = 0.2f; + _startColor.a = 1.0f; + _startColorVar.r = 0.5f; + _startColorVar.g = 0.5f; + _startColorVar.b = 0.5f; + _startColorVar.a = 0.0f; + _endColor.r = 0.5f; + _endColor.g = 0.5f; + _endColor.b = 0.5f; + _endColor.a = 0.0f; + _endColorVar.r = 0.5f; + _endColorVar.g = 0.5f; + _endColorVar.b = 0.5f; + _endColorVar.a = 0.0f; + + self.texture = [[CCTextureCache sharedTextureCache] addImage: @"fire.png"]; + + // additive + self.blendAdditive = NO; + } + + return self; +} +@end + +// +// ParticleSmoke +// +@implementation CCParticleSmoke +-(id) init +{ + return [self initWithTotalParticles:200]; +} + +-(id) initWithTotalParticles:(NSUInteger) p +{ + if( (self=[super initWithTotalParticles:p]) ) { + + // _duration + _duration = kCCParticleDurationInfinity; + + // Emitter mode: Gravity Mode + self.emitterMode = kCCParticleModeGravity; + + // Gravity Mode: gravity + self.gravity = ccp(0,0); + + // Gravity Mode: radial acceleration + self.radialAccel = 0; + self.radialAccelVar = 0; + + // Gravity Mode: speed of particles + self.speed = 25; + self.speedVar = 10; + + // _angle + _angle = 90; + _angleVar = 5; + + // emitter position + CGSize winSize = [[CCDirector sharedDirector] winSize]; + self.position = ccp(winSize.width/2, 0); + self.posVar = ccp(20, 0); + + // _life of particles + _life = 4; + _lifeVar = 1; + + // size, in pixels + _startSize = 60.0f; + _startSizeVar = 10.0f; + _endSize = kCCParticleStartSizeEqualToEndSize; + + // emits per frame + _emissionRate = _totalParticles/_life; + + // color of particles + _startColor.r = 0.8f; + _startColor.g = 0.8f; + _startColor.b = 0.8f; + _startColor.a = 1.0f; + _startColorVar.r = 0.02f; + _startColorVar.g = 0.02f; + _startColorVar.b = 0.02f; + _startColorVar.a = 0.0f; + _endColor.r = 0.0f; + _endColor.g = 0.0f; + _endColor.b = 0.0f; + _endColor.a = 1.0f; + _endColorVar.r = 0.0f; + _endColorVar.g = 0.0f; + _endColorVar.b = 0.0f; + _endColorVar.a = 0.0f; + + self.texture = [[CCTextureCache sharedTextureCache] addImage: @"fire.png"]; + + // additive + self.blendAdditive = NO; + } + + return self; +} +@end + +@implementation CCParticleSnow +-(id) init +{ + return [self initWithTotalParticles:700]; +} + +-(id) initWithTotalParticles:(NSUInteger)p +{ + if( (self=[super initWithTotalParticles:p]) ) { + + // _duration + _duration = kCCParticleDurationInfinity; + + // set gravity mode. + self.emitterMode = kCCParticleModeGravity; + + // Gravity Mode: gravity + self.gravity = ccp(0,-1); + + // Gravity Mode: speed of particles + self.speed = 5; + self.speedVar = 1; + + // Gravity Mode: radial + self.radialAccel = 0; + self.radialAccelVar = 1; + + // Gravity mode: tagential + self.tangentialAccel = 0; + self.tangentialAccelVar = 1; + + // emitter position + self.position = (CGPoint) { + [[CCDirector sharedDirector] winSize].width / 2, + [[CCDirector sharedDirector] winSize].height + 10 + }; + self.posVar = ccp( [[CCDirector sharedDirector] winSize].width / 2, 0 ); + + // _angle + _angle = -90; + _angleVar = 5; + + // _life of particles + _life = 45; + _lifeVar = 15; + + // size, in pixels + _startSize = 10.0f; + _startSizeVar = 5.0f; + _endSize = kCCParticleStartSizeEqualToEndSize; + + // emits per second + _emissionRate = 10; + + // color of particles + _startColor.r = 1.0f; + _startColor.g = 1.0f; + _startColor.b = 1.0f; + _startColor.a = 1.0f; + _startColorVar.r = 0.0f; + _startColorVar.g = 0.0f; + _startColorVar.b = 0.0f; + _startColorVar.a = 0.0f; + _endColor.r = 1.0f; + _endColor.g = 1.0f; + _endColor.b = 1.0f; + _endColor.a = 0.0f; + _endColorVar.r = 0.0f; + _endColorVar.g = 0.0f; + _endColorVar.b = 0.0f; + _endColorVar.a = 0.0f; + + self.texture = [[CCTextureCache sharedTextureCache] addImage: @"fire.png"]; + + // additive + self.blendAdditive = NO; + } + + return self; +} +@end + +@implementation CCParticleRain +-(id) init +{ + return [self initWithTotalParticles:1000]; +} + +-(id) initWithTotalParticles:(NSUInteger)p +{ + if( (self=[super initWithTotalParticles:p]) ) { + + // _duration + _duration = kCCParticleDurationInfinity; + + self.emitterMode = kCCParticleModeGravity; + + // Gravity Mode: gravity + self.gravity = ccp(10,-10); + + // Gravity Mode: radial + self.radialAccel = 0; + self.radialAccelVar = 1; + + // Gravity Mode: tagential + self.tangentialAccel = 0; + self.tangentialAccelVar = 1; + + // Gravity Mode: speed of particles + self.speed = 130; + self.speedVar = 30; + + // _angle + _angle = -90; + _angleVar = 5; + + + // emitter position + self.position = (CGPoint) { + [[CCDirector sharedDirector] winSize].width / 2, + [[CCDirector sharedDirector] winSize].height + }; + self.posVar = ccp( [[CCDirector sharedDirector] winSize].width / 2, 0 ); + + // _life of particles + _life = 4.5f; + _lifeVar = 0; + + // size, in pixels + _startSize = 4.0f; + _startSizeVar = 2.0f; + _endSize = kCCParticleStartSizeEqualToEndSize; + + // emits per second + _emissionRate = 20; + + // color of particles + _startColor.r = 0.7f; + _startColor.g = 0.8f; + _startColor.b = 1.0f; + _startColor.a = 1.0f; + _startColorVar.r = 0.0f; + _startColorVar.g = 0.0f; + _startColorVar.b = 0.0f; + _startColorVar.a = 0.0f; + _endColor.r = 0.7f; + _endColor.g = 0.8f; + _endColor.b = 1.0f; + _endColor.a = 0.5f; + _endColorVar.r = 0.0f; + _endColorVar.g = 0.0f; + _endColorVar.b = 0.0f; + _endColorVar.a = 0.0f; + + self.texture = [[CCTextureCache sharedTextureCache] addImage: @"fire.png"]; + + // additive + self.blendAdditive = NO; + } + + return self; +} +@end diff --git "a/21451198\345\215\242\350\266\205/project5/MyPlane/libs/cocos2d/CCParticleSystem.h" "b/21451198\345\215\242\350\266\205/project5/MyPlane/libs/cocos2d/CCParticleSystem.h" new file mode 100644 index 00000000..638be1b1 --- /dev/null +++ "b/21451198\345\215\242\350\266\205/project5/MyPlane/libs/cocos2d/CCParticleSystem.h" @@ -0,0 +1,464 @@ +/* + * cocos2d for iPhone: http://www.cocos2d-iphone.org + * + * Copyright (c) 2008-2010 Ricardo Quesada + * Copyright (c) 2011 Zynga Inc. + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + * THE SOFTWARE. + * + */ + + +#import "CCProtocols.h" +#import "CCNode.h" +#import "ccTypes.h" +#import "ccConfig.h" + +@class CCParticleBatchNode; + +//* @enum +enum { + /** The Particle emitter lives forever */ + kCCParticleDurationInfinity = -1, + + /** The starting size of the particle is equal to the ending size */ + kCCParticleStartSizeEqualToEndSize = -1, + + /** The starting radius of the particle is equal to the ending radius */ + kCCParticleStartRadiusEqualToEndRadius = -1, + + // backward compatible + kParticleStartSizeEqualToEndSize = kCCParticleStartSizeEqualToEndSize, + kParticleDurationInfinity = kCCParticleDurationInfinity, +}; + +//* @enum +enum { + /** Gravity mode (A mode) */ + kCCParticleModeGravity, + + /** Radius mode (B mode) */ + kCCParticleModeRadius, +}; + + +/** @typedef tCCPositionType + possible types of particle positions + */ +typedef enum { + /** Living particles are attached to the world and are unaffected by emitter repositioning. */ + kCCPositionTypeFree, + + /** Living particles are attached to the world but will follow the emitter repositioning. + Use case: Attach an emitter to an sprite, and you want that the emitter follows the sprite. + */ + kCCPositionTypeRelative, + + /** Living particles are attached to the emitter and are translated along with it. */ + kCCPositionTypeGrouped, +}tCCPositionType; + +// backward compatible +enum { + kPositionTypeFree = kCCPositionTypeFree, + kPositionTypeGrouped = kCCPositionTypeGrouped, +}; + +/** @struct tCCParticle + Structure that contains the values of each particle + */ +typedef struct sCCParticle { + CGPoint pos; + CGPoint startPos; + + ccColor4F color; + ccColor4F deltaColor; + + float size; + float deltaSize; + + float rotation; + float deltaRotation; + + ccTime timeToLive; + + NSUInteger atlasIndex; + + union { + // Mode A: gravity, direction, radial accel, tangential accel + struct { + CGPoint dir; + float radialAccel; + float tangentialAccel; + } A; + + // Mode B: radius mode + struct { + float angle; + float degreesPerSecond; + float radius; + float deltaRadius; + } B; + } mode; + +}tCCParticle; + +typedef void (*CC_UPDATE_PARTICLE_IMP)(id, SEL, tCCParticle*, CGPoint); + +@class CCTexture2D; + +/** Particle System base class + Attributes of a Particle System: + - emmision rate of the particles + - Gravity Mode (Mode A): + - gravity + - direction + - speed +- variance + - tangential acceleration +- variance + - radial acceleration +- variance + - Radius Mode (Mode B): + - startRadius +- variance + - endRadius +- variance + - rotate +- variance + - Properties common to all modes: + - life +- life variance + - start spin +- variance + - end spin +- variance + - start size +- variance + - end size +- variance + - start color +- variance + - end color +- variance + - life +- variance + - blending function + - texture + + cocos2d also supports particles generated by Particle Designer (http://particledesigner.71squared.com/). + 'Radius Mode' in Particle Designer uses a fixed emit rate of 30 hz. Since that can't be guarateed in cocos2d, + cocos2d uses a another approach, but the results are almost identical. + + cocos2d supports all the variables used by Particle Designer plus a bit more: + - spinning particles (supported when using CCParticleSystemQuad) + - tangential acceleration (Gravity mode) + - radial acceleration (Gravity mode) + - radius direction (Radius mode) (Particle Designer supports outwards to inwards direction only) + + It is possible to customize any of the above mentioned properties in runtime. Example: + + @code + emitter.radialAccel = 15; + emitter.startSpin = 0; + @endcode + + */ +@interface CCParticleSystem : CCNode +{ + // is the particle system active ? + BOOL _active; + // duration in seconds of the system. -1 is infinity + float _duration; + // time elapsed since the start of the system (in seconds) + float _elapsed; + + // position is from "superclass" CocosNode + CGPoint _sourcePosition; + // Position variance + CGPoint _posVar; + + // The angle (direction) of the particles measured in degrees + float _angle; + // Angle variance measured in degrees; + float _angleVar; + + // Different modes + + NSInteger _emitterMode; + union { + // Mode A:Gravity + Tangential Accel + Radial Accel + struct { + // gravity of the particles + CGPoint gravity; + + // The speed the particles will have. + float speed; + // The speed variance + float speedVar; + + // Tangential acceleration + float tangentialAccel; + // Tangential acceleration variance + float tangentialAccelVar; + + // Radial acceleration + float radialAccel; + // Radial acceleration variance + float radialAccelVar; + } A; + + // Mode B: circular movement (gravity, radial accel and tangential accel don't are not used in this mode) + struct { + + // The starting radius of the particles + float startRadius; + // The starting radius variance of the particles + float startRadiusVar; + // The ending radius of the particles + float endRadius; + // The ending radius variance of the particles + float endRadiusVar; + // Number of degress to rotate a particle around the source pos per second + float rotatePerSecond; + // Variance in degrees for rotatePerSecond + float rotatePerSecondVar; + } B; + } _mode; + + // start ize of the particles + float _startSize; + // start Size variance + float _startSizeVar; + // End size of the particle + float _endSize; + // end size of variance + float _endSizeVar; + + // How many seconds will the particle live + float _life; + // Life variance + float _lifeVar; + + // Start color of the particles + ccColor4F _startColor; + // Start color variance + ccColor4F _startColorVar; + // End color of the particles + ccColor4F _endColor; + // End color variance + ccColor4F _endColorVar; + + // start angle of the particles + float _startSpin; + // start angle variance + float _startSpinVar; + // End angle of the particle + float _endSpin; + // end angle ariance + float _endSpinVar; + + // Array of particles + tCCParticle *_particles; + // Maximum particles + NSUInteger _totalParticles; + // Count of active particles + NSUInteger _particleCount; + // Number of allocated particles + NSUInteger _allocatedParticles; + + // How many particles can be emitted per second + float _emissionRate; + float _emitCounter; + + // Texture of the particles + CCTexture2D *_texture; + // blend function + ccBlendFunc _blendFunc; + // Texture alpha behavior + BOOL _opacityModifyRGB; + + // movment type: free or grouped + tCCPositionType _positionType; + + // Whether or not the node will be auto-removed when there are not particles + BOOL _autoRemoveOnFinish; + + // particle idx + NSUInteger _particleIdx; + + // Optimization + CC_UPDATE_PARTICLE_IMP _updateParticleImp; + SEL _updateParticleSel; + + // for batching. If nil, then it won't be batched + CCParticleBatchNode *_batchNode; + + // index of system in batch node array + NSUInteger _atlasIndex; + + //YES if scaled or rotated + BOOL _transformSystemDirty; +} + +/** Is the emitter active */ +@property (nonatomic,readonly) BOOL active; +/** Quantity of particles that are being simulated at the moment */ +@property (nonatomic,readonly) NSUInteger particleCount; +/** How many seconds the emitter wil run. -1 means 'forever' */ +@property (nonatomic,readwrite,assign) float duration; +/** sourcePosition of the emitter */ +@property (nonatomic,readwrite,assign) CGPoint sourcePosition; +/** Position variance of the emitter */ +@property (nonatomic,readwrite,assign) CGPoint posVar; +/** life, and life variation of each particle */ +@property (nonatomic,readwrite,assign) float life; +/** life variance of each particle */ +@property (nonatomic,readwrite,assign) float lifeVar; +/** angle and angle variation of each particle */ +@property (nonatomic,readwrite,assign) float angle; +/** angle variance of each particle */ +@property (nonatomic,readwrite,assign) float angleVar; + +/** Gravity value. Only available in 'Gravity' mode. */ +@property (nonatomic,readwrite,assign) CGPoint gravity; +/** speed of each particle. Only available in 'Gravity' mode. */ +@property (nonatomic,readwrite,assign) float speed; +/** speed variance of each particle. Only available in 'Gravity' mode. */ +@property (nonatomic,readwrite,assign) float speedVar; +/** tangential acceleration of each particle. Only available in 'Gravity' mode. */ +@property (nonatomic,readwrite,assign) float tangentialAccel; +/** tangential acceleration variance of each particle. Only available in 'Gravity' mode. */ +@property (nonatomic,readwrite,assign) float tangentialAccelVar; +/** radial acceleration of each particle. Only available in 'Gravity' mode. */ +@property (nonatomic,readwrite,assign) float radialAccel; +/** radial acceleration variance of each particle. Only available in 'Gravity' mode. */ +@property (nonatomic,readwrite,assign) float radialAccelVar; + +/** The starting radius of the particles. Only available in 'Radius' mode. */ +@property (nonatomic,readwrite,assign) float startRadius; +/** The starting radius variance of the particles. Only available in 'Radius' mode. */ +@property (nonatomic,readwrite,assign) float startRadiusVar; +/** The ending radius of the particles. Only available in 'Radius' mode. */ +@property (nonatomic,readwrite,assign) float endRadius; +/** The ending radius variance of the particles. Only available in 'Radius' mode. */ +@property (nonatomic,readwrite,assign) float endRadiusVar; +/** Number of degress to rotate a particle around the source pos per second. Only available in 'Radius' mode. */ +@property (nonatomic,readwrite,assign) float rotatePerSecond; +/** Variance in degrees for rotatePerSecond. Only available in 'Radius' mode. */ +@property (nonatomic,readwrite,assign) float rotatePerSecondVar; + +/** start size in pixels of each particle */ +@property (nonatomic,readwrite,assign) float startSize; +/** size variance in pixels of each particle */ +@property (nonatomic,readwrite,assign) float startSizeVar; +/** end size in pixels of each particle */ +@property (nonatomic,readwrite,assign) float endSize; +/** end size variance in pixels of each particle */ +@property (nonatomic,readwrite,assign) float endSizeVar; +/** start color of each particle */ +@property (nonatomic,readwrite,assign) ccColor4F startColor; +/** start color variance of each particle */ +@property (nonatomic,readwrite,assign) ccColor4F startColorVar; +/** end color and end color variation of each particle */ +@property (nonatomic,readwrite,assign) ccColor4F endColor; +/** end color variance of each particle */ +@property (nonatomic,readwrite,assign) ccColor4F endColorVar; +//* initial angle of each particle +@property (nonatomic,readwrite,assign) float startSpin; +//* initial angle of each particle +@property (nonatomic,readwrite,assign) float startSpinVar; +//* initial angle of each particle +@property (nonatomic,readwrite,assign) float endSpin; +//* initial angle of each particle +@property (nonatomic,readwrite,assign) float endSpinVar; +/** emission rate of the particles */ +@property (nonatomic,readwrite,assign) float emissionRate; +/** maximum particles of the system */ +@property (nonatomic,readwrite,assign) NSUInteger totalParticles; +/** conforms to CocosNodeTexture protocol */ +@property (nonatomic,readwrite, retain) CCTexture2D * texture; +/** conforms to CocosNodeTexture protocol */ +@property (nonatomic,readwrite) ccBlendFunc blendFunc; +/** does the alpha value modify color */ +@property (nonatomic, readwrite, getter=doesOpacityModifyRGB, assign) BOOL opacityModifyRGB; +/** whether or not the particles are using blend additive. + If enabled, the following blending function will be used. + @code + source blend function = GL_SRC_ALPHA; + dest blend function = GL_ONE; + @endcode + */ +@property (nonatomic,readwrite) BOOL blendAdditive; +/** particles movement type: Free or Grouped + @since v0.8 + */ +@property (nonatomic,readwrite) tCCPositionType positionType; +/** whether or not the node will be auto-removed when it has no particles left. + By default it is NO. + @since v0.8 + */ +@property (nonatomic,readwrite) BOOL autoRemoveOnFinish; +/** Switch between different kind of emitter modes: + - kCCParticleModeGravity: uses gravity, speed, radial and tangential acceleration + - kCCParticleModeRadius: uses radius movement + rotation + */ +@property (nonatomic,readwrite) NSInteger emitterMode; + +/** weak reference to the CCSpriteBatchNode that renders the CCSprite */ +@property (nonatomic,readwrite,assign) CCParticleBatchNode *batchNode; + +@property (nonatomic,readwrite) NSUInteger atlasIndex; + +/** creates an initializes a CCParticleSystem from a plist file. + This plist files can be creted manually or with Particle Designer: + http://particledesigner.71squared.com/ + @since v0.99.3 + */ ++(id) particleWithFile:(NSString*)plistFile; + +/* creates an void particle emitter with a maximun number of particles. + @since v2.1 +*/ ++(id) particleWithTotalParticles:(NSUInteger) numberOfParticles; + + +/** initializes a CCParticleSystem from a plist file. + This plist files can be creted manually or with Particle Designer: + http://particledesigner.71squared.com/ + @since v0.99.3 + */ +-(id) initWithFile:(NSString*) plistFile; + +/** initializes a particle system from a NSDictionary. + @since v0.99.3 + */ +-(id) initWithDictionary:(NSDictionary*)dictionary; + +/** initializes a particle system from a NSDictionary and the path from where to load the png + @since v2.1 + */ +-(id) initWithDictionary:(NSDictionary *)dictionary path:(NSString*)dirname; + +//! Initializes a system with a fixed number of particles +-(id) initWithTotalParticles:(NSUInteger) numberOfParticles; +//! stop emitting particles. Running particles will continue to run until they die +-(void) stopSystem; +//! Kill all living particles. +-(void) resetSystem; +//! whether or not the system is full +-(BOOL) isFull; + +//! should be overriden by subclasses +-(void) updateQuadWithParticle:(tCCParticle*)particle newPosition:(CGPoint)pos; +//! should be overriden by subclasses +-(void) postStep; + +//! called in every loop. +-(void) update: (ccTime) dt; + +-(void) updateWithNoTime; + +@end diff --git "a/21451198\345\215\242\350\266\205/project5/MyPlane/libs/cocos2d/CCParticleSystem.m" "b/21451198\345\215\242\350\266\205/project5/MyPlane/libs/cocos2d/CCParticleSystem.m" new file mode 100644 index 00000000..908d5205 --- /dev/null +++ "b/21451198\345\215\242\350\266\205/project5/MyPlane/libs/cocos2d/CCParticleSystem.m" @@ -0,0 +1,929 @@ +/* + * cocos2d for iPhone: http://www.cocos2d-iphone.org + * + * Copyright (c) 2008-2010 Ricardo Quesada + * Copyright (c) 2011 Zynga Inc. + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + * THE SOFTWARE. + * + */ + + +// ideas taken from: +// . The ocean spray in your face [Jeff Lander] +// http://www.double.co.nz/dust/col0798.pdf +// . Building an Advanced Particle System [John van der Burg] +// http://www.gamasutra.com/features/20000623/vanderburg_01.htm +// . LOVE game engine +// http://love2d.org/ +// +// +// Radius mode support, from 71 squared +// http://particledesigner.71squared.com/ +// +// IMPORTANT: Particle Designer is supported by cocos2d, but +// 'Radius Mode' in Particle Designer uses a fixed emit rate of 30 hz. Since that can't be guarateed in cocos2d, +// cocos2d uses a another approach, but the results are almost identical. +// + +// opengl +#import "Platforms/CCGL.h" + +// cocos2d +#import "ccConfig.h" +#import "CCParticleSystem.h" +#import "CCParticleBatchNode.h" +#import "CCTextureCache.h" +#import "CCTextureAtlas.h" +#import "ccMacros.h" +#import "Support/CCProfiling.h" + +// support +#import "Support/OpenGL_Internal.h" +#import "Support/CGPointExtension.h" +#import "Support/base64.h" +#import "Support/ZipUtils.h" +#import "Support/CCFileUtils.h" + +@interface CCParticleSystem () +-(void) updateBlendFunc; +@end + +@implementation CCParticleSystem +@synthesize active = _active, duration = _duration; +@synthesize sourcePosition = _sourcePosition, posVar = _posVar; +@synthesize particleCount = _particleCount; +@synthesize life = _life, lifeVar = _lifeVar; +@synthesize angle = _angle, angleVar = _angleVar; +@synthesize startColor = _startColor, startColorVar = _startColorVar; +@synthesize endColor = _endColor, endColorVar = _endColorVar; +@synthesize startSpin = _startSpin, startSpinVar = _startSpinVar; +@synthesize endSpin = _endSpin, endSpinVar = _endSpinVar; +@synthesize emissionRate = _emissionRate; +@synthesize startSize = _startSize, startSizeVar = _startSizeVar; +@synthesize endSize = _endSize, endSizeVar = _endSizeVar; +@synthesize opacityModifyRGB = _opacityModifyRGB; +@synthesize blendFunc = _blendFunc; +@synthesize positionType = _positionType; +@synthesize autoRemoveOnFinish = _autoRemoveOnFinish; +@synthesize emitterMode = _emitterMode; +@synthesize atlasIndex = _atlasIndex; +@synthesize totalParticles = _totalParticles; + ++(id) particleWithFile:(NSString*) plistFile +{ + return [[[self alloc] initWithFile:plistFile] autorelease]; +} + ++(id) particleWithTotalParticles:(NSUInteger) numberOfParticles +{ + return [[[self alloc] initWithTotalParticles:numberOfParticles] autorelease]; +} + +-(id) init { + return [self initWithTotalParticles:150]; +} + +-(id) initWithFile:(NSString *)plistFile +{ + NSString *path = [[CCFileUtils sharedFileUtils] fullPathForFilename:plistFile]; + NSDictionary *dict = [NSDictionary dictionaryWithContentsOfFile:path]; + + NSAssert( dict != nil, @"Particles: file not found"); + + return [self initWithDictionary:dict path:[plistFile stringByDeletingLastPathComponent]]; +} + + +-(id) initWithDictionary:(NSDictionary *)dictionary +{ + return [self initWithDictionary:dictionary path:@""]; +} + +-(id) initWithDictionary:(NSDictionary *)dictionary path:(NSString*)dirname +{ + NSUInteger maxParticles = [[dictionary valueForKey:@"maxParticles"] integerValue]; + // self, not super + + if ((self=[self initWithTotalParticles:maxParticles] ) ) + { + // angle + _angle = [[dictionary valueForKey:@"angle"] floatValue]; + _angleVar = [[dictionary valueForKey:@"angleVariance"] floatValue]; + + // duration + _duration = [[dictionary valueForKey:@"duration"] floatValue]; + + // blend function + _blendFunc.src = [[dictionary valueForKey:@"blendFuncSource"] intValue]; + _blendFunc.dst = [[dictionary valueForKey:@"blendFuncDestination"] intValue]; + + // color + float r,g,b,a; + + r = [[dictionary valueForKey:@"startColorRed"] floatValue]; + g = [[dictionary valueForKey:@"startColorGreen"] floatValue]; + b = [[dictionary valueForKey:@"startColorBlue"] floatValue]; + a = [[dictionary valueForKey:@"startColorAlpha"] floatValue]; + _startColor = (ccColor4F) {r,g,b,a}; + + r = [[dictionary valueForKey:@"startColorVarianceRed"] floatValue]; + g = [[dictionary valueForKey:@"startColorVarianceGreen"] floatValue]; + b = [[dictionary valueForKey:@"startColorVarianceBlue"] floatValue]; + a = [[dictionary valueForKey:@"startColorVarianceAlpha"] floatValue]; + _startColorVar = (ccColor4F) {r,g,b,a}; + + r = [[dictionary valueForKey:@"finishColorRed"] floatValue]; + g = [[dictionary valueForKey:@"finishColorGreen"] floatValue]; + b = [[dictionary valueForKey:@"finishColorBlue"] floatValue]; + a = [[dictionary valueForKey:@"finishColorAlpha"] floatValue]; + _endColor = (ccColor4F) {r,g,b,a}; + + r = [[dictionary valueForKey:@"finishColorVarianceRed"] floatValue]; + g = [[dictionary valueForKey:@"finishColorVarianceGreen"] floatValue]; + b = [[dictionary valueForKey:@"finishColorVarianceBlue"] floatValue]; + a = [[dictionary valueForKey:@"finishColorVarianceAlpha"] floatValue]; + _endColorVar = (ccColor4F) {r,g,b,a}; + + // particle size + _startSize = [[dictionary valueForKey:@"startParticleSize"] floatValue]; + _startSizeVar = [[dictionary valueForKey:@"startParticleSizeVariance"] floatValue]; + _endSize = [[dictionary valueForKey:@"finishParticleSize"] floatValue]; + _endSizeVar = [[dictionary valueForKey:@"finishParticleSizeVariance"] floatValue]; + + // position + float x = [[dictionary valueForKey:@"sourcePositionx"] floatValue]; + float y = [[dictionary valueForKey:@"sourcePositiony"] floatValue]; + self.position = ccp(x,y); + _posVar.x = [[dictionary valueForKey:@"sourcePositionVariancex"] floatValue]; + _posVar.y = [[dictionary valueForKey:@"sourcePositionVariancey"] floatValue]; + + // Spinning + _startSpin = [[dictionary valueForKey:@"rotationStart"] floatValue]; + _startSpinVar = [[dictionary valueForKey:@"rotationStartVariance"] floatValue]; + _endSpin = [[dictionary valueForKey:@"rotationEnd"] floatValue]; + _endSpinVar = [[dictionary valueForKey:@"rotationEndVariance"] floatValue]; + + _emitterMode = [[dictionary valueForKey:@"emitterType"] intValue]; + + // Mode A: Gravity + tangential accel + radial accel + if( _emitterMode == kCCParticleModeGravity ) { + // gravity + _mode.A.gravity.x = [[dictionary valueForKey:@"gravityx"] floatValue]; + _mode.A.gravity.y = [[dictionary valueForKey:@"gravityy"] floatValue]; + + // + // speed + _mode.A.speed = [[dictionary valueForKey:@"speed"] floatValue]; + _mode.A.speedVar = [[dictionary valueForKey:@"speedVariance"] floatValue]; + + // radial acceleration + NSString *tmp = [dictionary valueForKey:@"radialAcceleration"]; + _mode.A.radialAccel = tmp ? [tmp floatValue] : 0; + + tmp = [dictionary valueForKey:@"radialAccelVariance"]; + _mode.A.radialAccelVar = tmp ? [tmp floatValue] : 0; + + // tangential acceleration + tmp = [dictionary valueForKey:@"tangentialAcceleration"]; + _mode.A.tangentialAccel = tmp ? [tmp floatValue] : 0; + + tmp = [dictionary valueForKey:@"tangentialAccelVariance"]; + _mode.A.tangentialAccelVar = tmp ? [tmp floatValue] : 0; + } + + // or Mode B: radius movement + else if( _emitterMode == kCCParticleModeRadius ) { + float maxRadius = [[dictionary valueForKey:@"maxRadius"] floatValue]; + float maxRadiusVar = [[dictionary valueForKey:@"maxRadiusVariance"] floatValue]; + float minRadius = [[dictionary valueForKey:@"minRadius"] floatValue]; + + _mode.B.startRadius = maxRadius; + _mode.B.startRadiusVar = maxRadiusVar; + _mode.B.endRadius = minRadius; + _mode.B.endRadiusVar = 0; + _mode.B.rotatePerSecond = [[dictionary valueForKey:@"rotatePerSecond"] floatValue]; + _mode.B.rotatePerSecondVar = [[dictionary valueForKey:@"rotatePerSecondVariance"] floatValue]; + + } else { + NSAssert( NO, @"Invalid emitterType in config file"); + } + + // life span + _life = [[dictionary valueForKey:@"particleLifespan"] floatValue]; + _lifeVar = [[dictionary valueForKey:@"particleLifespanVariance"] floatValue]; + + // emission Rate + _emissionRate = _totalParticles/_life; + + //don't get the internal texture if a batchNode is used + if (!_batchNode) + { + // Set a compatible default for the alpha transfer + _opacityModifyRGB = NO; + + // texture + // Try to get the texture from the cache + + NSString *textureName = [dictionary valueForKey:@"textureFileName"]; + NSString *textureDir = [textureName stringByDeletingLastPathComponent]; + + // For backward compatibility, only append the dirname if both dirnames are the same + if( ! [textureDir isEqualToString:dirname] ) + textureName = [dirname stringByAppendingPathComponent:textureName]; + + CCTexture2D *tex = [[CCTextureCache sharedTextureCache] addImage:textureName]; + + if( tex ) + [self setTexture:tex]; + else { + + NSString *textureData = [dictionary valueForKey:@"textureImageData"]; + NSAssert( textureData, @"CCParticleSystem: Couldn't load texture"); + + // if it fails, try to get it from the base64-gzipped data + unsigned char *buffer = NULL; + int len = base64Decode((unsigned char*)[textureData UTF8String], (unsigned int)[textureData length], &buffer); + NSAssert( buffer != NULL, @"CCParticleSystem: error decoding textureImageData"); + + unsigned char *deflated = NULL; + NSUInteger deflatedLen = ccInflateMemory(buffer, len, &deflated); + free( buffer ); + + NSAssert( deflated != NULL, @"CCParticleSystem: error ungzipping textureImageData"); + NSData *data = [[NSData alloc] initWithBytes:deflated length:deflatedLen]; + +#ifdef __CC_PLATFORM_IOS + UIImage *image = [[UIImage alloc] initWithData:data]; +#elif defined(__CC_PLATFORM_MAC) + NSBitmapImageRep *image = [[NSBitmapImageRep alloc] initWithData:data]; +#endif + + free(deflated); deflated = NULL; + + [self setTexture: [ [CCTextureCache sharedTextureCache] addCGImage:[image CGImage] forKey:textureName]]; + [data release]; + [image release]; + } + + NSAssert( [self texture] != NULL, @"CCParticleSystem: error loading the texture"); + } + } + + return self; +} + +-(id) initWithTotalParticles:(NSUInteger) numberOfParticles +{ + if( (self=[super init]) ) { + + _totalParticles = numberOfParticles; + + _particles = calloc( _totalParticles, sizeof(tCCParticle) ); + + if( ! _particles ) { + CCLOG(@"Particle system: not enough memory"); + [self release]; + return nil; + } + _allocatedParticles = numberOfParticles; + + if (_batchNode) + { + for (int i = 0; i < _totalParticles; i++) + { + _particles[i].atlasIndex=i; + } + } + + // default, active + _active = YES; + + // default blend function + _blendFunc = (ccBlendFunc) { CC_BLEND_SRC, CC_BLEND_DST }; + + // default movement type; + _positionType = kCCPositionTypeFree; + + // by default be in mode A: + _emitterMode = kCCParticleModeGravity; + + _autoRemoveOnFinish = NO; + + // Optimization: compile updateParticle method + _updateParticleSel = @selector(updateQuadWithParticle:newPosition:); + _updateParticleImp = (CC_UPDATE_PARTICLE_IMP) [self methodForSelector:_updateParticleSel]; + + //for batchNode + _transformSystemDirty = NO; + + // update after action in run! + [self scheduleUpdateWithPriority:1]; + } + return self; +} + +-(void) dealloc +{ + // Since the scheduler retains the "target (in this case the ParticleSystem) + // it is not needed to call "unscheduleUpdate" here. In fact, it will be called in "cleanup" +// [self unscheduleUpdate]; + + free( _particles ); + + [_texture release]; + + [super dealloc]; +} + +-(void) initParticle: (tCCParticle*) particle +{ + //CGPoint currentPosition = _position; + // timeToLive + // no negative life. prevent division by 0 + particle->timeToLive = _life + _lifeVar * CCRANDOM_MINUS1_1(); + particle->timeToLive = MAX(0, particle->timeToLive); + + // position + particle->pos.x = _sourcePosition.x + _posVar.x * CCRANDOM_MINUS1_1(); + particle->pos.y = _sourcePosition.y + _posVar.y * CCRANDOM_MINUS1_1(); + + // Color + ccColor4F start; + start.r = clampf( _startColor.r + _startColorVar.r * CCRANDOM_MINUS1_1(), 0, 1); + start.g = clampf( _startColor.g + _startColorVar.g * CCRANDOM_MINUS1_1(), 0, 1); + start.b = clampf( _startColor.b + _startColorVar.b * CCRANDOM_MINUS1_1(), 0, 1); + start.a = clampf( _startColor.a + _startColorVar.a * CCRANDOM_MINUS1_1(), 0, 1); + + ccColor4F end; + end.r = clampf( _endColor.r + _endColorVar.r * CCRANDOM_MINUS1_1(), 0, 1); + end.g = clampf( _endColor.g + _endColorVar.g * CCRANDOM_MINUS1_1(), 0, 1); + end.b = clampf( _endColor.b + _endColorVar.b * CCRANDOM_MINUS1_1(), 0, 1); + end.a = clampf( _endColor.a + _endColorVar.a * CCRANDOM_MINUS1_1(), 0, 1); + + particle->color = start; + particle->deltaColor.r = (end.r - start.r) / particle->timeToLive; + particle->deltaColor.g = (end.g - start.g) / particle->timeToLive; + particle->deltaColor.b = (end.b - start.b) / particle->timeToLive; + particle->deltaColor.a = (end.a - start.a) / particle->timeToLive; + + // size + float startS = _startSize + _startSizeVar * CCRANDOM_MINUS1_1(); + startS = MAX(0, startS); // No negative value + + particle->size = startS; + if( _endSize == kCCParticleStartSizeEqualToEndSize ) + particle->deltaSize = 0; + else { + float endS = _endSize + _endSizeVar * CCRANDOM_MINUS1_1(); + endS = MAX(0, endS); // No negative values + particle->deltaSize = (endS - startS) / particle->timeToLive; + } + + // rotation + float startA = _startSpin + _startSpinVar * CCRANDOM_MINUS1_1(); + float endA = _endSpin + _endSpinVar * CCRANDOM_MINUS1_1(); + particle->rotation = startA; + particle->deltaRotation = (endA - startA) / particle->timeToLive; + + // position + if( _positionType == kCCPositionTypeFree ) + particle->startPos = [self convertToWorldSpace:CGPointZero]; + + else if( _positionType == kCCPositionTypeRelative ) + particle->startPos = _position; + + + // direction + float a = CC_DEGREES_TO_RADIANS( _angle + _angleVar * CCRANDOM_MINUS1_1() ); + + // Mode Gravity: A + if( _emitterMode == kCCParticleModeGravity ) { + + CGPoint v = {cosf( a ), sinf( a )}; + float s = _mode.A.speed + _mode.A.speedVar * CCRANDOM_MINUS1_1(); + + // direction + particle->mode.A.dir = ccpMult( v, s ); + + // radial accel + particle->mode.A.radialAccel = _mode.A.radialAccel + _mode.A.radialAccelVar * CCRANDOM_MINUS1_1(); + + // tangential accel + particle->mode.A.tangentialAccel = _mode.A.tangentialAccel + _mode.A.tangentialAccelVar * CCRANDOM_MINUS1_1(); + } + + // Mode Radius: B + else { + // Set the default diameter of the particle from the source position + float startRadius = _mode.B.startRadius + _mode.B.startRadiusVar * CCRANDOM_MINUS1_1(); + float endRadius = _mode.B.endRadius + _mode.B.endRadiusVar * CCRANDOM_MINUS1_1(); + + particle->mode.B.radius = startRadius; + + if( _mode.B.endRadius == kCCParticleStartRadiusEqualToEndRadius ) + particle->mode.B.deltaRadius = 0; + else + particle->mode.B.deltaRadius = (endRadius - startRadius) / particle->timeToLive; + + particle->mode.B.angle = a; + particle->mode.B.degreesPerSecond = CC_DEGREES_TO_RADIANS(_mode.B.rotatePerSecond + _mode.B.rotatePerSecondVar * CCRANDOM_MINUS1_1()); + } +} + +-(BOOL) addParticle +{ + if( [self isFull] ) + return NO; + + tCCParticle * particle = &_particles[ _particleCount ]; + + [self initParticle: particle]; + _particleCount++; + + return YES; +} + +-(void) stopSystem +{ + _active = NO; + _elapsed = _duration; + _emitCounter = 0; +} + +-(void) resetSystem +{ + _active = YES; + _elapsed = 0; + for(_particleIdx = 0; _particleIdx < _particleCount; ++_particleIdx) { + tCCParticle *p = &_particles[_particleIdx]; + p->timeToLive = 0; + } + +} + +-(BOOL) isFull +{ + return (_particleCount == _totalParticles); +} + +#pragma mark ParticleSystem - MainLoop +-(void) update: (ccTime) dt +{ + CC_PROFILER_START_CATEGORY(kCCProfilerCategoryParticles , @"CCParticleSystem - update"); + + if( _active && _emissionRate ) { + float rate = 1.0f / _emissionRate; + + //issue #1201, prevent bursts of particles, due to too high emitCounter + if (_particleCount < _totalParticles) + _emitCounter += dt; + + while( _particleCount < _totalParticles && _emitCounter > rate ) { + [self addParticle]; + _emitCounter -= rate; + } + + _elapsed += dt; + + if(_duration != -1 && _duration < _elapsed) + [self stopSystem]; + } + + _particleIdx = 0; + + CGPoint currentPosition = CGPointZero; + if( _positionType == kCCPositionTypeFree ) + currentPosition = [self convertToWorldSpace:CGPointZero]; + + else if( _positionType == kCCPositionTypeRelative ) + currentPosition = _position; + + if (_visible) + { + while( _particleIdx < _particleCount ) + { + tCCParticle *p = &_particles[_particleIdx]; + + // life + p->timeToLive -= dt; + + if( p->timeToLive > 0 ) { + + // Mode A: gravity, direction, tangential accel & radial accel + if( _emitterMode == kCCParticleModeGravity ) { + CGPoint tmp, radial, tangential; + + radial = CGPointZero; + // radial acceleration + if(p->pos.x || p->pos.y) + radial = ccpNormalize(p->pos); + + tangential = radial; + radial = ccpMult(radial, p->mode.A.radialAccel); + + // tangential acceleration + float newy = tangential.x; + tangential.x = -tangential.y; + tangential.y = newy; + tangential = ccpMult(tangential, p->mode.A.tangentialAccel); + + // (gravity + radial + tangential) * dt + tmp = ccpAdd( ccpAdd( radial, tangential), _mode.A.gravity); + tmp = ccpMult( tmp, dt); + p->mode.A.dir = ccpAdd( p->mode.A.dir, tmp); + tmp = ccpMult(p->mode.A.dir, dt); + p->pos = ccpAdd( p->pos, tmp ); + } + + // Mode B: radius movement + else { + // Update the angle and radius of the particle. + p->mode.B.angle += p->mode.B.degreesPerSecond * dt; + p->mode.B.radius += p->mode.B.deltaRadius * dt; + + p->pos.x = - cosf(p->mode.B.angle) * p->mode.B.radius; + p->pos.y = - sinf(p->mode.B.angle) * p->mode.B.radius; + } + + // color + p->color.r += (p->deltaColor.r * dt); + p->color.g += (p->deltaColor.g * dt); + p->color.b += (p->deltaColor.b * dt); + p->color.a += (p->deltaColor.a * dt); + + // size + p->size += (p->deltaSize * dt); + p->size = MAX( 0, p->size ); + + // angle + p->rotation += (p->deltaRotation * dt); + + // + // update values in quad + // + + CGPoint newPos; + + if( _positionType == kCCPositionTypeFree || _positionType == kCCPositionTypeRelative ) + { + CGPoint diff = ccpSub( currentPosition, p->startPos ); + newPos = ccpSub(p->pos, diff); + } else + newPos = p->pos; + + // translate newPos to correct position, since matrix transform isn't performed in batchnode + // don't update the particle with the new position information, it will interfere with the radius and tangential calculations + if (_batchNode) + { + newPos.x+=_position.x; + newPos.y+=_position.y; + } + + _updateParticleImp(self, _updateParticleSel, p, newPos); + + // update particle counter + _particleIdx++; + + } else { + // life < 0 + NSInteger currentIndex = p->atlasIndex; + + if( _particleIdx != _particleCount-1 ) + _particles[_particleIdx] = _particles[_particleCount-1]; + + if (_batchNode) + { + //disable the switched particle + [_batchNode disableParticle:(_atlasIndex+currentIndex)]; + + //switch indexes + _particles[_particleCount-1].atlasIndex = currentIndex; + } + + _particleCount--; + + if( _particleCount == 0 && _autoRemoveOnFinish ) { + [self unscheduleUpdate]; + [_parent removeChild:self cleanup:YES]; + return; + } + } + }//while + _transformSystemDirty = NO; + } + + if (!_batchNode) + [self postStep]; + + CC_PROFILER_STOP_CATEGORY(kCCProfilerCategoryParticles , @"CCParticleSystem - update"); +} + +-(void) updateWithNoTime +{ + [self update:0.0f]; +} + +-(void) updateQuadWithParticle:(tCCParticle*)particle newPosition:(CGPoint)pos; +{ + // should be overriden +} + +-(void) postStep +{ + // should be overriden +} + +#pragma mark ParticleSystem - CCTexture protocol + +-(void) setTexture:(CCTexture2D*) texture +{ + if( _texture != texture ) { + [_texture release]; + _texture = [texture retain]; + + [self updateBlendFunc]; + } +} + +-(CCTexture2D*) texture +{ + return _texture; +} + +#pragma mark ParticleSystem - Additive Blending +-(void) setBlendAdditive:(BOOL)additive +{ + if( additive ) { + _blendFunc.src = GL_SRC_ALPHA; + _blendFunc.dst = GL_ONE; + + } else { + + if( _texture && ! [_texture hasPremultipliedAlpha] ) { + _blendFunc.src = GL_SRC_ALPHA; + _blendFunc.dst = GL_ONE_MINUS_SRC_ALPHA; + } else { + _blendFunc.src = CC_BLEND_SRC; + _blendFunc.dst = CC_BLEND_DST; + } + } +} + +-(BOOL) blendAdditive +{ + return( _blendFunc.src == GL_SRC_ALPHA && _blendFunc.dst == GL_ONE); +} + +-(void) setBlendFunc:(ccBlendFunc)blendFunc +{ + if( _blendFunc.src != blendFunc.src || _blendFunc.dst != blendFunc.dst ) { + _blendFunc = blendFunc; + [self updateBlendFunc]; + } +} +#pragma mark ParticleSystem - Total Particles Property + +- (void) setTotalParticles:(NSUInteger)tp +{ + NSAssert( tp <= _allocatedParticles, @"Particle: resizing particle array only supported for quads"); + _totalParticles = tp; +} + +- (NSUInteger) _totalParticles +{ + return _totalParticles; +} + +#pragma mark ParticleSystem - Properties of Gravity Mode +-(void) setTangentialAccel:(float)t +{ + NSAssert( _emitterMode == kCCParticleModeGravity, @"Particle Mode should be Gravity"); + _mode.A.tangentialAccel = t; +} +-(float) tangentialAccel +{ + NSAssert( _emitterMode == kCCParticleModeGravity, @"Particle Mode should be Gravity"); + return _mode.A.tangentialAccel; +} + +-(void) setTangentialAccelVar:(float)t +{ + NSAssert( _emitterMode == kCCParticleModeGravity, @"Particle Mode should be Gravity"); + _mode.A.tangentialAccelVar = t; +} +-(float) tangentialAccelVar +{ + NSAssert( _emitterMode == kCCParticleModeGravity, @"Particle Mode should be Gravity"); + return _mode.A.tangentialAccelVar; +} + +-(void) setRadialAccel:(float)t +{ + NSAssert( _emitterMode == kCCParticleModeGravity, @"Particle Mode should be Gravity"); + _mode.A.radialAccel = t; +} +-(float) radialAccel +{ + NSAssert( _emitterMode == kCCParticleModeGravity, @"Particle Mode should be Gravity"); + return _mode.A.radialAccel; +} + +-(void) setRadialAccelVar:(float)t +{ + NSAssert( _emitterMode == kCCParticleModeGravity, @"Particle Mode should be Gravity"); + _mode.A.radialAccelVar = t; +} +-(float) radialAccelVar +{ + NSAssert( _emitterMode == kCCParticleModeGravity, @"Particle Mode should be Gravity"); + return _mode.A.radialAccelVar; +} + +-(void) setGravity:(CGPoint)g +{ + NSAssert( _emitterMode == kCCParticleModeGravity, @"Particle Mode should be Gravity"); + _mode.A.gravity = g; +} +-(CGPoint) gravity +{ + NSAssert( _emitterMode == kCCParticleModeGravity, @"Particle Mode should be Gravity"); + return _mode.A.gravity; +} + +-(void) setSpeed:(float)speed +{ + NSAssert( _emitterMode == kCCParticleModeGravity, @"Particle Mode should be Gravity"); + _mode.A.speed = speed; +} +-(float) speed +{ + NSAssert( _emitterMode == kCCParticleModeGravity, @"Particle Mode should be Gravity"); + return _mode.A.speed; +} + +-(void) setSpeedVar:(float)speedVar +{ + NSAssert( _emitterMode == kCCParticleModeGravity, @"Particle Mode should be Gravity"); + _mode.A.speedVar = speedVar; +} +-(float) speedVar +{ + NSAssert( _emitterMode == kCCParticleModeGravity, @"Particle Mode should be Gravity"); + return _mode.A.speedVar; +} + +#pragma mark ParticleSystem - Properties of Radius Mode + +-(void) setStartRadius:(float)startRadius +{ + NSAssert( _emitterMode == kCCParticleModeRadius, @"Particle Mode should be Radius"); + _mode.B.startRadius = startRadius; +} +-(float) startRadius +{ + NSAssert( _emitterMode == kCCParticleModeRadius, @"Particle Mode should be Radius"); + return _mode.B.startRadius; +} + +-(void) setStartRadiusVar:(float)startRadiusVar +{ + NSAssert( _emitterMode == kCCParticleModeRadius, @"Particle Mode should be Radius"); + _mode.B.startRadiusVar = startRadiusVar; +} +-(float) startRadiusVar +{ + NSAssert( _emitterMode == kCCParticleModeRadius, @"Particle Mode should be Radius"); + return _mode.B.startRadiusVar; +} + +-(void) setEndRadius:(float)endRadius +{ + NSAssert( _emitterMode == kCCParticleModeRadius, @"Particle Mode should be Radius"); + _mode.B.endRadius = endRadius; +} +-(float) endRadius +{ + NSAssert( _emitterMode == kCCParticleModeRadius, @"Particle Mode should be Radius"); + return _mode.B.endRadius; +} + +-(void) setEndRadiusVar:(float)endRadiusVar +{ + NSAssert( _emitterMode == kCCParticleModeRadius, @"Particle Mode should be Radius"); + _mode.B.endRadiusVar = endRadiusVar; +} +-(float) endRadiusVar +{ + NSAssert( _emitterMode == kCCParticleModeRadius, @"Particle Mode should be Radius"); + return _mode.B.endRadiusVar; +} + +-(void) setRotatePerSecond:(float)degrees +{ + NSAssert( _emitterMode == kCCParticleModeRadius, @"Particle Mode should be Radius"); + _mode.B.rotatePerSecond = degrees; +} +-(float) rotatePerSecond +{ + NSAssert( _emitterMode == kCCParticleModeRadius, @"Particle Mode should be Radius"); + return _mode.B.rotatePerSecond; +} + +-(void) setRotatePerSecondVar:(float)degrees +{ + NSAssert( _emitterMode == kCCParticleModeRadius, @"Particle Mode should be Radius"); + _mode.B.rotatePerSecondVar = degrees; +} +-(float) rotatePerSecondVar +{ + NSAssert( _emitterMode == kCCParticleModeRadius, @"Particle Mode should be Radius"); + return _mode.B.rotatePerSecondVar; +} + +#pragma mark ParticleSystem - methods for batchNode rendering + +-(CCParticleBatchNode*) batchNode +{ + return _batchNode; +} + +-(void) setBatchNode:(CCParticleBatchNode*) batchNode +{ + if( _batchNode != batchNode ) { + + _batchNode = batchNode; // weak reference + + if( batchNode ) { + //each particle needs a unique index + for (int i = 0; i < _totalParticles; i++) + { + _particles[i].atlasIndex=i; + } + } + } +} + +//don't use a transform matrix, this is faster +-(void) setScale:(float) s +{ + _transformSystemDirty = YES; + [super setScale:s]; +} + +-(void) setRotation: (float)newRotation +{ + _transformSystemDirty = YES; + [super setRotation:newRotation]; +} + +-(void) setScaleX: (float)newScaleX +{ + _transformSystemDirty = YES; + [super setScaleX:newScaleX]; +} + +-(void) setScaleY: (float)newScaleY +{ + _transformSystemDirty = YES; + [super setScaleY:newScaleY]; +} + +#pragma mark Particle - Helpers + +-(void) updateBlendFunc +{ + NSAssert(! _batchNode, @"Can't change blending functions when the particle is being batched"); + + BOOL premultiplied = [_texture hasPremultipliedAlpha]; + + _opacityModifyRGB = NO; + + if( _texture && ( _blendFunc.src == CC_BLEND_SRC && _blendFunc.dst == CC_BLEND_DST ) ) { + if( premultiplied ) + _opacityModifyRGB = YES; + else { + _blendFunc.src = GL_SRC_ALPHA; + _blendFunc.dst = GL_ONE_MINUS_SRC_ALPHA; + } + } +} + + +@end diff --git "a/21451198\345\215\242\350\266\205/project5/MyPlane/libs/cocos2d/CCParticleSystemQuad.h" "b/21451198\345\215\242\350\266\205/project5/MyPlane/libs/cocos2d/CCParticleSystemQuad.h" new file mode 100644 index 00000000..11b3e38b --- /dev/null +++ "b/21451198\345\215\242\350\266\205/project5/MyPlane/libs/cocos2d/CCParticleSystemQuad.h" @@ -0,0 +1,73 @@ +/* + * cocos2d for iPhone: http://www.cocos2d-iphone.org + * + * Copyright (c) 2009 Leonardo Kasperavičius + * + * Copyright (c) 2008-2010 Ricardo Quesada + * Copyright (c) 2011 Zynga Inc. + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + * THE SOFTWARE. + * + */ + + +#import "CCParticleSystem.h" +#import "ccConfig.h" + +@class CCSpriteFrame; + +/** CCParticleSystemQuad is a subclass of CCParticleSystem + + It includes all the features of ParticleSystem. + + Special features and Limitations: + - Particle size can be any float number. + - The system can be scaled + - The particles can be rotated + - It supports subrects + - It supports batched rendering since 1.1 + @since v0.8 + */ +@interface CCParticleSystemQuad : CCParticleSystem +{ + ccV3F_C4B_T2F_Quad *_quads; // quads to be rendered + GLushort *_indices; // indices + GLuint _VAOname; + GLuint _buffersVBO[2]; //0: vertex 1: indices +} + +/** initialices the indices for the vertices */ +-(void) initIndices; + +/** initilizes the texture with a rectangle measured Points */ +-(void) initTexCoordsWithRect:(CGRect)rect; + +/** Sets a new CCSpriteFrame as particle. + WARNING: this method is experimental. Use setTexture:withRect instead. + @since v0.99.4 + */ +-(void)setDisplayFrame:(CCSpriteFrame*)spriteFrame; + +/** Sets a new texture with a rect. The rect is in Points. + @since v0.99.4 + */ +-(void) setTexture:(CCTexture2D *)texture withRect:(CGRect)rect; + +@end + diff --git "a/21451198\345\215\242\350\266\205/project5/MyPlane/libs/cocos2d/CCParticleSystemQuad.m" "b/21451198\345\215\242\350\266\205/project5/MyPlane/libs/cocos2d/CCParticleSystemQuad.m" new file mode 100644 index 00000000..c60b5b4f --- /dev/null +++ "b/21451198\345\215\242\350\266\205/project5/MyPlane/libs/cocos2d/CCParticleSystemQuad.m" @@ -0,0 +1,496 @@ +/* + * cocos2d for iPhone: http://www.cocos2d-iphone.org + * + * Copyright (c) 2009 Leonardo Kasperavičius + * + * Copyright (c) 2008-2010 Ricardo Quesada + * Copyright (c) 2011 Zynga Inc. + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + * THE SOFTWARE. + * + */ + + +// opengl +#import "Platforms/CCGL.h" + +// cocos2d +#import "ccConfig.h" +#import "CCParticleSystemQuad.h" +#import "CCParticleBatchNode.h" +#import "CCTextureAtlas.h" +#import "CCTextureCache.h" +#import "ccMacros.h" +#import "CCSpriteFrame.h" +#import "CCDirector.h" +#import "CCShaderCache.h" +#import "ccGLStateCache.h" +#import "CCGLProgram.h" +#import "CCConfiguration.h" + +// support +#import "Support/OpenGL_Internal.h" +#import "Support/CGPointExtension.h" +#import "Support/TransformUtils.h" +#import "Support/NSThread+performBlock.h" + +// extern +#import "kazmath/GL/matrix.h" + +@interface CCParticleSystemQuad () +-(void) initVAO; +-(BOOL) allocMemory; +@end + +@implementation CCParticleSystemQuad + +// overriding the init method +-(id) initWithTotalParticles:(NSUInteger) numberOfParticles +{ + // base initialization + if( (self=[super initWithTotalParticles:numberOfParticles]) ) { + + // allocating data space + if( ! [self allocMemory] ) { + [self release]; + return nil; + } + + // Don't initialize the texCoords yet since there are not textures +// [self initTexCoordsWithRect:CGRectMake(0, 0, [_texture pixelsWide], [_texture pixelsHigh])]; + + [self initIndices]; + [self initVAO]; + + self.shaderProgram = [[CCShaderCache sharedShaderCache] programForKey:kCCShader_PositionTextureColor]; + } + + return self; +} + +-(BOOL) allocMemory +{ + NSAssert( ( !_quads && !_indices), @"Memory already alloced"); + NSAssert( !_batchNode, @"Memory should not be alloced when not using batchNode"); + + _quads = calloc( sizeof(_quads[0]) * _totalParticles, 1 ); + _indices = calloc( sizeof(_indices[0]) * _totalParticles * 6, 1 ); + + if( !_quads || !_indices) { + CCLOG(@"cocos2d: Particle system: not enough memory"); + if( _quads ) + free( _quads ); + if(_indices) + free(_indices); + + return NO; + } + + return YES; +} + +- (void) setTotalParticles:(NSUInteger)tp +{ + // If we are setting the total numer of particles to a number higher + // than what is allocated, we need to allocate new arrays + if( tp > _allocatedParticles ) + { + // Allocate new memory + size_t particlesSize = tp * sizeof(tCCParticle); + size_t quadsSize = sizeof(_quads[0]) * tp * 1; + size_t indicesSize = sizeof(_indices[0]) * tp * 6 * 1; + + tCCParticle* particlesNew = realloc(_particles, particlesSize); + ccV3F_C4B_T2F_Quad *quadsNew = realloc(_quads, quadsSize); + GLushort* indicesNew = realloc(_indices, indicesSize); + + if (particlesNew && quadsNew && indicesNew) + { + // Assign pointers + _particles = particlesNew; + _quads = quadsNew; + _indices = indicesNew; + + // Clear the memory + // XXX: Bug? If the quads are cleared, then drawing doesn't work... WHY??? XXX +// memset(_quads, 0, quadsSize); + memset(_particles, 0, particlesSize); + memset(_indices, 0, indicesSize); + + _allocatedParticles = tp; + } + else + { + // Out of memory, failed to resize some array + if (particlesNew) _particles = particlesNew; + if (quadsNew) _quads = quadsNew; + if (indicesNew) _indices = indicesNew; + + CCLOG(@"Particle system: out of memory"); + return; + } + + _totalParticles = tp; + + // Init particles + if (_batchNode) + { + for (int i = 0; i < _totalParticles; i++) + { + _particles[i].atlasIndex=i; + } + } + + [self initIndices]; + + // clean VAO + glDeleteBuffers(2, &_buffersVBO[0]); + glDeleteVertexArrays(1, &_VAOname); + + [self initVAO]; + } + else + { + _totalParticles = tp; + } + + [self resetSystem]; +} + +-(void) initVAO +{ + // VAO requires GL_APPLE_vertex_array_object in order to be created on a different thread + // https://devforums.apple.com/thread/145566?tstart=0 + + void (^createVAO)(void) = ^ { + glGenVertexArrays(1, &_VAOname); + ccGLBindVAO(_VAOname); + + #define kQuadSize sizeof(_quads[0].bl) + + glGenBuffers(2, &_buffersVBO[0]); + + glBindBuffer(GL_ARRAY_BUFFER, _buffersVBO[0]); + glBufferData(GL_ARRAY_BUFFER, sizeof(_quads[0]) * _totalParticles, _quads, GL_DYNAMIC_DRAW); + + // vertices + glEnableVertexAttribArray(kCCVertexAttrib_Position); + glVertexAttribPointer(kCCVertexAttrib_Position, 2, GL_FLOAT, GL_FALSE, kQuadSize, (GLvoid*) offsetof( ccV3F_C4B_T2F, vertices)); + + // colors + glEnableVertexAttribArray(kCCVertexAttrib_Color); + glVertexAttribPointer(kCCVertexAttrib_Color, 4, GL_UNSIGNED_BYTE, GL_TRUE, kQuadSize, (GLvoid*) offsetof( ccV3F_C4B_T2F, colors)); + + // tex coords + glEnableVertexAttribArray(kCCVertexAttrib_TexCoords); + glVertexAttribPointer(kCCVertexAttrib_TexCoords, 2, GL_FLOAT, GL_FALSE, kQuadSize, (GLvoid*) offsetof( ccV3F_C4B_T2F, texCoords)); + + glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, _buffersVBO[1]); + glBufferData(GL_ELEMENT_ARRAY_BUFFER, sizeof(_indices[0]) * _totalParticles * 6, _indices, GL_STATIC_DRAW); + + // Must unbind the VAO before changing the element buffer. + ccGLBindVAO(0); + glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, 0); + glBindBuffer(GL_ARRAY_BUFFER, 0); + + CHECK_GL_ERROR_DEBUG(); + }; + + NSThread *cocos2dThread = [[CCDirector sharedDirector] runningThread]; + if( cocos2dThread == [NSThread currentThread] || [[CCConfiguration sharedConfiguration] supportsShareableVAO] ) + createVAO(); + else + [cocos2dThread performBlock:createVAO waitUntilDone:YES]; +} + +-(void) dealloc +{ + if( ! _batchNode ) { + free(_quads); + free(_indices); + + glDeleteBuffers(2, &_buffersVBO[0]); + glDeleteVertexArrays(1, &_VAOname); + } + + [super dealloc]; +} + +// pointRect is in Points coordinates. +-(void) initTexCoordsWithRect:(CGRect)pointRect +{ + // convert to Tex coords + + CGRect rect = CGRectMake( + pointRect.origin.x * CC_CONTENT_SCALE_FACTOR(), + pointRect.origin.y * CC_CONTENT_SCALE_FACTOR(), + pointRect.size.width * CC_CONTENT_SCALE_FACTOR(), + pointRect.size.height * CC_CONTENT_SCALE_FACTOR() ); + + GLfloat wide = [_texture pixelsWide]; + GLfloat high = [_texture pixelsHigh]; + +#if CC_FIX_ARTIFACTS_BY_STRECHING_TEXEL + GLfloat left = (rect.origin.x*2+1) / (wide*2); + GLfloat bottom = (rect.origin.y*2+1) / (high*2); + GLfloat right = left + (rect.size.width*2-2) / (wide*2); + GLfloat top = bottom + (rect.size.height*2-2) / (high*2); +#else + GLfloat left = rect.origin.x / wide; + GLfloat bottom = rect.origin.y / high; + GLfloat right = left + rect.size.width / wide; + GLfloat top = bottom + rect.size.height / high; +#endif // ! CC_FIX_ARTIFACTS_BY_STRECHING_TEXEL + + // Important. Texture in cocos2d are inverted, so the Y component should be inverted + CC_SWAP( top, bottom); + + ccV3F_C4B_T2F_Quad *quads; + NSUInteger start, end; + if (_batchNode) + { + quads = [[_batchNode textureAtlas] quads]; + start = _atlasIndex; + end = _atlasIndex + _totalParticles; + } + else + { + quads = _quads; + start = 0; + end = _totalParticles; + } + + for(NSUInteger i=start; iatlasIndex]); + } + else + quad = &(_quads[_particleIdx]); + + ccColor4B color = (_opacityModifyRGB) + ? (ccColor4B){ p->color.r*p->color.a*255, p->color.g*p->color.a*255, p->color.b*p->color.a*255, p->color.a*255} + : (ccColor4B){ p->color.r*255, p->color.g*255, p->color.b*255, p->color.a*255}; + + quad->bl.colors = color; + quad->br.colors = color; + quad->tl.colors = color; + quad->tr.colors = color; + + // vertices + GLfloat size_2 = p->size/2; + if( p->rotation ) { + GLfloat x1 = -size_2; + GLfloat y1 = -size_2; + + GLfloat x2 = size_2; + GLfloat y2 = size_2; + GLfloat x = newPos.x; + GLfloat y = newPos.y; + + GLfloat r = (GLfloat)-CC_DEGREES_TO_RADIANS(p->rotation); + GLfloat cr = cosf(r); + GLfloat sr = sinf(r); + GLfloat ax = x1 * cr - y1 * sr + x; + GLfloat ay = x1 * sr + y1 * cr + y; + GLfloat bx = x2 * cr - y1 * sr + x; + GLfloat by = x2 * sr + y1 * cr + y; + GLfloat cx = x2 * cr - y2 * sr + x; + GLfloat cy = x2 * sr + y2 * cr + y; + GLfloat dx = x1 * cr - y2 * sr + x; + GLfloat dy = x1 * sr + y2 * cr + y; + + // bottom-left + quad->bl.vertices.x = ax; + quad->bl.vertices.y = ay; + + // bottom-right vertex: + quad->br.vertices.x = bx; + quad->br.vertices.y = by; + + // top-left vertex: + quad->tl.vertices.x = dx; + quad->tl.vertices.y = dy; + + // top-right vertex: + quad->tr.vertices.x = cx; + quad->tr.vertices.y = cy; + } else { + // bottom-left vertex: + quad->bl.vertices.x = newPos.x - size_2; + quad->bl.vertices.y = newPos.y - size_2; + + // bottom-right vertex: + quad->br.vertices.x = newPos.x + size_2; + quad->br.vertices.y = newPos.y - size_2; + + // top-left vertex: + quad->tl.vertices.x = newPos.x - size_2; + quad->tl.vertices.y = newPos.y + size_2; + + // top-right vertex: + quad->tr.vertices.x = newPos.x + size_2; + quad->tr.vertices.y = newPos.y + size_2; + } +} + +-(void) postStep +{ + glBindBuffer(GL_ARRAY_BUFFER, _buffersVBO[0] ); + + // Option 1: Sub Data +#if __CC_PLATFORM_MAC + glBufferSubData(GL_ARRAY_BUFFER, 0, sizeof(_quads[0])*_particleCount, _quads); + + // Option 2: Data +// glBufferData(GL_ARRAY_BUFFER, sizeof(_quads[0]) * _particleCount, _quads, GL_STREAM_DRAW); + +#elif __CC_PLATFORM_IOS + // Option 3: Orphaning + glMapBuffer + glBufferData(GL_ARRAY_BUFFER, sizeof(_quads[0])*_totalParticles, nil, GL_STREAM_DRAW); + void *buf = glMapBuffer(GL_ARRAY_BUFFER, GL_WRITE_ONLY); + memcpy(buf, _quads, sizeof(_quads[0])*_particleCount); + glUnmapBuffer(GL_ARRAY_BUFFER); +#endif + + glBindBuffer(GL_ARRAY_BUFFER, 0); + + CHECK_GL_ERROR_DEBUG(); +} + +// overriding draw method +-(void) draw +{ + NSAssert(!_batchNode,@"draw should not be called when added to a particleBatchNode"); + + CC_NODE_DRAW_SETUP(); + + ccGLBindTexture2D( [_texture name] ); + ccGLBlendFunc( _blendFunc.src, _blendFunc.dst ); + + NSAssert( _particleIdx == _particleCount, @"Abnormal error in particle quad"); + + ccGLBindVAO( _VAOname ); + glDrawElements(GL_TRIANGLES, (GLsizei) _particleIdx*6, GL_UNSIGNED_SHORT, 0); + + CC_INCREMENT_GL_DRAWS(1); + + CHECK_GL_ERROR_DEBUG(); +} + +-(void) setBatchNode:(CCParticleBatchNode *)batchNode +{ + if( _batchNode != batchNode ) { + + CCParticleBatchNode *oldBatch = _batchNode; + + [super setBatchNode:batchNode]; + + // NEW: is self render ? + if( ! batchNode ) { + [self allocMemory]; + [self initIndices]; + [self setTexture:[oldBatch texture]]; + [self initVAO]; + } + + // OLD: was it self render ? cleanup + else if( ! oldBatch ) + { + // copy current state to batch + ccV3F_C4B_T2F_Quad *batchQuads = [[_batchNode textureAtlas] quads]; + ccV3F_C4B_T2F_Quad *quad = &(batchQuads[_atlasIndex] ); + memcpy( quad, _quads, _totalParticles * sizeof(_quads[0]) ); + + if (_quads) + free(_quads); + _quads = NULL; + + if (_indices) + free(_indices); + _indices = NULL; + + glDeleteBuffers(2, &_buffersVBO[0]); + glDeleteVertexArrays(1, &_VAOname); + } + } +} + +@end diff --git "a/21451198\345\215\242\350\266\205/project5/MyPlane/libs/cocos2d/CCPhysicsDebugNode.h" "b/21451198\345\215\242\350\266\205/project5/MyPlane/libs/cocos2d/CCPhysicsDebugNode.h" new file mode 100644 index 00000000..8f1af8b3 --- /dev/null +++ "b/21451198\345\215\242\350\266\205/project5/MyPlane/libs/cocos2d/CCPhysicsDebugNode.h" @@ -0,0 +1,58 @@ +/* Copyright (c) 2012 Scott Lembcke and Howling Moon Software + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + * SOFTWARE. + */ + +#import "ccConfig.h" + +#if CC_ENABLE_CHIPMUNK_INTEGRATION + +#import "chipmunk.h" + +#import "CCDrawNode.h" + +@class ChipmunkSpace; + +/** + A Node that draws the components of a physics engine. + + Supported physics engines: + - Chipmunk + - Objective-Chipmunk + + @since v2.1 + */ +@interface CCPhysicsDebugNode : CCDrawNode +{ + ChipmunkSpace *_spaceObj; + cpSpace *_spacePtr; +} + +// property for the cpSpace +@property (nonatomic, readwrite, assign) cpSpace *space; + +/** Create a debug node for an Objective-Chipmunk space. */ ++ (id) debugNodeForChipmunkSpace:(ChipmunkSpace *)space; + +/** Create a debug node for a regular Chipmunk space. */ ++ (id) debugNodeForCPSpace:(cpSpace *)space; + +@end + +#endif // CC_ENABLE_CHIPMUNK_INTEGRATION diff --git "a/21451198\345\215\242\350\266\205/project5/MyPlane/libs/cocos2d/CCPhysicsDebugNode.m" "b/21451198\345\215\242\350\266\205/project5/MyPlane/libs/cocos2d/CCPhysicsDebugNode.m" new file mode 100644 index 00000000..c2d91035 --- /dev/null +++ "b/21451198\345\215\242\350\266\205/project5/MyPlane/libs/cocos2d/CCPhysicsDebugNode.m" @@ -0,0 +1,185 @@ +/* Copyright (c) 2012 Scott Lembcke and Howling Moon Software + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + * SOFTWARE. + */ + + +#import "ccConfig.h" + +#if CC_ENABLE_CHIPMUNK_INTEGRATION + +#import "CCPhysicsDebugNode.h" + +#import "ccTypes.h" + +#include +#include +#include +#include +#include + + +/* + IMPORTANT - READ ME! + + This file sets pokes around in the private API a lot to provide efficient + debug rendering given nothing more than reference to a Chipmunk space. + It is not recommended to write rendering code like this in your own games + as the private API may change with little or no warning. +*/ + +static ccColor4F ColorForBody(cpBody *body) +{ + if(cpBodyIsRogue(body) || cpBodyIsSleeping(body)){ + return ccc4f(0.5, 0.5, 0.5 ,0.5); + } else if(body->CP_PRIVATE(node).idleTime > body->CP_PRIVATE(space)->sleepTimeThreshold) { + return ccc4f(0.33, 0.33, 0.33, 0.5); + } else { + return ccc4f(1, 0, 0, 0.5); + } +} + +static void +DrawShape(cpShape *shape, CCDrawNode *renderer) +{ + cpBody *body = shape->body; + ccColor4F color = ColorForBody(body); + + switch(shape->CP_PRIVATE(klass)->type){ + case CP_CIRCLE_SHAPE: { + cpCircleShape *circle = (cpCircleShape *)shape; + cpVect center = circle->tc; + cpFloat radius = circle->r; + [renderer drawDot:center radius:cpfmax(radius, 1.0) color:color]; + [renderer drawSegmentFrom:center to:cpvadd(center, cpvmult(body->rot, radius)) radius:1.0 color:color]; + } break; + case CP_SEGMENT_SHAPE: { + cpSegmentShape *seg = (cpSegmentShape *)shape; + [renderer drawSegmentFrom:seg->ta to:seg->tb radius:cpfmax(seg->r, 2.0) color:color]; + } break; + case CP_POLY_SHAPE: { + cpPolyShape *poly = (cpPolyShape *)shape; + ccColor4F line = color; + line.a = cpflerp(color.a, 1.0, 0.5); + + [renderer drawPolyWithVerts:poly->tVerts count:poly->numVerts fillColor:color borderWidth:1.0 borderColor:line]; + }break; + default: + cpAssertHard(FALSE, "Bad assertion in DrawShape()"); + } +} + +ccColor4F CONSTRAINT_COLOR = {0, 1, 0, 0.5}; + +static void +DrawConstraint(cpConstraint *constraint, CCDrawNode *renderer) +{ + cpBody *body_a = constraint->a; + cpBody *body_b = constraint->b; + + const cpConstraintClass *klass = constraint->CP_PRIVATE(klass); + if(klass == cpPinJointGetClass()){ + cpPinJoint *joint = (cpPinJoint *)constraint; + + cpVect a = cpBodyLocal2World(body_a, joint->anchr1); + cpVect b = cpBodyLocal2World(body_b, joint->anchr2); + + [renderer drawDot:a radius:3.0 color:CONSTRAINT_COLOR]; + [renderer drawDot:b radius:3.0 color:CONSTRAINT_COLOR]; + [renderer drawSegmentFrom:a to:b radius:1.0 color:CONSTRAINT_COLOR]; + } else if(klass == cpSlideJointGetClass()){ + cpSlideJoint *joint = (cpSlideJoint *)constraint; + + cpVect a = cpBodyLocal2World(body_a, joint->anchr1); + cpVect b = cpBodyLocal2World(body_b, joint->anchr2); + + [renderer drawDot:a radius:3.0 color:CONSTRAINT_COLOR]; + [renderer drawDot:b radius:3.0 color:CONSTRAINT_COLOR]; + [renderer drawSegmentFrom:a to:b radius:1.0 color:CONSTRAINT_COLOR]; + } else if(klass == cpPivotJointGetClass()){ + cpPivotJoint *joint = (cpPivotJoint *)constraint; + + cpVect a = cpBodyLocal2World(body_a, joint->anchr1); + cpVect b = cpBodyLocal2World(body_b, joint->anchr2); + + [renderer drawDot:a radius:3.0 color:CONSTRAINT_COLOR]; + [renderer drawDot:b radius:3.0 color:CONSTRAINT_COLOR]; + } else if(klass == cpGrooveJointGetClass()){ + cpGrooveJoint *joint = (cpGrooveJoint *)constraint; + + cpVect a = cpBodyLocal2World(body_a, joint->grv_a); + cpVect b = cpBodyLocal2World(body_a, joint->grv_b); + cpVect c = cpBodyLocal2World(body_b, joint->anchr2); + + [renderer drawDot:c radius:3.0 color:CONSTRAINT_COLOR]; + [renderer drawSegmentFrom:a to:b radius:1.0 color:CONSTRAINT_COLOR]; + } else if(klass == cpDampedSpringGetClass()){ + // TODO + } else { +// printf("Cannot draw constraint\n"); + } +} + + +@interface ChipmunkSpace : NSObject +-(cpSpace *)space; +@end + + +@implementation CCPhysicsDebugNode + +@synthesize space = _spacePtr; +-(void) draw; +{ + if( ! _spacePtr ) + return; + + cpSpaceEachShape(_spacePtr, (cpSpaceShapeIteratorFunc)DrawShape, self); + cpSpaceEachConstraint(_spacePtr, (cpSpaceConstraintIteratorFunc)DrawConstraint, self); + + [super draw]; + [super clear]; +} + ++ debugNodeForChipmunkSpace:(ChipmunkSpace *)space; +{ + CCPhysicsDebugNode *node = [[CCPhysicsDebugNode alloc] init]; + node->_spaceObj = [space retain]; + node->_spacePtr = space.space; + + return [node autorelease]; +} + ++ debugNodeForCPSpace:(cpSpace *)space; +{ + CCPhysicsDebugNode *node = [[CCPhysicsDebugNode alloc] init]; + node->_spacePtr = space; + + return [node autorelease]; +} + +- (void) dealloc +{ + [_spaceObj release]; + [super dealloc]; +} + +@end + +#endif // CC_ENABLE_CHIPMUNK_INTEGRATION diff --git "a/21451198\345\215\242\350\266\205/project5/MyPlane/libs/cocos2d/CCPhysicsSprite.h" "b/21451198\345\215\242\350\266\205/project5/MyPlane/libs/cocos2d/CCPhysicsSprite.h" new file mode 100644 index 00000000..915c924a --- /dev/null +++ "b/21451198\345\215\242\350\266\205/project5/MyPlane/libs/cocos2d/CCPhysicsSprite.h" @@ -0,0 +1,82 @@ +/* Copyright (c) 2012 Scott Lembcke and Howling Moon Software + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + * SOFTWARE. + */ + +#import "ccConfig.h" +#import "CCSprite.h" + + +#if CC_ENABLE_CHIPMUNK_INTEGRATION +#import "chipmunk.h" +@class ChipmunkBody; + +#elif CC_ENABLE_BOX2D_INTEGRATION +class b2Body; +#endif // CC_ENABLE_BOX2D_INTEGRATION + +/** A CCSprite subclass that is bound to a physics body. + It works with: + - Chipmunk: Preprocessor macro CC_ENABLE_CHIPMUNK_INTEGRATION should be defined + - Objective-Chipmunk: Preprocessor macro CC_ENABLE_CHIPMUNK_INTEGRATION should be defined + - Box2d: Preprocessor macro CC_ENABLE_BOX2D_INTEGRATION should be defined + + Features and Limitations: + - Scale and Skew properties are ignored. + - Position and rotation are going to updated from the physics body + - If you update the rotation or position manually, the physics body will be updated + - You can't eble both Chipmunk support and Box2d support at the same time. Only one can be enabled at compile time + */ +@interface CCPhysicsSprite : CCSprite +{ + BOOL _ignoreBodyRotation; + +#if CC_ENABLE_CHIPMUNK_INTEGRATION + cpBody *_cpBody; + +#elif CC_ENABLE_BOX2D_INTEGRATION + b2Body *_b2Body; + + // Pixels to Meters ratio + float _PTMRatio; +#endif // CC_ENABLE_BOX2D_INTEGRATION +} + +/** Keep the sprite's rotation separate from the body. */ +@property(nonatomic, assign) BOOL ignoreBodyRotation; + +#if CC_ENABLE_CHIPMUNK_INTEGRATION + +/** Body accessor when using regular Chipmunk */ +@property(nonatomic, assign) cpBody *CPBody; + +/** Body accessor when using Objective-Chipmunk */ +@property(nonatomic, assign) ChipmunkBody *chipmunkBody; + + +#elif CC_ENABLE_BOX2D_INTEGRATION + +/** Body accessor when using box2d */ +@property(nonatomic, assign) b2Body *b2Body; + +@property(nonatomic, assign) float PTMRatio; + +#endif // CC_ENABLE_BOX2D_INTEGRATION + +@end diff --git "a/21451198\345\215\242\350\266\205/project5/MyPlane/libs/cocos2d/CCPhysicsSprite.mm" "b/21451198\345\215\242\350\266\205/project5/MyPlane/libs/cocos2d/CCPhysicsSprite.mm" new file mode 100644 index 00000000..d514cf50 --- /dev/null +++ "b/21451198\345\215\242\350\266\205/project5/MyPlane/libs/cocos2d/CCPhysicsSprite.mm" @@ -0,0 +1,187 @@ +/* Copyright (c) 2012 Scott Lembcke and Howling Moon Software + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + * SOFTWARE. + */ + +#import "CCPhysicsSprite.h" +#import "Support/CGPointExtension.h" + +#if CC_ENABLE_CHIPMUNK_INTEGRATION +#import "chipmunk.h" +#elif CC_ENABLE_BOX2D_INTEGRATION +#import "Box2D.h" +#endif + +#if CC_ENABLE_CHIPMUNK_INTEGRATION +@interface ChipmunkBody : NSObject +-(cpBody *)body; +@end +#endif // CC_ENABLE_CHIPMUNK_INTEGRATION + +@implementation CCPhysicsSprite + +@synthesize ignoreBodyRotation = _ignoreBodyRotation; + +#if CC_ENABLE_CHIPMUNK_INTEGRATION +@synthesize CPBody = _cpBody; +#endif +#if CC_ENABLE_BOX2D_INTEGRATION +@synthesize b2Body = _b2Body; +@synthesize PTMRatio = _PTMRatio; +#endif + +#pragma mark - Chipmunk support + +#if CC_ENABLE_CHIPMUNK_INTEGRATION +-(ChipmunkBody *)chipmunkBody +{ + return (ChipmunkBody *) _cpBody->data; +} + +-(void)setChipmunkBody:(ChipmunkBody *)chipmunkBody +{ + _cpBody = chipmunkBody.body; +} +// Override the setters and getters to always reflect the body's properties. +-(CGPoint)position +{ + return cpBodyGetPos(_cpBody); +} + +-(void)setPosition:(CGPoint)position +{ + cpBodySetPos(_cpBody, position); +} + +-(float)rotation +{ + return (_ignoreBodyRotation ? super.rotation : -CC_RADIANS_TO_DEGREES(cpBodyGetAngle(_cpBody))); +} + +-(void)setRotation:(float)rotation +{ + if(_ignoreBodyRotation){ + super.rotation = rotation; + } else { + cpBodySetAngle(_cpBody, -CC_DEGREES_TO_RADIANS(rotation)); + } +} + +// returns the transform matrix according the Chipmunk Body values +-(CGAffineTransform) nodeToParentTransform +{ + // Although scale is not used by physics engines, it is calculated just in case + // the sprite is animated (scaled up/down) using actions. + // For more info see: http://www.cocos2d-iphone.org/forum/topic/68990 + cpVect rot = (_ignoreBodyRotation ? cpvforangle(-CC_DEGREES_TO_RADIANS(_rotationX)) : _cpBody->rot); + CGFloat x = _cpBody->p.x + rot.x * -_anchorPointInPoints.x * _scaleX - rot.y * -_anchorPointInPoints.y * _scaleY; + CGFloat y = _cpBody->p.y + rot.y * -_anchorPointInPoints.x * _scaleX + rot.x * -_anchorPointInPoints.y * _scaleY; + + if(_ignoreAnchorPointForPosition){ + x += _anchorPointInPoints.x; + y += _anchorPointInPoints.y; + } + + return (_transform = CGAffineTransformMake(rot.x * _scaleX, rot.y * _scaleX, + -rot.y * _scaleY, rot.x * _scaleY, + x, y)); +} + +#elif CC_ENABLE_BOX2D_INTEGRATION + +#pragma mark - Box2d support + +// Override the setters and getters to always reflect the body's properties. +-(CGPoint)position +{ + b2Vec2 pos = _b2Body->GetPosition(); + + float x = pos.x * _PTMRatio; + float y = pos.y * _PTMRatio; + return ccp(x,y); +} + +-(void)setPosition:(CGPoint)position +{ + float angle = _b2Body->GetAngle(); + _b2Body->SetTransform( b2Vec2(position.x / _PTMRatio, position.y / _PTMRatio), angle ); +} + +-(float)rotation +{ + return (_ignoreBodyRotation ? super.rotation : + CC_RADIANS_TO_DEGREES( _b2Body->GetAngle() ) ); +} + +-(void)setRotation:(float)rotation +{ + if(_ignoreBodyRotation){ + super.rotation = rotation; + } else { + b2Vec2 p = _b2Body->GetPosition(); + float radians = CC_DEGREES_TO_RADIANS(rotation); + _b2Body->SetTransform( p, radians); + } +} + +// returns the transform matrix according the Chipmunk Body values +-(CGAffineTransform) nodeToParentTransform +{ + b2Vec2 pos = _b2Body->GetPosition(); + + float x = pos.x * _PTMRatio; + float y = pos.y * _PTMRatio; + + if ( _ignoreAnchorPointForPosition ) { + x += _anchorPointInPoints.x; + y += _anchorPointInPoints.y; + } + + // Make matrix + float radians = _b2Body->GetAngle(); + float c = cosf(radians); + float s = sinf(radians); + + // Although scale is not used by physics engines, it is calculated just in case + // the sprite is animated (scaled up/down) using actions. + // For more info see: http://www.cocos2d-iphone.org/forum/topic/68990 + if( ! CGPointEqualToPoint(_anchorPointInPoints, CGPointZero) ){ + x += c*-_anchorPointInPoints.x * _scaleX + -s*-_anchorPointInPoints.y * _scaleY; + y += s*-_anchorPointInPoints.x * _scaleX + c*-_anchorPointInPoints.y * _scaleY; + } + + // Rot, Translate Matrix + _transform = CGAffineTransformMake( c * _scaleX, s * _scaleX, + -s * _scaleY, c * _scaleY, + x, y ); + + return _transform; +} +#endif // CC_ENABLE_BOX2D_INTEGRATION + +// this method will only get called if the sprite is batched. +// return YES if the physic's values (angles, position ) changed. +// If you return NO, then nodeToParentTransform won't be called. +-(BOOL) dirty +{ + return YES; +} + + +@end diff --git "a/21451198\345\215\242\350\266\205/project5/MyPlane/libs/cocos2d/CCProgressTimer.h" "b/21451198\345\215\242\350\266\205/project5/MyPlane/libs/cocos2d/CCProgressTimer.h" new file mode 100644 index 00000000..092a85aa --- /dev/null +++ "b/21451198\345\215\242\350\266\205/project5/MyPlane/libs/cocos2d/CCProgressTimer.h" @@ -0,0 +1,92 @@ +/* + * cocos2d for iPhone: http://www.cocos2d-iphone.org + * + * Copyright (c) 2010 Lam Pham + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + * THE SOFTWARE. + * + */ + +#import +#import "CCSprite.h" + +/** Types of progress + @since v0.99.1 + */ +typedef enum { + /// Radial Counter-Clockwise + kCCProgressTimerTypeRadial, + /// Bar + kCCProgressTimerTypeBar, +} CCProgressTimerType; + +/** + CCProgresstimer is a subclass of CCNode. + It renders the inner sprite according to the percentage. + The progress can be Radial, Horizontal or vertical. + @since v0.99.1 + */ +@interface CCProgressTimer : CCNodeRGBA { + CCProgressTimerType _type; + float _percentage; + CCSprite *_sprite; + + int _vertexDataCount; + ccV2F_C4B_T2F *_vertexData; + CGPoint _midpoint; + CGPoint _barChangeRate; + BOOL _reverseDirection; +} +/** Change the percentage to change progress. */ +@property (nonatomic, readwrite) CCProgressTimerType type; +@property (nonatomic, readwrite) BOOL reverseDirection; +@property (nonatomic, readonly) ccV2F_C4B_T2F *vertexData; +@property (nonatomic, readonly) int vertexDataCount; + +/** + * Midpoint is used to modify the progress start position. + * If you're using radials type then the midpoint changes the center point + * If you're using bar type the the midpoint changes the bar growth + * it expands from the center but clamps to the sprites edge so: + * you want a left to right then set the midpoint all the way to ccp(0,y) + * you want a right to left then set the midpoint all the way to ccp(1,y) + * you want a bottom to top then set the midpoint all the way to ccp(x,0) + * you want a top to bottom then set the midpoint all the way to ccp(x,1) + */ +@property (nonatomic, readwrite) CGPoint midpoint; + +/** + * This allows the bar type to move the component at a specific rate + * Set the component to 0 to make sure it stays at 100%. + * For example you want a left to right bar but not have the height stay 100% + * Set the rate to be ccp(0,1); and set the midpoint to = ccp(0,.5f); + */ +@property (nonatomic, readwrite) CGPoint barChangeRate; + +/** Percentages are from 0 to 100 */ +@property (nonatomic, readwrite) float percentage; + +/** The image to show the progress percentage */ +@property (nonatomic, readwrite, retain) CCSprite *sprite; + +/** Creates a progress timer with the sprite as the shape the timer goes through */ ++ (id) progressWithSprite:(CCSprite*) sprite; +/** Initializes a progress timer with the sprite as the shape the timer goes through */ +- (id) initWithSprite:(CCSprite*) sprite; +@end diff --git "a/21451198\345\215\242\350\266\205/project5/MyPlane/libs/cocos2d/CCProgressTimer.m" "b/21451198\345\215\242\350\266\205/project5/MyPlane/libs/cocos2d/CCProgressTimer.m" new file mode 100644 index 00000000..b650c133 --- /dev/null +++ "b/21451198\345\215\242\350\266\205/project5/MyPlane/libs/cocos2d/CCProgressTimer.m" @@ -0,0 +1,541 @@ +/* + * cocos2d for iPhone: http://www.cocos2d-iphone.org + * + * Copyright (c) 2010 Lam Pham + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + * THE SOFTWARE. + * + */ + +#import "CCProgressTimer.h" + +#import "ccMacros.h" +#import "CCTextureCache.h" +#import "CCGLProgram.h" +#import "CCShaderCache.h" +#import "ccGLStateCache.h" +#import "CCDirector.h" +#import "Support/CGPointExtension.h" +#import "Support/TransformUtils.h" +#import "CCDrawingPrimitives.h" + +// extern +#import "kazmath/GL/matrix.h" + +#define kProgressTextureCoordsCount 4 +// kProgressTextureCoords holds points {0,1} {0,0} {1,0} {1,1} we can represent it as bits +const char kCCProgressTextureCoords = 0x4b; + +@interface CCProgressTimer () + +-(void)updateProgress; +-(void)updateBar; +-(void)updateRadial; +-(void)updateColor; +-(CGPoint)boundaryTexCoord:(char)index; +@end + + +@implementation CCProgressTimer +@synthesize percentage = _percentage; +@synthesize sprite = _sprite; +@synthesize type = _type; +@synthesize reverseDirection = _reverseDirection; +@synthesize midpoint = _midpoint; +@synthesize barChangeRate = _barChangeRate; +@synthesize vertexData = _vertexData; +@synthesize vertexDataCount = _vertexDataCount; + ++(id)progressWithSprite:(CCSprite*) sprite +{ + return [[[self alloc]initWithSprite:sprite] autorelease]; +} + +-(id) init +{ + return [self initWithSprite:nil]; +} + +// designated initializer +-(id)initWithSprite:(CCSprite*) sprite +{ + if(( self = [super init] )){ + _percentage = 0.f; + _vertexData = NULL; + _vertexDataCount = 0; + self.anchorPoint = ccp(0.5f,0.5f); + self.type = kCCProgressTimerTypeRadial; + self.reverseDirection = NO; + self.midpoint = ccp(.5f, .5f); + self.barChangeRate = ccp(1,1); + self.sprite = sprite; + + // shader program + self.shaderProgram = [[CCShaderCache sharedShaderCache] programForKey:kCCShader_PositionTextureColor]; + } + return self; +} + +-(void)dealloc +{ + if(_vertexData){ + free(_vertexData); + } + [_sprite release]; + [super dealloc]; +} + +-(void)setPercentage:(float) percentage +{ + if(_percentage != percentage) { + _percentage = clampf( percentage, 0, 100); + [self updateProgress]; + } +} + +-(void)setSprite:(CCSprite *)newSprite +{ + if(_sprite != newSprite){ + [_sprite release]; + _sprite = [newSprite retain]; + self.contentSize = _sprite.contentSize; + + // Everytime we set a new sprite, we free the current vertex data + if(_vertexData){ + free(_vertexData); + _vertexData = NULL; + _vertexDataCount = 0; + } + } +} + +-(void)setType:(CCProgressTimerType)newType +{ + if (newType != _type) { + + // release all previous information + if(_vertexData){ + free(_vertexData); + _vertexData = NULL; + _vertexDataCount = 0; + } + _type = newType; + [self updateProgress]; + } +} + +-(void)setReverseDirection:(BOOL)reverse +{ + if( _reverseDirection != reverse ) { + _reverseDirection = reverse; + + // release all previous information + if(_vertexData){ + free(_vertexData); + _vertexData = NULL; + _vertexDataCount = 0; + } + } +} + +-(void)setColor:(ccColor3B)c +{ + _sprite.color = c; + [self updateColor]; +} + +-(ccColor3B)color +{ + return _sprite.color; +} + +-(void)setOpacity:(GLubyte)o +{ + _sprite.opacity = o; + [self updateColor]; +} + +-(GLubyte)opacity +{ + return _sprite.opacity; +} + +#pragma mark ProgressTimer Internal + +/// +// @returns the vertex position from the texture coordinate +/// +-(ccTex2F)textureCoordFromAlphaPoint:(CGPoint) alpha +{ + if (!_sprite) { + return (ccTex2F){0,0}; + } + ccV3F_C4B_T2F_Quad quad = _sprite.quad; + CGPoint min = (CGPoint){quad.bl.texCoords.u,quad.bl.texCoords.v}; + CGPoint max = (CGPoint){quad.tr.texCoords.u,quad.tr.texCoords.v}; + // Fix bug #1303 so that progress timer handles sprite frame texture rotation + if (_sprite.textureRectRotated) { + CC_SWAP(alpha.x, alpha.y); + } + return (ccTex2F){min.x * (1.f - alpha.x) + max.x * alpha.x, min.y * (1.f - alpha.y) + max.y * alpha.y}; +} + +-(ccVertex2F)vertexFromAlphaPoint:(CGPoint) alpha +{ + if (!_sprite) { + return (ccVertex2F){0.f, 0.f}; + } + ccV3F_C4B_T2F_Quad quad = _sprite.quad; + CGPoint min = (CGPoint){quad.bl.vertices.x,quad.bl.vertices.y}; + CGPoint max = (CGPoint){quad.tr.vertices.x,quad.tr.vertices.y}; + return (ccVertex2F){min.x * (1.f - alpha.x) + max.x * alpha.x, min.y * (1.f - alpha.y) + max.y * alpha.y}; +} + +-(void)updateColor +{ + if (!_sprite) { + return; + } + if(_vertexData){ + ccColor4B sc = _sprite.quad.tl.colors; + for (int i=0; i < _vertexDataCount; ++i) { + _vertexData[i].colors = sc; + } + } +} + +-(void)updateProgress +{ + switch (_type) { + case kCCProgressTimerTypeRadial: + [self updateRadial]; + break; + case kCCProgressTimerTypeBar: + [self updateBar]; + break; + default: + break; + } +} + +-(void)setAnchorPoint:(CGPoint)anchorPoint +{ + [super setAnchorPoint:anchorPoint]; +} + +-(CGPoint) midpoint +{ + return _midpoint; +} + +-(void)setMidpoint:(CGPoint)midPoint +{ + _midpoint = ccpClamp(midPoint, CGPointZero, ccp(1,1)); +} + +/// +// Update does the work of mapping the texture onto the triangles +// It now doesn't occur the cost of free/alloc data every update cycle. +// It also only changes the percentage point but no other points if they have not +// been modified. +// +// It now deals with flipped texture. If you run into this problem, just use the +// sprite property and enable the methods flipX, flipY. +/// +-(void)updateRadial +{ + if (!_sprite) { + return; + } + + float alpha = _percentage / 100.f; + + float angle = 2.f*((float)M_PI) * ( _reverseDirection == YES ? alpha : 1.f - alpha); + + // We find the vector to do a hit detection based on the percentage + // We know the first vector is the one @ 12 o'clock (top,mid) so we rotate + // from that by the progress angle around the _midpoint pivot + CGPoint topMid = ccp(_midpoint.x, 1.f); + CGPoint percentagePt = ccpRotateByAngle(topMid, _midpoint, angle); + + + int index = 0; + CGPoint hit = CGPointZero; + + if (alpha == 0.f) { + // More efficient since we don't always need to check intersection + // If the alpha is zero then the hit point is top mid and the index is 0. + hit = topMid; + index = 0; + } else if (alpha == 1.f) { + // More efficient since we don't always need to check intersection + // If the alpha is one then the hit point is top mid and the index is 4. + hit = topMid; + index = 4; + } else { + // We run a for loop checking the edges of the texture to find the + // intersection point + // We loop through five points since the top is split in half + + float min_t = FLT_MAX; + + for (int i = 0; i <= kProgressTextureCoordsCount; ++i) { + int pIndex = (i + (kProgressTextureCoordsCount - 1))%kProgressTextureCoordsCount; + + CGPoint edgePtA = [self boundaryTexCoord:i % kProgressTextureCoordsCount]; + CGPoint edgePtB = [self boundaryTexCoord:pIndex]; + + // Remember that the top edge is split in half for the 12 o'clock position + // Let's deal with that here by finding the correct endpoints + if(i == 0){ + edgePtB = ccpLerp(edgePtA, edgePtB, 1 - _midpoint.x); + } else if(i == 4){ + edgePtA = ccpLerp(edgePtA, edgePtB, 1 - _midpoint.x); + } + + // s and t are returned by ccpLineIntersect + float s = 0, t = 0; + if(ccpLineIntersect(edgePtA, edgePtB, _midpoint, percentagePt, &s, &t)) + { + + // Since our hit test is on rays we have to deal with the top edge + // being in split in half so we have to test as a segment + if ((i == 0 || i == 4)) { + // s represents the point between edgePtA--edgePtB + if (!(0.f <= s && s <= 1.f)) { + continue; + } + } + // As long as our t isn't negative we are at least finding a + // correct hitpoint from _midpoint to percentagePt. + if (t >= 0.f) { + // Because the percentage line and all the texture edges are + // rays we should only account for the shortest intersection + if (t < min_t) { + min_t = t; + index = i; + } + } + } + } + + // Now that we have the minimum magnitude we can use that to find our intersection + hit = ccpAdd(_midpoint, ccpMult(ccpSub(percentagePt, _midpoint),min_t)); + + } + + + // The size of the vertex data is the index from the hitpoint + // the 3 is for the _midpoint, 12 o'clock point and hitpoint position. + + BOOL sameIndexCount = YES; + if(_vertexDataCount != index + 3){ + sameIndexCount = NO; + if(_vertexData){ + free(_vertexData); + _vertexData = NULL; + _vertexDataCount = 0; + } + } + + + if(!_vertexData) { + _vertexDataCount = index + 3; + _vertexData = malloc(_vertexDataCount * sizeof(ccV2F_C4B_T2F)); + NSAssert( _vertexData, @"CCProgressTimer. Not enough memory"); + } + [self updateColor]; + + if (!sameIndexCount) { + + // First we populate the array with the _midpoint, then all + // vertices/texcoords/colors of the 12 'o clock start and edges and the hitpoint + _vertexData[0].texCoords = [self textureCoordFromAlphaPoint:_midpoint]; + _vertexData[0].vertices = [self vertexFromAlphaPoint:_midpoint]; + + _vertexData[1].texCoords = [self textureCoordFromAlphaPoint:topMid]; + _vertexData[1].vertices = [self vertexFromAlphaPoint:topMid]; + + for(int i = 0; i < index; ++i){ + CGPoint alphaPoint = [self boundaryTexCoord:i]; + _vertexData[i+2].texCoords = [self textureCoordFromAlphaPoint:alphaPoint]; + _vertexData[i+2].vertices = [self vertexFromAlphaPoint:alphaPoint]; + } + } + + // hitpoint will go last + _vertexData[_vertexDataCount - 1].texCoords = [self textureCoordFromAlphaPoint:hit]; + _vertexData[_vertexDataCount - 1].vertices = [self vertexFromAlphaPoint:hit]; +} + +/// +// Update does the work of mapping the texture onto the triangles for the bar +// It now doesn't occur the cost of free/alloc data every update cycle. +// It also only changes the percentage point but no other points if they have not +// been modified. +// +// It now deals with flipped texture. If you run into this problem, just use the +// sprite property and enable the methods flipX, flipY. +/// +-(void)updateBar +{ + if (!_sprite) { + return; + } + float alpha = _percentage / 100.f; + CGPoint alphaOffset = ccpMult(ccp(1.f * (1.f - _barChangeRate.x) + alpha * _barChangeRate.x, 1.f * (1.f - _barChangeRate.y) + alpha * _barChangeRate.y), .5f); + CGPoint min = ccpSub(_midpoint, alphaOffset); + CGPoint max = ccpAdd(_midpoint, alphaOffset); + + if (min.x < 0.f) { + max.x += -min.x; + min.x = 0.f; + } + + if (max.x > 1.f) { + min.x -= max.x - 1.f; + max.x = 1.f; + } + + if (min.y < 0.f) { + max.y += -min.y; + min.y = 0.f; + } + + if (max.y > 1.f) { + min.y -= max.y - 1.f; + max.y = 1.f; + } + + + if (!_reverseDirection) { + if(!_vertexData) { + _vertexDataCount = 4; + _vertexData = malloc(_vertexDataCount * sizeof(ccV2F_C4B_T2F)); + NSAssert( _vertexData, @"CCProgressTimer. Not enough memory"); + } + // TOPLEFT + _vertexData[0].texCoords = [self textureCoordFromAlphaPoint:ccp(min.x,max.y)]; + _vertexData[0].vertices = [self vertexFromAlphaPoint:ccp(min.x,max.y)]; + + // BOTLEFT + _vertexData[1].texCoords = [self textureCoordFromAlphaPoint:ccp(min.x,min.y)]; + _vertexData[1].vertices = [self vertexFromAlphaPoint:ccp(min.x,min.y)]; + + // TOPRIGHT + _vertexData[2].texCoords = [self textureCoordFromAlphaPoint:ccp(max.x,max.y)]; + _vertexData[2].vertices = [self vertexFromAlphaPoint:ccp(max.x,max.y)]; + + // BOTRIGHT + _vertexData[3].texCoords = [self textureCoordFromAlphaPoint:ccp(max.x,min.y)]; + _vertexData[3].vertices = [self vertexFromAlphaPoint:ccp(max.x,min.y)]; + } else { + if(!_vertexData) { + _vertexDataCount = 8; + _vertexData = malloc(_vertexDataCount * sizeof(ccV2F_C4B_T2F)); + NSAssert( _vertexData, @"CCProgressTimer. Not enough memory"); + // TOPLEFT 1 + _vertexData[0].texCoords = [self textureCoordFromAlphaPoint:ccp(0,1)]; + _vertexData[0].vertices = [self vertexFromAlphaPoint:ccp(0,1)]; + + // BOTLEFT 1 + _vertexData[1].texCoords = [self textureCoordFromAlphaPoint:ccp(0,0)]; + _vertexData[1].vertices = [self vertexFromAlphaPoint:ccp(0,0)]; + + // TOPRIGHT 2 + _vertexData[6].texCoords = [self textureCoordFromAlphaPoint:ccp(1,1)]; + _vertexData[6].vertices = [self vertexFromAlphaPoint:ccp(1,1)]; + + // BOTRIGHT 2 + _vertexData[7].texCoords = [self textureCoordFromAlphaPoint:ccp(1,0)]; + _vertexData[7].vertices = [self vertexFromAlphaPoint:ccp(1,0)]; + } + + // TOPRIGHT 1 + _vertexData[2].texCoords = [self textureCoordFromAlphaPoint:ccp(min.x,max.y)]; + _vertexData[2].vertices = [self vertexFromAlphaPoint:ccp(min.x,max.y)]; + + // BOTRIGHT 1 + _vertexData[3].texCoords = [self textureCoordFromAlphaPoint:ccp(min.x,min.y)]; + _vertexData[3].vertices = [self vertexFromAlphaPoint:ccp(min.x,min.y)]; + + // TOPLEFT 2 + _vertexData[4].texCoords = [self textureCoordFromAlphaPoint:ccp(max.x,max.y)]; + _vertexData[4].vertices = [self vertexFromAlphaPoint:ccp(max.x,max.y)]; + + // BOTLEFT 2 + _vertexData[5].texCoords = [self textureCoordFromAlphaPoint:ccp(max.x,min.y)]; + _vertexData[5].vertices = [self vertexFromAlphaPoint:ccp(max.x,min.y)]; + } + [self updateColor]; +} + +-(CGPoint)boundaryTexCoord:(char)index +{ + if (index < kProgressTextureCoordsCount) { + if (_reverseDirection) { + return ccp((kCCProgressTextureCoords>>(7-(index<<1)))&1,(kCCProgressTextureCoords>>(7-((index<<1)+1)))&1); + } else { + return ccp((kCCProgressTextureCoords>>((index<<1)+1))&1,(kCCProgressTextureCoords>>(index<<1))&1); + } + } + return CGPointZero; +} + +-(void) draw +{ + if( ! _vertexData || ! _sprite) + return; + + CC_NODE_DRAW_SETUP(); + + ccGLBlendFunc( _sprite.blendFunc.src, _sprite.blendFunc.dst ); + + ccGLEnableVertexAttribs(kCCVertexAttribFlag_PosColorTex ); + + ccGLBindTexture2D( _sprite.texture.name ); + + glVertexAttribPointer( kCCVertexAttrib_Position, 2, GL_FLOAT, GL_FALSE, sizeof(_vertexData[0]) , &_vertexData[0].vertices); + glVertexAttribPointer( kCCVertexAttrib_TexCoords, 2, GL_FLOAT, GL_FALSE, sizeof(_vertexData[0]), &_vertexData[0].texCoords); + glVertexAttribPointer( kCCVertexAttrib_Color, 4, GL_UNSIGNED_BYTE, GL_TRUE, sizeof(_vertexData[0]), &_vertexData[0].colors); + + if(_type == kCCProgressTimerTypeRadial) + { + glDrawArrays(GL_TRIANGLE_FAN, 0, _vertexDataCount); + } + else if (_type == kCCProgressTimerTypeBar) + { + if (!_reverseDirection) + { + glDrawArrays(GL_TRIANGLE_STRIP, 0, _vertexDataCount); + } + else + { + glDrawArrays(GL_TRIANGLE_STRIP, 0, _vertexDataCount/2); + glDrawArrays(GL_TRIANGLE_STRIP, 4, _vertexDataCount/2); + + // 2 draw calls + CC_INCREMENT_GL_DRAWS(1); + } + } + CC_INCREMENT_GL_DRAWS(1); + +} + +@end diff --git "a/21451198\345\215\242\350\266\205/project5/MyPlane/libs/cocos2d/CCProtocols.h" "b/21451198\345\215\242\350\266\205/project5/MyPlane/libs/cocos2d/CCProtocols.h" new file mode 100644 index 00000000..62d06191 --- /dev/null +++ "b/21451198\345\215\242\350\266\205/project5/MyPlane/libs/cocos2d/CCProtocols.h" @@ -0,0 +1,160 @@ +/* + * cocos2d for iPhone: http://www.cocos2d-iphone.org + * + * Copyright (c) 2008-2010 Ricardo Quesada + * Copyright (c) 2011 Zynga Inc. + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + * THE SOFTWARE. + */ + +#import "ccMacros.h" +#import "ccTypes.h" + + +@class CCTexture2D; +@class CCDirector; + +#pragma mark - CCRGBAProtocol + +/// CC RGBA protocol +@protocol CCRGBAProtocol +/** sets and returns the color (tint) + @since v0.8 + */ +@property (nonatomic) ccColor3B color; +/** returns the displayed color */ +@property (nonatomic, readonly) ccColor3B displayedColor; +/** whether or not color should be propagated to its children */ +@property (nonatomic, getter = isCascadeColorEnabled) BOOL cascadeColorEnabled; + +/** recursive method that updates display color */ +- (void)updateDisplayedColor:(ccColor3B)color; + +/** sets and returns the opacity. + @warning If the the texture has premultiplied alpha then, the R, G and B channels will be modified. + Values goes from 0 to 255, where 255 means fully opaque. + */ +@property (nonatomic) GLubyte opacity; +/** returns the displayed opacity */ +@property (nonatomic, readonly) GLubyte displayedOpacity; +/** whether or not opacity should be propagated to its children */ +@property (nonatomic, getter = isCascadeOpacityEnabled) BOOL cascadeOpacityEnabled; + +/** recursive method that updates the displayed opacity */ +- (void)updateDisplayedOpacity:(GLubyte)opacity; + +@optional +/** sets the premultipliedAlphaOpacity property. + If set to NO then opacity will be applied as: glColor(R,G,B,opacity); + If set to YES then opacity will be applied as: glColor(opacity, opacity, opacity, opacity ); + Textures with premultiplied alpha will have this property by default on YES. Otherwise the default value is NO + @since v0.8 + */ +-(void) setOpacityModifyRGB:(BOOL)boolean; +/** returns whether or not the opacity will be applied using glColor(R,G,B,opacity) or glColor(opacity, opacity, opacity, opacity); + @since v0.8 + */ + -(BOOL) doesOpacityModifyRGB; +@end + +#pragma mark - CCBlendProtocol +/** + You can specify the blending function. + @since v0.99.0 + */ +@protocol CCBlendProtocol +/** set the source blending function for the texture */ +-(void) setBlendFunc:(ccBlendFunc)blendFunc; +/** returns the blending function used for the texture */ +-(ccBlendFunc) blendFunc; +@end + + +#pragma mark - CCTextureProtocol + +/** CCNode objects that uses a Texture2D to render the images. + The texture can have a blending function. + If the texture has alpha premultiplied the default blending function is: + src=GL_ONE dst= GL_ONE_MINUS_SRC_ALPHA + else + src=GL_SRC_ALPHA dst= GL_ONE_MINUS_SRC_ALPHA + But you can change the blending function at any time. + @since v0.8.0 + */ +@protocol CCTextureProtocol +/** returns the used texture */ +-(CCTexture2D*) texture; +/** sets a new texture. it will be retained */ +-(void) setTexture:(CCTexture2D*)texture; +@end + +#pragma mark - CCLabelProtocol +/** Common interface for Labels */ +@protocol CCLabelProtocol +/** sets a new label using an NSString. + The string will be copied. + */ +-(void) setString:(NSString*)label; +/** returns the string that is rendered */ +-(NSString*) string; +@optional +/** sets a new label using a CString. + It is faster than setString since it doesn't require to alloc/retain/release an NString object. + @since v0.99.0 + */ +-(void) setCString:(char*)label; +@end + + +#pragma mark - CCDirectorDelegate +/** CCDirector delegate */ +@protocol CCDirectorDelegate + +@optional +/** Called by CCDirector when the projection is updated, and "custom" projection is used */ +-(void) updateProjection; + +#ifdef __CC_PLATFORM_IOS +/** Returns a Boolean value indicating whether the CCDirector supports the specified orientation. Default value is YES (supports all possible orientations) */ +- (BOOL)shouldAutorotateToInterfaceOrientation:(UIInterfaceOrientation)interfaceOrientation; + +// Commented. See issue #1453 for further info: http://code.google.com/p/cocos2d-iphone/issues/detail?id=1453 +//- (void)willRotateToInterfaceOrientation:(UIInterfaceOrientation)toInterfaceOrientation duration:(NSTimeInterval)duration; + +/** Called when projection is resized (due to layoutSubviews on the view). This is important to respond to in order to setup your scene with the proper dimensions (which only exist after the first call to layoutSubviews) so that you can set your scene as early as possible to avoid startup flicker + */ +-(void) directorDidReshapeProjection:(CCDirector*)director; + +#endif // __CC_PLATFORM_IOS + +@end + + +#pragma mark - CCAccelerometerDelegate + +#ifdef __CC_PLATFORM_IOS +/** CCAccelerometerDelegate delegate */ +@class UIAcceleration; +@class UIAccelerometer; +@protocol CCAccelerometerDelegate + +@optional +- (void)accelerometer:(UIAccelerometer *)accelerometer didAccelerate:(UIAcceleration *)acceleration; +@end +#endif // __CC_PLATFORM_IOS diff --git "a/21451198\345\215\242\350\266\205/project5/MyPlane/libs/cocos2d/CCRenderTexture.h" "b/21451198\345\215\242\350\266\205/project5/MyPlane/libs/cocos2d/CCRenderTexture.h" new file mode 100644 index 00000000..21b2fe1e --- /dev/null +++ "b/21451198\345\215\242\350\266\205/project5/MyPlane/libs/cocos2d/CCRenderTexture.h" @@ -0,0 +1,159 @@ +/* + * cocos2d for iPhone: http://www.cocos2d-iphone.org + * + * Copyright (c) 2009 Jason Booth + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + * THE SOFTWARE. + * + */ + +#import + +#import "ccMacros.h" +#import "CCNode.h" +#import "CCSprite.h" +#import "Support/OpenGL_Internal.h" +#import "kazmath/mat4.h" + +#ifdef __CC_PLATFORM_IOS +#import +#endif // iPHone + +typedef enum +{ + kCCImageFormatJPEG = 0, + kCCImageFormatPNG = 1, +} tCCImageFormat; + + +/** + CCRenderTexture is a generic rendering target. To render things into it, + simply construct a render target, call begin on it, call visit on any cocos2d + scenes or objects to render them, and call end. For convenience, render texture + adds a sprite as its display child with the results, so you can simply add + the render texture to your scene and treat it like any other CCNode. + There are also functions for saving the render texture to disk in PNG or JPG format. + + @since v0.8.1 + */ +@interface CCRenderTexture : CCNode +{ + GLuint _FBO; + GLuint _depthRenderBufffer; + GLint _oldFBO; + CCTexture2D* _texture; + CCSprite* _sprite; + GLenum _pixelFormat; + + // code for "auto" update + GLbitfield _clearFlags; + ccColor4F _clearColor; + GLclampf _clearDepth; + GLint _clearStencil; + BOOL _autoDraw; +} + +/** The CCSprite being used. + The sprite, by default, will use the following blending function: GL_ONE, GL_ONE_MINUS_SRC_ALPHA. + The blending function can be changed in runtime by calling: + - [[renderTexture sprite] setBlendFunc:(ccBlendFunc){GL_ONE, GL_ONE_MINUS_SRC_ALPHA}]; +*/ +@property (nonatomic,readwrite, retain) CCSprite* sprite; + +/** Valid flags: GL_COLOR_BUFFER_BIT, GL_DEPTH_BUFFER_BIT, GL_STENCIL_BUFFER_BIT. They can be OR'ed. Valid when "autoDraw is YES. */ +@property (nonatomic, readwrite) GLbitfield clearFlags; +/** Clear color value. Valid only when "autoDraw" is YES. */ +@property (nonatomic, readwrite) ccColor4F clearColor; +/** Value for clearDepth. Valid only when autoDraw is YES. */ +@property (nonatomic, readwrite) GLclampf clearDepth; +/** Value for clear Stencil. Valid only when autoDraw is YES */ +@property (nonatomic, readwrite) GLint clearStencil; +/** When enabled, it will render its children into the texture automatically. Disabled by default for compatiblity reasons. + Will be enabled in the future. + */ +@property (nonatomic, readwrite) BOOL autoDraw; + + +/** initializes a RenderTexture object with width and height in Points and a pixel format( only RGB and RGBA formats are valid ) and depthStencil format*/ ++(id)renderTextureWithWidth:(int)w height:(int)h pixelFormat:(CCTexture2DPixelFormat) format depthStencilFormat:(GLuint)depthStencilFormat; + +/** creates a RenderTexture object with width and height in Points and a pixel format, only RGB and RGBA formats are valid */ ++(id)renderTextureWithWidth:(int)w height:(int)h pixelFormat:(CCTexture2DPixelFormat) format; + +/** creates a RenderTexture object with width and height in Points, pixel format is RGBA8888 */ ++(id)renderTextureWithWidth:(int)w height:(int)h; + +/** initializes a RenderTexture object with width and height in Points and a pixel format, only RGB and RGBA formats are valid */ +-(id)initWithWidth:(int)w height:(int)h pixelFormat:(CCTexture2DPixelFormat) format; + +/** initializes a RenderTexture object with width and height in Points and a pixel format( only RGB and RGBA formats are valid ) and depthStencil format*/ +- (id)initWithWidth:(int)w height:(int)h pixelFormat:(CCTexture2DPixelFormat)format depthStencilFormat:(GLuint)depthStencilFormat; + +/** starts grabbing */ +-(void)begin; + +/** starts rendering to the texture while clearing the texture first. + This is more efficient then calling -clear first and then -begin */ +-(void)beginWithClear:(float)r g:(float)g b:(float)b a:(float)a; + +/** starts rendering to the texture while clearing the texture first. + This is more efficient then calling -clear first and then -begin */ +- (void)beginWithClear:(float)r g:(float)g b:(float)b a:(float)a depth:(float)depthValue; + +/** starts rendering to the texture while clearing the texture first. + This is more efficient then calling -clear first and then -begin */ +- (void)beginWithClear:(float)r g:(float)g b:(float)b a:(float)a depth:(float)depthValue stencil:(int)stencilValue; + + +/** ends grabbing */ +-(void)end; + +/** clears the texture with a color */ +-(void)clear:(float)r g:(float)g b:(float)b a:(float)a; + +/** clears the texture with a specified depth value */ +- (void)clearDepth:(float)depthValue; + +/** clears the texture with a specified stencil value */ +- (void)clearStencil:(int)stencilValue; + +/* creates a new CGImage from with the texture's data. + Caller is responsible for releasing it by calling CGImageRelease(). + */ +-(CGImageRef) newCGImage; + +/** saves the texture into a file using JPEG format. The file will be saved in the Documents folder. + Returns YES if the operation is successful. + */ +-(BOOL)saveToFile:(NSString*)name; + +/** saves the texture into a file. The format could be JPG or PNG. The file will be saved in the Documents folder. + Returns YES if the operation is successful. + */ +-(BOOL)saveToFile:(NSString*)name format:(tCCImageFormat)format; + +#ifdef __CC_PLATFORM_IOS + +/* returns an autoreleased UIImage from the texture */ +-(UIImage *) getUIImage; + +#endif // __CC_PLATFORM_IOS + +@end + diff --git "a/21451198\345\215\242\350\266\205/project5/MyPlane/libs/cocos2d/CCRenderTexture.m" "b/21451198\345\215\242\350\266\205/project5/MyPlane/libs/cocos2d/CCRenderTexture.m" new file mode 100644 index 00000000..f63afd81 --- /dev/null +++ "b/21451198\345\215\242\350\266\205/project5/MyPlane/libs/cocos2d/CCRenderTexture.m" @@ -0,0 +1,553 @@ +/* + * cocos2d for iPhone: http://www.cocos2d-iphone.org + * + * Copyright (c) 2009 Jason Booth + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + * THE SOFTWARE. + * + */ + +#import "CCRenderTexture.h" +#import "CCDirector.h" +#import "ccMacros.h" +#import "CCGLProgram.h" +#import "ccGLStateCache.h" +#import "CCConfiguration.h" +#import "Support/ccUtils.h" +#import "Support/CCFileUtils.h" +#import "Support/CGPointExtension.h" +#import "CCGrid.h" + +#if __CC_PLATFORM_MAC +#import +#endif + +// extern +#import "kazmath/GL/matrix.h" + +@implementation CCRenderTexture + +@synthesize sprite=_sprite; +@synthesize autoDraw=_autoDraw; +@synthesize clearColor=_clearColor; +@synthesize clearDepth=_clearDepth; +@synthesize clearStencil=_clearStencil; +@synthesize clearFlags=_clearFlags; + ++(id)renderTextureWithWidth:(int)w height:(int)h pixelFormat:(CCTexture2DPixelFormat) format depthStencilFormat:(GLuint)depthStencilFormat +{ + return [[[self alloc] initWithWidth:w height:h pixelFormat:format depthStencilFormat:depthStencilFormat] autorelease]; +} + +// issue #994 ++(id)renderTextureWithWidth:(int)w height:(int)h pixelFormat:(CCTexture2DPixelFormat) format +{ + return [[[self alloc] initWithWidth:w height:h pixelFormat:format] autorelease]; +} + ++(id)renderTextureWithWidth:(int)w height:(int)h +{ + return [[[self alloc] initWithWidth:w height:h pixelFormat:kCCTexture2DPixelFormat_RGBA8888 depthStencilFormat:0] autorelease]; +} + +-(id)initWithWidth:(int)w height:(int)h +{ + return [self initWithWidth:w height:h pixelFormat:kCCTexture2DPixelFormat_RGBA8888]; +} + +- (id)initWithWidth:(int)w height:(int)h pixelFormat:(CCTexture2DPixelFormat)format +{ + return [self initWithWidth:w height:h pixelFormat:format depthStencilFormat:0]; +} + +-(id)initWithWidth:(int)w height:(int)h pixelFormat:(CCTexture2DPixelFormat) format depthStencilFormat:(GLuint)depthStencilFormat +{ + if ((self = [super init])) + { + NSAssert(format != kCCTexture2DPixelFormat_A8,@"only RGB and RGBA formats are valid for a render texture"); + + CCDirector *director = [CCDirector sharedDirector]; + + // XXX multithread + if( [director runningThread] != [NSThread currentThread] ) + CCLOGWARN(@"cocos2d: WARNING. CCRenderTexture is running on its own thread. Make sure that an OpenGL context is being used on this thread!"); + + + w *= CC_CONTENT_SCALE_FACTOR(); + h *= CC_CONTENT_SCALE_FACTOR(); + + glGetIntegerv(GL_FRAMEBUFFER_BINDING, &_oldFBO); + + // textures must be power of two + NSUInteger powW; + NSUInteger powH; + + if( [[CCConfiguration sharedConfiguration] supportsNPOT] ) { + powW = w; + powH = h; + } else { + powW = ccNextPOT(w); + powH = ccNextPOT(h); + } + + void *data = malloc((int)(powW * powH * 4)); + memset(data, 0, (int)(powW * powH * 4)); + _pixelFormat=format; + + _texture = [[CCTexture2D alloc] initWithData:data pixelFormat:_pixelFormat pixelsWide:powW pixelsHigh:powH contentSize:CGSizeMake(w, h)]; + free( data ); + + GLint oldRBO; + glGetIntegerv(GL_RENDERBUFFER_BINDING, &oldRBO); + + // generate FBO + glGenFramebuffers(1, &_FBO); + glBindFramebuffer(GL_FRAMEBUFFER, _FBO); + + // associate texture with FBO + glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, _texture.name, 0); + + if (depthStencilFormat != 0) { + //create and attach depth buffer + glGenRenderbuffers(1, &_depthRenderBufffer); + glBindRenderbuffer(GL_RENDERBUFFER, _depthRenderBufffer); + glRenderbufferStorage(GL_RENDERBUFFER, depthStencilFormat, (GLsizei)powW, (GLsizei)powH); + glFramebufferRenderbuffer(GL_FRAMEBUFFER, GL_DEPTH_ATTACHMENT, GL_RENDERBUFFER, _depthRenderBufffer); + + // if depth format is the one with stencil part, bind same render buffer as stencil attachment + if (depthStencilFormat == GL_DEPTH24_STENCIL8) + glFramebufferRenderbuffer(GL_FRAMEBUFFER, GL_STENCIL_ATTACHMENT, GL_RENDERBUFFER, _depthRenderBufffer); + } + + // check if it worked (probably worth doing :) ) + NSAssert( glCheckFramebufferStatus(GL_FRAMEBUFFER) == GL_FRAMEBUFFER_COMPLETE, @"Could not attach texture to framebuffer"); + + [_texture setAliasTexParameters]; + + // retained + self.sprite = [CCSprite spriteWithTexture:_texture]; + + [_texture release]; + [_sprite setScaleY:-1]; + + // issue #937 + [_sprite setBlendFunc:(ccBlendFunc){GL_ONE, GL_ONE_MINUS_SRC_ALPHA}]; + // issue #1464 + [_sprite setOpacityModifyRGB:YES]; + + glBindRenderbuffer(GL_RENDERBUFFER, oldRBO); + glBindFramebuffer(GL_FRAMEBUFFER, _oldFBO); + + // Diabled by default. + _autoDraw = NO; + + // add sprite for backward compatibility + [self addChild:_sprite]; + } + return self; +} + +-(void)dealloc +{ + glDeleteFramebuffers(1, &_FBO); + if (_depthRenderBufffer) + glDeleteRenderbuffers(1, &_depthRenderBufffer); + + [_sprite release]; + [super dealloc]; +} + +-(void)begin +{ + kmGLMatrixMode(KM_GL_PROJECTION); + kmGLPushMatrix(); + kmGLMatrixMode(KM_GL_MODELVIEW); + kmGLPushMatrix(); + + CCDirector *director = [CCDirector sharedDirector]; + [director setProjection:director.projection]; + + CGSize texSize = [_texture contentSizeInPixels]; + + + // Calculate the adjustment ratios based on the old and new projections + CGSize size = [director winSizeInPixels]; + float widthRatio = size.width / texSize.width; + float heightRatio = size.height / texSize.height; + + + // Adjust the orthographic projection and viewport + glViewport(0, 0, texSize.width, texSize.height ); + + kmMat4 orthoMatrix; + kmMat4OrthographicProjection(&orthoMatrix, (float)-1.0 / widthRatio, (float)1.0 / widthRatio, + (float)-1.0 / heightRatio, (float)1.0 / heightRatio, -1,1 ); + kmGLMultMatrix(&orthoMatrix); + + + glGetIntegerv(GL_FRAMEBUFFER_BINDING, &_oldFBO); + glBindFramebuffer(GL_FRAMEBUFFER, _FBO); +} + +-(void)beginWithClear:(float)r g:(float)g b:(float)b a:(float)a depth:(float)depthValue stencil:(int)stencilValue flags:(GLbitfield)flags +{ + [self begin]; + + // save clear color + GLfloat clearColor[4]; + GLfloat depthClearValue; + int stencilClearValue; + + if(flags & GL_COLOR_BUFFER_BIT) { + glGetFloatv(GL_COLOR_CLEAR_VALUE,clearColor); + glClearColor(r, g, b, a); + } + + if( flags & GL_DEPTH_BUFFER_BIT ) { + glGetFloatv(GL_DEPTH_CLEAR_VALUE, &depthClearValue); + glClearDepth(depthValue); + } + + if( flags & GL_STENCIL_BUFFER_BIT ) { + glGetIntegerv(GL_STENCIL_CLEAR_VALUE, &stencilClearValue); + glClearStencil(stencilValue); + } + + glClear(flags); + + + // restore + if( flags & GL_COLOR_BUFFER_BIT) + glClearColor(clearColor[0], clearColor[1], clearColor[2], clearColor[3]); + if( flags & GL_DEPTH_BUFFER_BIT) + glClearDepth(depthClearValue); + if( flags & GL_STENCIL_BUFFER_BIT) + glClearStencil(stencilClearValue); +} + +-(void)beginWithClear:(float)r g:(float)g b:(float)b a:(float)a +{ + [self beginWithClear:r g:g b:b a:a depth:0 stencil:0 flags:GL_COLOR_BUFFER_BIT]; +} + +-(void)beginWithClear:(float)r g:(float)g b:(float)b a:(float)a depth:(float)depthValue +{ + [self beginWithClear:r g:g b:b a:a depth:depthValue stencil:0 flags:GL_COLOR_BUFFER_BIT|GL_DEPTH_BUFFER_BIT]; +} +-(void)beginWithClear:(float)r g:(float)g b:(float)b a:(float)a depth:(float)depthValue stencil:(int)stencilValue +{ + [self beginWithClear:r g:g b:b a:a depth:depthValue stencil:stencilValue flags:GL_COLOR_BUFFER_BIT|GL_DEPTH_BUFFER_BIT|GL_STENCIL_BUFFER_BIT]; +} + +-(void)end +{ + CCDirector *director = [CCDirector sharedDirector]; + glBindFramebuffer(GL_FRAMEBUFFER, _oldFBO); + + // restore viewport + [director setViewport]; + + kmGLMatrixMode(KM_GL_PROJECTION); + kmGLPopMatrix(); + kmGLMatrixMode(KM_GL_MODELVIEW); + kmGLPopMatrix(); +} + +-(void)clear:(float)r g:(float)g b:(float)b a:(float)a +{ + [self beginWithClear:r g:g b:b a:a]; + [self end]; +} + +- (void)clearDepth:(float)depthValue +{ + [self begin]; + //! save old depth value + GLfloat depthClearValue; + glGetFloatv(GL_DEPTH_CLEAR_VALUE, &depthClearValue); + + glClearDepth(depthValue); + glClear(GL_DEPTH_BUFFER_BIT); + + // restore clear color + glClearDepth(depthClearValue); + [self end]; +} + +- (void)clearStencil:(int)stencilValue +{ + // save old stencil value + int stencilClearValue; + glGetIntegerv(GL_STENCIL_CLEAR_VALUE, &stencilClearValue); + + glClearStencil(stencilValue); + glClear(GL_STENCIL_BUFFER_BIT); + + // restore clear color + glClearStencil(stencilClearValue); +} + +#pragma mark RenderTexture - "auto" update + +- (void)visit +{ + // override visit. + // Don't call visit on its children + if (!_visible) + return; + + kmGLPushMatrix(); + + if (_grid && _grid.active) { + [_grid beforeDraw]; + [self transformAncestors]; + } + + [self transform]; + [_sprite visit]; + [self draw]; + + if (_grid && _grid.active) + [_grid afterDraw:self]; + + kmGLPopMatrix(); + + _orderOfArrival = 0; +} + +- (void)draw +{ + if( _autoDraw) { + + [self begin]; + + if (_clearFlags) { + + GLfloat oldClearColor[4]; + GLfloat oldDepthClearValue; + GLint oldStencilClearValue; + + // backup and set + if( _clearFlags & GL_COLOR_BUFFER_BIT ) { + glGetFloatv(GL_COLOR_CLEAR_VALUE, oldClearColor); + glClearColor(_clearColor.r, _clearColor.g, _clearColor.b, _clearColor.a); + } + + if( _clearFlags & GL_DEPTH_BUFFER_BIT ) { + glGetFloatv(GL_DEPTH_CLEAR_VALUE, &oldDepthClearValue); + glClearDepth(_clearDepth); + } + + if( _clearFlags & GL_STENCIL_BUFFER_BIT ) { + glGetIntegerv(GL_STENCIL_CLEAR_VALUE, &oldStencilClearValue); + glClearStencil(_clearStencil); + } + + // clear + glClear(_clearFlags); + + // restore + if( _clearFlags & GL_COLOR_BUFFER_BIT ) + glClearColor(oldClearColor[0], oldClearColor[1], oldClearColor[2], oldClearColor[3]); + if( _clearFlags & GL_DEPTH_BUFFER_BIT ) + glClearDepth(oldDepthClearValue); + if( _clearFlags & GL_STENCIL_BUFFER_BIT ) + glClearStencil(oldStencilClearValue); + } + + //! make sure all children are drawn + [self sortAllChildren]; + + CCNode *child; + CCARRAY_FOREACH(_children, child) { + if( child != _sprite) + [child visit]; + } + [self end]; + + } + +// [_sprite visit]; +} + +#pragma mark RenderTexture - Save Image + +-(CGImageRef) newCGImage +{ + NSAssert(_pixelFormat == kCCTexture2DPixelFormat_RGBA8888,@"only RGBA8888 can be saved as image"); + + + CGSize s = [_texture contentSizeInPixels]; + int tx = s.width; + int ty = s.height; + + int bitsPerComponent = 8; + int bitsPerPixel = 4 * 8; + int bytesPerPixel = bitsPerPixel / 8; + int bytesPerRow = bytesPerPixel * tx; + NSInteger myDataLength = bytesPerRow * ty; + + GLubyte *buffer = calloc(myDataLength,1); + GLubyte *pixels = calloc(myDataLength,1); + + + if( ! (buffer && pixels) ) { + CCLOG(@"cocos2d: CCRenderTexture#getCGImageFromBuffer: not enough memory"); + free(buffer); + free(pixels); + return nil; + } + + [self begin]; + + + glReadPixels(0,0,tx,ty,GL_RGBA,GL_UNSIGNED_BYTE, buffer); + + [self end]; + + // make data provider with data. + + CGBitmapInfo bitmapInfo = kCGImageAlphaPremultipliedLast | kCGBitmapByteOrderDefault; + CGDataProviderRef provider = CGDataProviderCreateWithData(NULL, buffer, myDataLength, NULL); + CGColorSpaceRef colorSpaceRef = CGColorSpaceCreateDeviceRGB(); + CGImageRef iref = CGImageCreate(tx, ty, + bitsPerComponent, bitsPerPixel, bytesPerRow, + colorSpaceRef, bitmapInfo, provider, + NULL, false, + kCGRenderingIntentDefault); + + CGContextRef context = CGBitmapContextCreate(pixels, tx, + ty, CGImageGetBitsPerComponent(iref), + CGImageGetBytesPerRow(iref), CGImageGetColorSpace(iref), + bitmapInfo); + + // vertically flipped + if( YES ) { + CGContextTranslateCTM(context, 0.0f, ty); + CGContextScaleCTM(context, 1.0f, -1.0f); + } + CGContextDrawImage(context, CGRectMake(0.0f, 0.0f, tx, ty), iref); + CGImageRef image = CGBitmapContextCreateImage(context); + + CGContextRelease(context); + CGImageRelease(iref); + CGColorSpaceRelease(colorSpaceRef); + CGDataProviderRelease(provider); + + free(pixels); + free(buffer); + + return image; +} + +-(BOOL) saveToFile:(NSString*)name +{ + return [self saveToFile:name format:kCCImageFormatJPEG]; +} + +-(BOOL)saveToFile:(NSString*)fileName format:(tCCImageFormat)format +{ + BOOL success; + + NSString *fullPath = [[NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES) objectAtIndex:0] stringByAppendingPathComponent:fileName]; + + CGImageRef imageRef = [self newCGImage]; + + if( ! imageRef ) { + CCLOG(@"cocos2d: Error: Cannot create CGImage ref from texture"); + return NO; + } + +#if __CC_PLATFORM_IOS + + UIImage* image = [[UIImage alloc] initWithCGImage:imageRef scale:CC_CONTENT_SCALE_FACTOR() orientation:UIImageOrientationUp]; + NSData *imageData = nil; + + if( format == kCCImageFormatPNG ) + imageData = UIImagePNGRepresentation( image ); + + else if( format == kCCImageFormatJPEG ) + imageData = UIImageJPEGRepresentation(image, 0.9f); + + else + NSAssert(NO, @"Unsupported format"); + + [image release]; + + success = [imageData writeToFile:fullPath atomically:YES]; + + +#elif __CC_PLATFORM_MAC + + CFURLRef url = (CFURLRef)[NSURL fileURLWithPath:fullPath]; + + CGImageDestinationRef dest; + + if( format == kCCImageFormatPNG ) + dest = CGImageDestinationCreateWithURL(url, kUTTypePNG, 1, NULL); + + else if( format == kCCImageFormatJPEG ) + dest = CGImageDestinationCreateWithURL(url, kUTTypeJPEG, 1, NULL); + + else + NSAssert(NO, @"Unsupported format"); + + CGImageDestinationAddImage(dest, imageRef, nil); + + success = CGImageDestinationFinalize(dest); + + CFRelease(dest); +#endif + + CGImageRelease(imageRef); + + if( ! success ) + CCLOG(@"cocos2d: ERROR: Failed to save file:%@ to disk",fullPath); + + return success; +} + + +#if __CC_PLATFORM_IOS + +-(UIImage *) getUIImage +{ + CGImageRef imageRef = [self newCGImage]; + + UIImage* image = [[UIImage alloc] initWithCGImage:imageRef scale:CC_CONTENT_SCALE_FACTOR() orientation:UIImageOrientationUp]; + + CGImageRelease( imageRef ); + + return [image autorelease]; +} +#endif // __CC_PLATFORM_IOS + +#pragma RenderTexture - Override + +-(CGSize) contentSize +{ + return _texture.contentSize; +} + +-(void) setContentSize:(CGSize)size +{ + NSAssert(NO, @"You cannot change the content size of an already created CCRenderTexture. Recreate it"); +} + +@end diff --git "a/21451198\345\215\242\350\266\205/project5/MyPlane/libs/cocos2d/CCScene.h" "b/21451198\345\215\242\350\266\205/project5/MyPlane/libs/cocos2d/CCScene.h" new file mode 100644 index 00000000..02f504fd --- /dev/null +++ "b/21451198\345\215\242\350\266\205/project5/MyPlane/libs/cocos2d/CCScene.h" @@ -0,0 +1,47 @@ +/* + * cocos2d for iPhone: http://www.cocos2d-iphone.org + * + * Copyright (c) 2008-2010 Ricardo Quesada + * Copyright (c) 2011 Zynga Inc. + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + * THE SOFTWARE. + * + */ + + +#import "CCNode.h" + +/** CCScene is a subclass of CCNode that is used only as an abstract concept. + + CCScene an CCNode are almost identical with the difference that CCScene has its + anchor point (by default) at the center of the screen. + + For the moment CCScene has no other logic than that, but in future releases it might have + additional logic. + + It is a good practice to use and CCScene as the parent of all your nodes. +*/ +@interface CCScene : CCNode +{ +} +/** initializes a node. + The node will be created as "autorelease". + */ +-(id) init; +@end diff --git "a/21451198\345\215\242\350\266\205/project5/MyPlane/libs/cocos2d/CCScene.m" "b/21451198\345\215\242\350\266\205/project5/MyPlane/libs/cocos2d/CCScene.m" new file mode 100644 index 00000000..9bb52d7b --- /dev/null +++ "b/21451198\345\215\242\350\266\205/project5/MyPlane/libs/cocos2d/CCScene.m" @@ -0,0 +1,45 @@ +/* + * cocos2d for iPhone: http://www.cocos2d-iphone.org + * + * Copyright (c) 2008-2010 Ricardo Quesada + * Copyright (c) 2011 Zynga Inc. + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + * THE SOFTWARE. + * + */ + + +#import "CCScene.h" +#import "Support/CGPointExtension.h" +#import "CCDirector.h" + + +@implementation CCScene +-(id) init +{ + if( (self=[super init]) ) { + CGSize s = [[CCDirector sharedDirector] winSize]; + self.ignoreAnchorPointForPosition = YES; + _anchorPoint = ccp(0.5f, 0.5f); + [self setContentSize:s]; + } + + return self; +} +@end diff --git "a/21451198\345\215\242\350\266\205/project5/MyPlane/libs/cocos2d/CCScheduler.h" "b/21451198\345\215\242\350\266\205/project5/MyPlane/libs/cocos2d/CCScheduler.h" new file mode 100644 index 00000000..c4f4997a --- /dev/null +++ "b/21451198\345\215\242\350\266\205/project5/MyPlane/libs/cocos2d/CCScheduler.h" @@ -0,0 +1,284 @@ +/* + * cocos2d for iPhone: http://www.cocos2d-iphone.org + * + * Copyright (c) 2008-2010 Ricardo Quesada + * Copyright (c) 2011 Zynga Inc. + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + * THE SOFTWARE. + */ + + + +#import "Support/uthash.h" +#import "ccTypes.h" + +// Priority level reserved for system services. +#define kCCPrioritySystem INT_MIN + +// Minimum priority level for user scheduling. +#define kCCPriorityNonSystemMin (kCCPrioritySystem+1) + +typedef void (*TICK_IMP)(id, SEL, ccTime); + +// +// CCTimer +// +/** Light weight timer */ +@interface CCTimer : NSObject +{ + ccTime _interval; + ccTime _elapsed; + BOOL _runForever; + BOOL _useDelay; + uint _nTimesExecuted; + uint _repeat; //0 = once, 1 is 2 x executed + ccTime _delay; +} + +/** interval in seconds */ +@property (nonatomic,readwrite,assign) ccTime interval; + + +/** triggers the timer */ +-(void) update: (ccTime) dt; +@end + +@interface CCTimerTargetSelector : CCTimer +{ + id _target; + SEL _selector; + TICK_IMP _impMethod; +} + +/** selector */ +@property (nonatomic,readonly) SEL selector; + +/** Allocates a timer with a target and a selector. */ ++(id) timerWithTarget:(id) t selector:(SEL)s; + +/** Allocates a timer with a target, a selector and an interval in seconds. */ ++(id) timerWithTarget:(id) t selector:(SEL)s interval:(ccTime)seconds; + +/** Initializes a timer with a target and a selector. */ +-(id) initWithTarget:(id) t selector:(SEL)s; + +/** Initializes a timer with a target, a selector, an interval in seconds, repeat in number of times to repeat, delay in seconds */ +-(id) initWithTarget:(id)t selector:(SEL)s interval:(ccTime) seconds repeat:(uint) r delay:(ccTime) d; +@end + + +@interface CCTimerBlock : CCTimer +{ + void (^_block)(ccTime delta); + NSString *_key; + id _target; +} + +/** unique identifier of the block */ +@property (nonatomic, readonly) NSString *key; + +/** owner of the timer */ +@property (nonatomic, readonly, assign) id target; + +/** Allocates a timer with a target, interval in seconds, a key and a block */ ++(id) timerWithTarget:(id)owner interval:(ccTime)seconds key:(NSString*)key block:(void(^)(ccTime delta)) block; + +/** Initializes a timer with a target(owner), interval in seconds, repeat in number of times to repeat, delay in seconds and a block */ +-(id) initWithTarget:(id)owner interval:(ccTime) seconds repeat:(uint) r delay:(ccTime)d key:(NSString*)key block:(void(^)(ccTime delta))block; +@end + + +// +// CCScheduler +// +/** CCScheduler is responsible of triggering the scheduled callbacks. + You should not use NSTimer. Instead use this class. + + There are 2 different types of callbacks (selectors): + + - update selector: the 'update' selector will be called every frame. You can customize the priority. + - custom selector: A custom selector will be called every frame, or with a custom interval of time + + The 'custom selectors' should be avoided when possible. It is faster, and consumes less memory to use the 'update selector'. + +*/ + +struct _listEntry; +struct _hashSelectorEntry; +struct _hashUpdateEntry; + +@interface CCScheduler : NSObject +{ + ccTime _timeScale; + + // + // "updates with priority" stuff + // + struct _listEntry *updatesNeg; // list of priority < 0 + struct _listEntry *updates0; // list priority == 0 + struct _listEntry *updatesPos; // list priority > 0 + struct _hashUpdateEntry *hashForUpdates; // hash used to fetch quickly the list entries for pause,delete,etc. + + // Used for "selectors with interval" + struct _hashSelectorEntry *hashForTimers; + struct _hashSelectorEntry *currentTarget; + BOOL currentTargetSalvaged; + + // Optimization + TICK_IMP impMethod; + SEL updateSelector; + + BOOL updateHashLocked; // If true unschedule will not remove anything from a hash. Elements will only be marked for deletion. + + BOOL _paused; +} + +/** Modifies the time of all scheduled callbacks. + You can use this property to create a 'slow motion' or 'fast forward' effect. + Default is 1.0. To create a 'slow motion' effect, use values below 1.0. + To create a 'fast forward' effect, use values higher than 1.0. + @since v0.8 + @warning It will affect EVERY scheduled selector / action. + */ +@property (nonatomic,readwrite) ccTime timeScale; + + +/** Will pause / resume the CCScheduler. + It won't dispatch any message to any target/selector, block if it is paused. + + The difference between `pauseAllTargets` and `pause, is that `setPaused` will pause the CCScheduler, + while `pauseAllTargets` will pause all the targets, one by one. + `setPaused` will pause the whole Scheduler, meaning that calls to `resumeTargets:`, `resumeTarget:` won't affect it. + + @since v2.1.0 + */ +@property (nonatomic,readonly,getter=isPaused) BOOL paused; + +/** 'update' the scheduler. + You should NEVER call this method, unless you know what you are doing. + */ +-(void) update:(ccTime)dt; + +/** The scheduled method will be called every 'interval' seconds. + If paused is YES, then it won't be called until it is resumed. + If 'interval' is 0, it will be called every frame, but if so, it recommended to use 'scheduleUpdateForTarget:' instead. + If the selector is already scheduled, then only the interval parameter will be updated without re-scheduling it again. + repeat lets the action be repeated repeat + 1 times, use kCCRepeatForever to let the action run continuously + delay is the amount of time the action will wait before it'll start + + @since v0.99.3, repeat and delay added in v1.1 + */ +-(void) scheduleSelector:(SEL)selector forTarget:(id)target interval:(ccTime)interval repeat:(uint)repeat delay:(ccTime)delay paused:(BOOL)paused; + +/** calls scheduleSelector with kCCRepeatForever and a 0 delay */ +-(void) scheduleSelector:(SEL)selector forTarget:(id)target interval:(ccTime)interval paused:(BOOL)paused; + +/** Schedules the 'update' selector for a given target with a given priority. + The 'update' selector will be called every frame. + The lower the priority, the earlier it is called. + @since v0.99.3 + */ +-(void) scheduleUpdateForTarget:(id)target priority:(NSInteger)priority paused:(BOOL)paused; + +/** The scheduled block will be called every 'interval' seconds. + 'key' is a unique identifier of the block. Needed to unschedule the block or update its interval. + 'target' is needed for all the method related to "target" like "pause" and "unschedule" + If 'interval' is 0, it will be called every frame, but if so, it recommended to use 'scheduleUpdateForTarget:' instead. + 'repeat' lets the action be repeated repeat + 1 times, use kCCRepeatForever to let the action run continuously. + 'delay' is the amount of time the action will wait before it'll start. + If paused is YES, then it won't be called until it is resumed. + If the block is already scheduled, then only the interval parameter will be updated without re-scheduling it again. + @since v2.1 + */ +-(void) scheduleBlockForKey:(NSString*)key target:(id)target interval:(ccTime)interval repeat:(uint)repeat delay:(ccTime)delay paused:(BOOL)paused block:(void(^)(ccTime dt))block; + +/** Unshedules a selector for a given target. + If you want to unschedule the "update", use unscheudleUpdateForTarget. + @since v0.99.3 + */ +-(void) unscheduleSelector:(SEL)selector forTarget:(id)target; + +/** Unshedules a block for a given key / target pair. + If you want to unschedule the "update", use unscheudleUpdateForTarget. + @since v2.1 + */ +-(void) unscheduleBlockForKey:(NSString*)key target:(id)target; + +/** Unschedules the update selector for a given target + @since v0.99.3 + */ +-(void) unscheduleUpdateForTarget:(id)target; + +/** Unschedules all selectors and blocks for a given target. + This also includes the "update" selector. + @since v0.99.3 + */ +-(void) unscheduleAllForTarget:(id)target; + +/** Unschedules all selectors and blocks from all targets. + You should NEVER call this method, unless you know what you are doing. + + @since v0.99.3 + */ +-(void) unscheduleAll; + +/** Unschedules all selectors and blocks from all targets with a minimum priority. + You should only call this with kCCPriorityNonSystemMin or higher. + @since v2.0.0 + */ +-(void) unscheduleAllWithMinPriority:(NSInteger)minPriority; + +/** Pauses the target. + All scheduled selectors/update for a given target won't be 'ticked' until the target is resumed. + If the target is not present, nothing happens. + @since v0.99.3 + */ +-(void) pauseTarget:(id)target; + +/** Resumes the target. + The 'target' will be unpaused, so all schedule selectors/update will be 'ticked' again. + If the target is not present, nothing happens. + @since v0.99.3 + */ +-(void) resumeTarget:(id)target; + +/** Returns whether or not the target is paused + @since v1.0.0 + */ +-(BOOL) isTargetPaused:(id)target; + +/** Pause all selectors and blocks from all targets. + You should NEVER call this method, unless you know what you are doing. + @since v2.0.0 + */ +-(NSSet*) pauseAllTargets; + +/** Pause all selectors and blocks from all targets with a minimum priority. + You should only call this with kCCPriorityNonSystemMin or higher. + @since v2.0.0 + */ +-(NSSet*) pauseAllTargetsWithMinPriority:(NSInteger)minPriority; + +/** Resume selectors on a set of targets. + This can be useful for undoing a call to pauseAllSelectors. + @since v2.0.0 + */ +-(void) resumeTargets:(NSSet *)targetsToResume; + +@end diff --git "a/21451198\345\215\242\350\266\205/project5/MyPlane/libs/cocos2d/CCScheduler.m" "b/21451198\345\215\242\350\266\205/project5/MyPlane/libs/cocos2d/CCScheduler.m" new file mode 100644 index 00000000..f24a644d --- /dev/null +++ "b/21451198\345\215\242\350\266\205/project5/MyPlane/libs/cocos2d/CCScheduler.m" @@ -0,0 +1,931 @@ +/* + * cocos2d for iPhone: http://www.cocos2d-iphone.org + * + * Copyright (c) 2008-2010 Ricardo Quesada + * Copyright (c) 2011 Zynga Inc. + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + * THE SOFTWARE. + */ + + +// cocos2d imports +#import "CCScheduler.h" +#import "ccMacros.h" +#import "CCDirector.h" +#import "Support/uthash.h" +#import "Support/utlist.h" +#import "Support/ccCArray.h" + +// +// Data structures +// +#pragma mark - +#pragma mark Data Structures + +// A list double-linked list used for "updates with priority" +typedef struct _listEntry +{ + struct _listEntry *prev, *next; + TICK_IMP impMethod; + id target; // not retained (retained by hashUpdateEntry) + NSInteger priority; + BOOL paused; + BOOL markedForDeletion; // selector will no longer be called and entry will be removed at end of the next tick +} tListEntry; + +typedef struct _hashUpdateEntry +{ + tListEntry **list; // Which list does it belong to ? + tListEntry *entry; // entry in the list + id target; // hash key (retained) + UT_hash_handle hh; +} tHashUpdateEntry; + +// Hash Element used for "selectors with interval" +typedef struct _hashSelectorEntry +{ + struct ccArray *timers; + id target; // hash key (retained) + unsigned int timerIndex; + CCTimer *currentTimer; + BOOL currentTimerSalvaged; + BOOL paused; + UT_hash_handle hh; +} tHashTimerEntry; + + + +// +// CCTimer +// +#pragma mark - CCTimer + +@interface CCTimer () +-(void) setupTimerWithInterval:(ccTime)seconds repeat:(uint)r delay:(ccTime)d; +-(void) trigger; +-(void) cancel; +@end + +@implementation CCTimer + +@synthesize interval=_interval; + +-(void) setupTimerWithInterval:(ccTime)seconds repeat:(uint)r delay:(ccTime)d +{ + _elapsed = -1; + _interval = seconds; + _delay = d; + _useDelay = (_delay > 0) ? YES : NO; + _repeat = r; + _runForever = (_repeat == kCCRepeatForever) ? YES : NO; +} + +-(void) dealloc +{ + CCLOGINFO(@"cocos2d: deallocing %@", self); + + [super dealloc]; +} + +-(void) trigger +{ + // override me +} + +-(void) cancel +{ + // override me +} + +-(void) update: (ccTime) dt +{ + if( _elapsed == - 1) + { + _elapsed = 0; + _nTimesExecuted = 0; + } + else + { + if (_runForever && !_useDelay) + {//standard timer usage + _elapsed += dt; + if( _elapsed >= _interval ) { + [self trigger]; + _elapsed = 0; + + } + } + else + {//advanced usage + _elapsed += dt; + if (_useDelay) + { + if( _elapsed >= _delay ) + { + [self trigger]; + _elapsed = _elapsed - _delay; + _nTimesExecuted+=1; + _useDelay = NO; + } + } + else + { + if (_elapsed >= _interval) + { + [self trigger]; + _elapsed = 0; + _nTimesExecuted += 1; + + } + } + + if (!_runForever && _nTimesExecuted > _repeat) + { //unschedule timer + [self cancel]; + } + } + } +} +@end + +#pragma mark CCTimerTargetSelector + +@implementation CCTimerTargetSelector + +@synthesize selector=_selector; + ++(id) timerWithTarget:(id)t selector:(SEL)s +{ + return [[[self alloc] initWithTarget:t selector:s interval:0 repeat:kCCRepeatForever delay:0] autorelease]; +} + ++(id) timerWithTarget:(id)t selector:(SEL)s interval:(ccTime) i +{ + return [[[self alloc] initWithTarget:t selector:s interval:i repeat:kCCRepeatForever delay:0] autorelease]; +} + +-(id) initWithTarget:(id)t selector:(SEL)s +{ + return [self initWithTarget:t selector:s interval:0 repeat:kCCRepeatForever delay: 0]; +} + +-(id) initWithTarget:(id)t selector:(SEL)s interval:(ccTime) seconds repeat:(uint) r delay:(ccTime) d +{ + if( (self=[super init]) ) { +#if COCOS2D_DEBUG + NSMethodSignature *sig = [t methodSignatureForSelector:s]; + NSAssert(sig !=0 , @"Signature not found for selector - does it have the following form? -(void) name: (ccTime) dt"); +#endif + + // target is not retained. It is retained in the hash structure + _target = t; + _selector = s; + _impMethod = (TICK_IMP) [t methodForSelector:s]; + + [self setupTimerWithInterval:seconds repeat:r delay:d]; + } + return self; +} + +- (NSString*) description +{ + return [NSString stringWithFormat:@"<%@ = %p | target:%@ selector:(%@)>", [self class], self, [_target class], NSStringFromSelector(_selector)]; +} + +-(void) trigger +{ + _impMethod(_target, _selector, _elapsed); +} + +-(void) cancel +{ + [[[CCDirector sharedDirector] scheduler] unscheduleSelector:_selector forTarget:_target]; +} + +@end + +#pragma mark CCTimerBlock + +@implementation CCTimerBlock + +@synthesize key=_key; +@synthesize target=_target; + ++(id) timerWithTarget:(id)owner interval:(ccTime)seconds key:(NSString*)key block:(void(^)(ccTime delta)) block +{ + return [[[self alloc] initWithTarget:(id)owner interval:seconds repeat:kCCRepeatForever delay:0 key:key block:block] autorelease]; +} + +-(id) initWithTarget:(id)owner interval:(ccTime) seconds repeat:(uint) r delay:(ccTime)d key:(NSString*)key block:(void(^)(ccTime delta))block +{ + if( (self=[super init]) ) { + _block = [block copy]; + _key = [key copy]; + _target = owner; + + [self setupTimerWithInterval:seconds repeat:r delay:d]; + } + + return self; +} + +- (NSString*) description +{ + return [NSString stringWithFormat:@"<%@ = %p | block>", [self class], self]; +} + +- (void)dealloc +{ + [_key release]; + [_block release]; + + [super dealloc]; +} + +-(void) trigger +{ + _block( _elapsed); +} + +-(void) cancel +{ + [[[CCDirector sharedDirector] scheduler] unscheduleBlockForKey:_key target:_target]; +} + +@end + + + +// +// CCScheduler +// +#pragma mark - CCScheduler + +@interface CCScheduler (Private) +-(void) removeHashElement:(tHashTimerEntry*)element; +@end + +@implementation CCScheduler + +@synthesize paused = _paused; +@synthesize timeScale = _timeScale; + +- (id) init +{ + if( (self=[super init]) ) { + _timeScale = 1.0f; + + // used to trigger CCTimer#update + updateSelector = @selector(update:); + impMethod = (TICK_IMP) [CCTimerTargetSelector instanceMethodForSelector:updateSelector]; + + // updates with priority + updates0 = NULL; + updatesNeg = NULL; + updatesPos = NULL; + hashForUpdates = NULL; + + // selectors with interval + currentTarget = nil; + currentTargetSalvaged = NO; + hashForTimers = nil; + updateHashLocked = NO; + _paused = NO; + } + + return self; +} + +- (NSString*) description +{ + return [NSString stringWithFormat:@"<%@ = %p | timeScale = %0.2f >", [self class], self, _timeScale]; +} + +- (void) dealloc +{ + CCLOG(@"cocos2d: deallocing %@", self); + + [self unscheduleAll]; + + [super dealloc]; +} + + +#pragma mark CCScheduler - Timers + +-(void) removeHashElement:(tHashTimerEntry*)element +{ + ccArrayFree(element->timers); + [element->target release]; + HASH_DEL(hashForTimers, element); + free(element); +} + +-(void) scheduleSelector:(SEL)selector forTarget:(id)target interval:(ccTime)interval paused:(BOOL)paused +{ + [self scheduleSelector:selector forTarget:target interval:interval repeat:kCCRepeatForever delay:0.0f paused:paused]; +} + +-(void) scheduleSelector:(SEL)selector forTarget:(id)target interval:(ccTime)interval repeat:(uint)repeat delay:(ccTime)delay paused:(BOOL)paused +{ + NSAssert( selector != nil, @"Argument selector must be non-nil"); + NSAssert( target != nil, @"Argument target must be non-nil"); + + tHashTimerEntry *element = NULL; + HASH_FIND_INT(hashForTimers, &target, element); + + if( ! element ) { + element = calloc( sizeof( *element ), 1 ); + element->target = [target retain]; + HASH_ADD_INT( hashForTimers, target, element ); + + // Is this the 1st element ? Then set the pause level to all the selectors of this target + element->paused = paused; + + } else + NSAssert( element->paused == paused, @"CCScheduler. Trying to schedule a selector with a pause value different than the target"); + + + if( element->timers == nil ) + element->timers = ccArrayNew(10); + else + { + for( unsigned int i=0; i< element->timers->num; i++ ) { + CCTimer *timer = element->timers->arr[i]; + if( [timer isKindOfClass:[CCTimerTargetSelector class]] && selector == [(CCTimerTargetSelector*)timer selector] ) { + CCLOG(@"CCScheduler#scheduleSelector. Selector already scheduled. Updating interval from: %.4f to %.4f", [timer interval], interval); + [timer setInterval: interval]; + return; + } + } + ccArrayEnsureExtraCapacity(element->timers, 1); + } + + CCTimerTargetSelector *timer = [[CCTimerTargetSelector alloc] initWithTarget:target selector:selector interval:interval repeat:repeat delay:delay]; + ccArrayAppendObject(element->timers, timer); + [timer release]; +} + +-(void) scheduleBlockForKey:(NSString*)key target:(id)owner interval:(ccTime)interval repeat:(uint)repeat delay:(ccTime)delay paused:(BOOL)paused block:(void(^)(ccTime dt))block +{ + NSAssert( block != nil, @"Argument block must be non-nil"); + NSAssert( owner != nil, @"Argument owner must be non-nil"); + + tHashTimerEntry *element = NULL; + HASH_FIND_INT(hashForTimers, &owner, element); + + if( ! element ) { + element = calloc( sizeof( *element ), 1 ); + element->target = [owner retain]; + HASH_ADD_INT( hashForTimers, target, element ); + + // Is this the 1st element ? Then set the pause level to all the selectors of this target + element->paused = paused; + + } else + NSAssert( element->paused == paused, @"CCScheduler. Trying to schedule a block with a pause value different than the target"); + + + if( element->timers == nil ) + element->timers = ccArrayNew(10); + else + { + for( unsigned int i=0; i< element->timers->num; i++ ) { + CCTimer *timer = element->timers->arr[i]; + if( [timer isKindOfClass:[CCTimerBlock class]] && [key isEqualToString:[(CCTimerBlock*)timer key] ] ) { + CCLOG(@"CCScheduler#scheduleBlock. Block already scheduled. Updating interval from: %.4f to %.4f", [timer interval], interval); + [timer setInterval: interval]; + return; + } + } + ccArrayEnsureExtraCapacity(element->timers, 1); + } + + CCTimerBlock *timer = [[CCTimerBlock alloc] initWithTarget:owner interval:interval repeat:repeat delay:delay key:key block:block]; + ccArrayAppendObject(element->timers, timer); + [timer release]; +} + +-(void) unscheduleSelector:(SEL)selector forTarget:(id)target +{ + // explicity handle nil arguments when removing an object + if( target==nil && selector==NULL) + return; + + NSAssert( target != nil, @"Target MUST not be nil"); + NSAssert( selector != NULL, @"Selector MUST not be NULL"); + + tHashTimerEntry *element = NULL; + HASH_FIND_INT(hashForTimers, &target, element); + + if( element ) { + + for( unsigned int i=0; i< element->timers->num; i++ ) { + CCTimer *timer = element->timers->arr[i]; + + + if( [timer isKindOfClass:[CCTimerTargetSelector class]] && selector == [(CCTimerTargetSelector*)timer selector] ) { + + if( timer == element->currentTimer && !element->currentTimerSalvaged ) { + [element->currentTimer retain]; + element->currentTimerSalvaged = YES; + } + + ccArrayRemoveObjectAtIndex(element->timers, i ); + + // update timerIndex in case we are in tick:, looping over the actions + if( element->timerIndex >= i ) + element->timerIndex--; + + if( element->timers->num == 0 ) { + if( currentTarget == element ) + currentTargetSalvaged = YES; + else + [self removeHashElement: element]; + } + return; + } + } + } + + // Not Found + // NSLog(@"CCScheduler#unscheduleSelector:forTarget: selector not found: %@", selString); + +} + +-(void) unscheduleBlockForKey:(NSString*)key target:(id)target +{ + // explicity handle nil arguments when removing an object + if( target==nil && key==NULL) + return; + + NSAssert( target != nil, @"Target MUST not be nil"); + NSAssert( key != NULL, @"key MUST not be NULL"); + + tHashTimerEntry *element = NULL; + HASH_FIND_INT(hashForTimers, &target, element); + + if( element ) { + + for( unsigned int i=0; i< element->timers->num; i++ ) { + CCTimer *timer = element->timers->arr[i]; + + + if( [timer isKindOfClass:[CCTimerBlock class]] && [key isEqualToString: [(CCTimerBlock*)timer key]] ) { + + if( timer == element->currentTimer && !element->currentTimerSalvaged ) { + [element->currentTimer retain]; + element->currentTimerSalvaged = YES; + } + + ccArrayRemoveObjectAtIndex(element->timers, i ); + + // update timerIndex in case we are in tick:, looping over the actions + if( element->timerIndex >= i ) + element->timerIndex--; + + if( element->timers->num == 0 ) { + if( currentTarget == element ) + currentTargetSalvaged = YES; + else + [self removeHashElement: element]; + } + return; + } + } + } + + // Not Found +// NSLog(@"CCScheduler#unscheduleSelector:forTarget: selector not found: %@", selString); +} + +#pragma mark CCScheduler - Update Specific + +-(void) priorityIn:(tListEntry**)list target:(id)target priority:(NSInteger)priority paused:(BOOL)paused +{ + tListEntry *listElement = malloc( sizeof(*listElement) ); + + listElement->target = target; + listElement->priority = priority; + listElement->paused = paused; + listElement->impMethod = (TICK_IMP) [target methodForSelector:updateSelector]; + listElement->next = listElement->prev = NULL; + listElement->markedForDeletion = NO; + + // empty list ? + if( ! *list ) { + DL_APPEND( *list, listElement ); + + } else { + BOOL added = NO; + + for( tListEntry *elem = *list; elem ; elem = elem->next ) { + if( priority < elem->priority ) { + + if( elem == *list ) + DL_PREPEND(*list, listElement); + else { + listElement->next = elem; + listElement->prev = elem->prev; + + elem->prev->next = listElement; + elem->prev = listElement; + } + + added = YES; + break; + } + } + + // Not added? priority has the higher value. Append it. + if( !added ) + DL_APPEND(*list, listElement); + } + + // update hash entry for quicker access + tHashUpdateEntry *hashElement = calloc( sizeof(*hashElement), 1 ); + hashElement->target = [target retain]; + hashElement->list = list; + hashElement->entry = listElement; + HASH_ADD_INT(hashForUpdates, target, hashElement ); +} + +-(void) appendIn:(tListEntry**)list target:(id)target paused:(BOOL)paused +{ + tListEntry *listElement = malloc( sizeof( * listElement ) ); + + listElement->target = target; + listElement->paused = paused; + listElement->markedForDeletion = NO; + listElement->impMethod = (TICK_IMP) [target methodForSelector:updateSelector]; + + DL_APPEND(*list, listElement); + + + // update hash entry for quicker access + tHashUpdateEntry *hashElement = calloc( sizeof(*hashElement), 1 ); + hashElement->target = [target retain]; + hashElement->list = list; + hashElement->entry = listElement; + HASH_ADD_INT(hashForUpdates, target, hashElement ); +} + +-(void) scheduleUpdateForTarget:(id)target priority:(NSInteger)priority paused:(BOOL)paused +{ + tHashUpdateEntry * hashElement = NULL; + HASH_FIND_INT(hashForUpdates, &target, hashElement); + if(hashElement) + { +#if COCOS2D_DEBUG >= 1 + NSAssert( hashElement->entry->markedForDeletion, @"CCScheduler: You can't re-schedule an 'update' selector'. Unschedule it first"); +#endif + // TODO : check if priority has changed! + + hashElement->entry->markedForDeletion = NO; + return; + } + + // most of the updates are going to be 0, that's way there + // is an special list for updates with priority 0 + if( priority == 0 ) + [self appendIn:&updates0 target:target paused:paused]; + + else if( priority < 0 ) + [self priorityIn:&updatesNeg target:target priority:priority paused:paused]; + + else // priority > 0 + [self priorityIn:&updatesPos target:target priority:priority paused:paused]; +} + +- (void) removeUpdateFromHash:(tListEntry*)entry +{ + tHashUpdateEntry * element = NULL; + + HASH_FIND_INT(hashForUpdates, &entry->target, element); + if( element ) { + // list entry + DL_DELETE( *element->list, element->entry ); + free( element->entry ); + + // hash entry + id target = element->target; + HASH_DEL( hashForUpdates, element); + free(element); + + // target#release should be the last one to prevent + // a possible double-free. eg: If the [target dealloc] might want to remove it itself from there + [target release]; + } +} + +-(void) unscheduleUpdateForTarget:(id)target +{ + if( target == nil ) + return; + + tHashUpdateEntry * element = NULL; + HASH_FIND_INT(hashForUpdates, &target, element); + if( element ) { + if(updateHashLocked) + element->entry->markedForDeletion = YES; + else + [self removeUpdateFromHash:element->entry]; + +// // list entry +// DL_DELETE( *element->list, element->entry ); +// free( element->entry ); +// +// // hash entry +// [element->target release]; +// HASH_DEL( hashForUpdates, element); +// free(element); + } +} + +#pragma mark CCScheduler - Common for Update selector & Custom Selectors + +-(void) unscheduleAll +{ + [self unscheduleAllWithMinPriority:kCCPrioritySystem]; +} + +-(void) unscheduleAllWithMinPriority:(NSInteger)minPriority +{ + // Custom Selectors + for(tHashTimerEntry *element=hashForTimers; element != NULL; ) { + id target = element->target; + element=element->hh.next; + [self unscheduleAllForTarget:target]; + } + + // Updates selectors + tListEntry *entry, *tmp; + if(minPriority < 0) { + DL_FOREACH_SAFE( updatesNeg, entry, tmp ) { + if(entry->priority >= minPriority) { + [self unscheduleUpdateForTarget:entry->target]; + } + } + } + if(minPriority <= 0) { + DL_FOREACH_SAFE( updates0, entry, tmp ) { + [self unscheduleUpdateForTarget:entry->target]; + } + } + DL_FOREACH_SAFE( updatesPos, entry, tmp ) { + if(entry->priority >= minPriority) { + [self unscheduleUpdateForTarget:entry->target]; + } + } + +} + +-(void) unscheduleAllForTarget:(id)target +{ + // explicit nil handling + if( target == nil ) + return; + + // Custom Selectors + tHashTimerEntry *element = NULL; + HASH_FIND_INT(hashForTimers, &target, element); + + if( element ) { + if( ccArrayContainsObject(element->timers, element->currentTimer) && !element->currentTimerSalvaged ) { + [element->currentTimer retain]; + element->currentTimerSalvaged = YES; + } + ccArrayRemoveAllObjects(element->timers); + if( currentTarget == element ) + currentTargetSalvaged = YES; + else + [self removeHashElement:element]; + } + + // Update Selector + [self unscheduleUpdateForTarget:target]; +} + +-(void) resumeTarget:(id)target +{ + NSAssert( target != nil, @"target must be non nil" ); + + // Custom Selectors + tHashTimerEntry *element = NULL; + HASH_FIND_INT(hashForTimers, &target, element); + if( element ) + element->paused = NO; + + // Update selector + tHashUpdateEntry * elementUpdate = NULL; + HASH_FIND_INT(hashForUpdates, &target, elementUpdate); + if( elementUpdate ) { + NSAssert( elementUpdate->entry != NULL, @"resumeTarget: unknown error"); + elementUpdate->entry->paused = NO; + } +} + +-(void) pauseTarget:(id)target +{ + NSAssert( target != nil, @"target must be non nil" ); + + // Custom selectors + tHashTimerEntry *element = NULL; + HASH_FIND_INT(hashForTimers, &target, element); + if( element ) + element->paused = YES; + + // Update selector + tHashUpdateEntry * elementUpdate = NULL; + HASH_FIND_INT(hashForUpdates, &target, elementUpdate); + if( elementUpdate ) { + NSAssert( elementUpdate->entry != NULL, @"pauseTarget: unknown error"); + elementUpdate->entry->paused = YES; + } + +} + +-(BOOL) isTargetPaused:(id)target +{ + NSAssert( target != nil, @"target must be non nil" ); + + // Custom selectors + tHashTimerEntry *element = NULL; + HASH_FIND_INT(hashForTimers, &target, element); + if( element ) + return element->paused; + + // We should check update selectors if target does not have custom selectors + tHashUpdateEntry * elementUpdate = NULL; + HASH_FIND_INT(hashForUpdates, &target, elementUpdate); + if ( elementUpdate ) + return elementUpdate->entry->paused; + + return NO; // should never get here +} + +-(NSSet*) pauseAllTargets +{ + return [self pauseAllTargetsWithMinPriority:kCCPrioritySystem]; +} + +-(NSSet*) pauseAllTargetsWithMinPriority:(NSInteger)minPriority +{ + NSMutableSet* idsWithSelectors = [NSMutableSet setWithCapacity:50]; + + // Custom Selectors + for(tHashTimerEntry *element=hashForTimers; element != NULL; element=element->hh.next) { + element->paused = YES; + [idsWithSelectors addObject:element->target]; + } + + // Updates selectors + tListEntry *entry, *tmp; + if(minPriority < 0) { + DL_FOREACH_SAFE( updatesNeg, entry, tmp ) { + if(entry->priority >= minPriority) { + entry->paused = YES; + [idsWithSelectors addObject:entry->target]; + } + } + } + if(minPriority <= 0) { + DL_FOREACH_SAFE( updates0, entry, tmp ) { + entry->paused = YES; + [idsWithSelectors addObject:entry->target]; + } + } + DL_FOREACH_SAFE( updatesPos, entry, tmp ) { + if(entry->priority >= minPriority) { + entry->paused = YES; + [idsWithSelectors addObject:entry->target]; + } + } + + return idsWithSelectors; +} + +-(void) resumeTargets:(NSSet *)targetsToResume +{ + for(id target in targetsToResume) { + [self resumeTarget:target]; + } +} + +#pragma mark CCScheduler - Main Loop + +-(void) update: (ccTime) dt +{ + // all "dt" are going to be ignored if paused + if( _paused ) + return; + + updateHashLocked = YES; + + if( _timeScale != 1.0f ) + dt *= _timeScale; + + // Iterate all over the Updates selectors + tListEntry *entry, *tmp; + + // updates with priority < 0 + DL_FOREACH_SAFE( updatesNeg, entry, tmp ) { + if( ! entry->paused && !entry->markedForDeletion ) + entry->impMethod( entry->target, updateSelector, dt ); + } + + // updates with priority == 0 + DL_FOREACH_SAFE( updates0, entry, tmp ) { + if( ! entry->paused && !entry->markedForDeletion ) + { + entry->impMethod( entry->target, updateSelector, dt ); + } + } + + // updates with priority > 0 + DL_FOREACH_SAFE( updatesPos, entry, tmp ) { + if( ! entry->paused && !entry->markedForDeletion ) + entry->impMethod( entry->target, updateSelector, dt ); + } + + // Iterate all over the custom selectors (CCTimers) + for(tHashTimerEntry *elt=hashForTimers; elt != NULL; ) { + + currentTarget = elt; + currentTargetSalvaged = NO; + + if( ! currentTarget->paused ) { + + // The 'timers' ccArray may change while inside this loop. + for( elt->timerIndex = 0; elt->timerIndex < elt->timers->num; elt->timerIndex++) { + elt->currentTimer = elt->timers->arr[elt->timerIndex]; + elt->currentTimerSalvaged = NO; + + impMethod( elt->currentTimer, updateSelector, dt); + + if( elt->currentTimerSalvaged ) { + // The currentTimer told the remove itself. To prevent the timer from + // accidentally deallocating itself before finishing its step, we retained + // it. Now that step is done, it is safe to release it. + [elt->currentTimer release]; + } + + elt->currentTimer = nil; + } + } + + // elt, at this moment, is still valid + // so it is safe to ask this here (issue #490) + elt = elt->hh.next; + + // only delete currentTarget if no actions were scheduled during the cycle (issue #481) + if( currentTargetSalvaged && currentTarget->timers->num == 0 ) + [self removeHashElement:currentTarget]; + } + + // delete all updates that are morked for deletion + // updates with priority < 0 + DL_FOREACH_SAFE( updatesNeg, entry, tmp ) { + if(entry->markedForDeletion ) + { + [self removeUpdateFromHash:entry]; + } + } + + // updates with priority == 0 + DL_FOREACH_SAFE( updates0, entry, tmp ) { + if(entry->markedForDeletion ) + { + [self removeUpdateFromHash:entry]; + } + } + + // updates with priority > 0 + DL_FOREACH_SAFE( updatesPos, entry, tmp ) { + if(entry->markedForDeletion ) + { + [self removeUpdateFromHash:entry]; + } + } + + updateHashLocked = NO; + currentTarget = nil; +} +@end + diff --git "a/21451198\345\215\242\350\266\205/project5/MyPlane/libs/cocos2d/CCShaderCache.h" "b/21451198\345\215\242\350\266\205/project5/MyPlane/libs/cocos2d/CCShaderCache.h" new file mode 100644 index 00000000..2ee948b4 --- /dev/null +++ "b/21451198\345\215\242\350\266\205/project5/MyPlane/libs/cocos2d/CCShaderCache.h" @@ -0,0 +1,60 @@ +/* + * cocos2d for iPhone: http://www.cocos2d-iphone.org + * + * Copyright (c) 2008-2010 Ricardo Quesada + * Copyright (c) 2011 Zynga Inc. + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + * THE SOFTWARE. + */ + +#import +#import "ccMacros.h" +#ifdef __CC_PLATFORM_IOS +#import +#endif // __CC_PLATFORM_IOS + +@class CCGLProgram; + +/** CCShaderCache + Singleton that stores manages GL shaders + @since v2.0 + */ +@interface CCShaderCache : NSObject { + + NSMutableDictionary *_programs; + +} + +/** returns the shared instance */ ++ (CCShaderCache *)sharedShaderCache; + +/** purges the cache. It releases the retained instance. */ ++(void)purgeSharedShaderCache; + +/** loads the default shaders */ +-(void) loadDefaultShaders; + +/** returns a GL program for a given key */ +-(CCGLProgram *) programForKey:(NSString*)key; + +/** adds a CCGLProgram to the cache for a given name */ +- (void) addProgram:(CCGLProgram*)program forKey:(NSString*)key; + +@end + diff --git "a/21451198\345\215\242\350\266\205/project5/MyPlane/libs/cocos2d/CCShaderCache.m" "b/21451198\345\215\242\350\266\205/project5/MyPlane/libs/cocos2d/CCShaderCache.m" new file mode 100644 index 00000000..5478b5aa --- /dev/null +++ "b/21451198\345\215\242\350\266\205/project5/MyPlane/libs/cocos2d/CCShaderCache.m" @@ -0,0 +1,231 @@ +/* + * cocos2d for iPhone: http://www.cocos2d-iphone.org + * + * Copyright (c) 2011 Ricardo Quesada + * Copyright (c) 2011 Zynga Inc. + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + * THE SOFTWARE. + */ + +#import "CCShaderCache.h" +#import "ccShaders.h" +#import "CCGLProgram.h" +#import "ccMacros.h" +#import "Support/OpenGL_Internal.h" + +static CCShaderCache *_sharedShaderCache; + +@implementation CCShaderCache + +#pragma mark CCShaderCache - Alloc, Init & Dealloc + ++ (CCShaderCache *)sharedShaderCache +{ + if (!_sharedShaderCache) + _sharedShaderCache = [[CCShaderCache alloc] init]; + + return _sharedShaderCache; +} + ++(void)purgeSharedShaderCache +{ + [_sharedShaderCache release]; + _sharedShaderCache = nil; +} + + ++(id)alloc +{ + NSAssert(_sharedShaderCache == nil, @"Attempted to allocate a second instance of a singleton."); + return [super alloc]; +} + +- (void)dealloc +{ + CCLOGINFO(@"cocos2d deallocing %@", self); + + [_programs release]; + [super dealloc]; +} + ++(void)purgeSharedTextureCache +{ + [_sharedShaderCache release]; + _sharedShaderCache = nil; +} + +-(id) init +{ + if( (self=[super init]) ) { + _programs = [[NSMutableDictionary alloc ] initWithCapacity: 10]; + + [self loadDefaultShaders]; + } + + return self; +} + +-(void) loadDefaultShaders +{ + // Position Texture Color shader + CCGLProgram *p = [[CCGLProgram alloc] initWithVertexShaderByteArray:ccPositionTextureColor_vert + fragmentShaderByteArray:ccPositionTextureColor_frag]; + + [p addAttribute:kCCAttributeNamePosition index:kCCVertexAttrib_Position]; + [p addAttribute:kCCAttributeNameColor index:kCCVertexAttrib_Color]; + [p addAttribute:kCCAttributeNameTexCoord index:kCCVertexAttrib_TexCoords]; + + [p link]; + [p updateUniforms]; + + [_programs setObject:p forKey:kCCShader_PositionTextureColor]; + [p release]; + + CHECK_GL_ERROR_DEBUG(); + + // Position Texture Color alpha test + p = [[CCGLProgram alloc] initWithVertexShaderByteArray:ccPositionTextureColor_vert + fragmentShaderByteArray:ccPositionTextureColorAlphaTest_frag]; + + [p addAttribute:kCCAttributeNamePosition index:kCCVertexAttrib_Position]; + [p addAttribute:kCCAttributeNameColor index:kCCVertexAttrib_Color]; + [p addAttribute:kCCAttributeNameTexCoord index:kCCVertexAttrib_TexCoords]; + + [p link]; + [p updateUniforms]; + + [_programs setObject:p forKey:kCCShader_PositionTextureColorAlphaTest]; + [p release]; + + CHECK_GL_ERROR_DEBUG(); + + // + // Position, Color shader + // + p = [[CCGLProgram alloc] initWithVertexShaderByteArray:ccPositionColor_vert + fragmentShaderByteArray:ccPositionColor_frag]; + + [p addAttribute:kCCAttributeNamePosition index:kCCVertexAttrib_Position]; + [p addAttribute:kCCAttributeNameColor index:kCCVertexAttrib_Color]; + + [p link]; + [p updateUniforms]; + + [_programs setObject:p forKey:kCCShader_PositionColor]; + [p release]; + + CHECK_GL_ERROR_DEBUG(); + + // + // Position Texture shader + // + p = [[CCGLProgram alloc] initWithVertexShaderByteArray:ccPositionTexture_vert + fragmentShaderByteArray:ccPositionTexture_frag]; + + [p addAttribute:kCCAttributeNamePosition index:kCCVertexAttrib_Position]; + [p addAttribute:kCCAttributeNameTexCoord index:kCCVertexAttrib_TexCoords]; + + [p link]; + [p updateUniforms]; + + [_programs setObject:p forKey:kCCShader_PositionTexture]; + [p release]; + + CHECK_GL_ERROR_DEBUG(); + + // + // Position, Texture attribs, 1 Color as uniform shader + // + p = [[CCGLProgram alloc] initWithVertexShaderByteArray:ccPositionTexture_uColor_vert + fragmentShaderByteArray:ccPositionTexture_uColor_frag]; + + [p addAttribute:kCCAttributeNamePosition index:kCCVertexAttrib_Position]; + [p addAttribute:kCCAttributeNameTexCoord index:kCCVertexAttrib_TexCoords]; + + [p link]; + [p updateUniforms]; + + [_programs setObject:p forKey:kCCShader_PositionTexture_uColor]; + [p release]; + + CHECK_GL_ERROR_DEBUG(); + + // + // Position Texture A8 Color shader + // + p = [[CCGLProgram alloc] initWithVertexShaderByteArray:ccPositionTextureA8Color_vert + fragmentShaderByteArray:ccPositionTextureA8Color_frag]; + + [p addAttribute:kCCAttributeNamePosition index:kCCVertexAttrib_Position]; + [p addAttribute:kCCAttributeNameColor index:kCCVertexAttrib_Color]; + [p addAttribute:kCCAttributeNameTexCoord index:kCCVertexAttrib_TexCoords]; + + [p link]; + [p updateUniforms]; + + [_programs setObject:p forKey:kCCShader_PositionTextureA8Color]; + [p release]; + + CHECK_GL_ERROR_DEBUG(); + + // + // Position and 1 color passed as a uniform (to similate glColor4ub ) + // + p = [[CCGLProgram alloc] initWithVertexShaderByteArray:ccPosition_uColor_vert + fragmentShaderByteArray:ccPosition_uColor_frag]; + + [p addAttribute:@"aVertex" index:kCCVertexAttrib_Position]; + + [p link]; + [p updateUniforms]; + + [_programs setObject:p forKey:kCCShader_Position_uColor]; + [p release]; + + CHECK_GL_ERROR_DEBUG(); + + // + // Position, Legth(TexCoords, Color (used by Draw Node basically ) + // + p = [[CCGLProgram alloc] initWithVertexShaderByteArray:ccPositionColorLengthTexture_vert + fragmentShaderByteArray:ccPositionColorLengthTexture_frag]; + + [p addAttribute:kCCAttributeNamePosition index:kCCVertexAttrib_Position]; + [p addAttribute:kCCAttributeNameTexCoord index:kCCVertexAttrib_TexCoords]; + [p addAttribute:kCCAttributeNameColor index:kCCVertexAttrib_Color]; + + [p link]; + [p updateUniforms]; + + [_programs setObject:p forKey:kCCShader_PositionLengthTexureColor]; + [p release]; + CHECK_GL_ERROR_DEBUG(); +} + +-(CCGLProgram *) programForKey:(NSString*)key +{ + return [_programs objectForKey:key]; +} + +- (void) addProgram:(CCGLProgram*)program forKey:(NSString*)key +{ + [_programs setObject:program forKey:key]; +} + +@end diff --git "a/21451198\345\215\242\350\266\205/project5/MyPlane/libs/cocos2d/CCSprite.h" "b/21451198\345\215\242\350\266\205/project5/MyPlane/libs/cocos2d/CCSprite.h" new file mode 100644 index 00000000..f7b4dfcc --- /dev/null +++ "b/21451198\345\215\242\350\266\205/project5/MyPlane/libs/cocos2d/CCSprite.h" @@ -0,0 +1,281 @@ +/* + * cocos2d for iPhone: http://www.cocos2d-iphone.org + * + * Copyright (c) 2008-2010 Ricardo Quesada + * Copyright (c) 2011 Zynga Inc. + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + * THE SOFTWARE. + * + */ + + +#import "CCNode.h" +#import "CCProtocols.h" +#import "CCTextureAtlas.h" + +@class CCSpriteBatchNode; +@class CCSpriteFrame; +@class CCAnimation; + +#pragma mark CCSprite + +#define CCSpriteIndexNotInitialized 0xffffffff /// CCSprite invalid index on the CCSpriteBatchode + + +/** CCSprite is a 2d image ( http://en.wikipedia.org/wiki/Sprite_(computer_graphics) ) + * + * CCSprite can be created with an image, or with a sub-rectangle of an image. + * + * If the parent or any of its ancestors is a CCSpriteBatchNode then the following features/limitations are valid + * - Features when the parent is a CCBatchNode: + * - MUCH faster rendering, specially if the CCSpriteBatchNode has many children. All the children will be drawn in a single batch. + * + * - Limitations + * - Camera is not supported yet (eg: CCOrbitCamera action doesn't work) + * - GridBase actions are not supported (eg: CCLens, CCRipple, CCTwirl) + * - The Alias/Antialias property belongs to CCSpriteBatchNode, so you can't individually set the aliased property. + * - The Blending function property belongs to CCSpriteBatchNode, so you can't individually set the blending function property. + * - Parallax scroller is not supported, but can be simulated with a "proxy" sprite. + * + * If the parent is an standard CCNode, then CCSprite behaves like any other CCNode: + * - It supports blending functions + * - It supports aliasing / antialiasing + * - But the rendering will be slower: 1 draw per children. + * + * The default anchorPoint in CCSprite is (0.5, 0.5). + */ +@interface CCSprite : CCNodeRGBA +{ + + // + // Data used when the sprite is rendered using a CCSpriteBatchNode + // + CCTextureAtlas *_textureAtlas; // Sprite Sheet texture atlas (weak reference) + NSUInteger _atlasIndex; // Absolute (real) Index on the batch node + CCSpriteBatchNode *_batchNode; // Used batch node (weak reference) + CGAffineTransform _transformToBatch; // + BOOL _dirty; // Sprite needs to be updated + BOOL _recursiveDirty; // Subchildren needs to be updated + BOOL _hasChildren; // optimization to check if it contain children + BOOL _shouldBeHidden; // should not be drawn because one of the ancestors is not visible + + // + // Data used when the sprite is self-rendered + // + ccBlendFunc _blendFunc; // Needed for the texture protocol + CCTexture2D *_texture; // Texture used to render the sprite + + // + // Shared data + // + + // sprite rectangle + CGRect _rect; + + // texture + BOOL _rectRotated; + + // Offset Position (used by Zwoptex) + CGPoint _offsetPosition; + CGPoint _unflippedOffsetPositionFromCenter; + + // vertex coords, texture coords and color info + ccV3F_C4B_T2F_Quad _quad; + + // opacity and RGB protocol + BOOL _opacityModifyRGB; + + // image is flipped + BOOL _flipX; + BOOL _flipY; +} + +/** whether or not the Sprite needs to be updated in the Atlas */ +@property (nonatomic,readwrite) BOOL dirty; +/** the quad (tex coords, vertex coords and color) information */ +@property (nonatomic,readonly) ccV3F_C4B_T2F_Quad quad; +/** The index used on the TextureAtlas. Don't modify this value unless you know what you are doing */ +@property (nonatomic,readwrite) NSUInteger atlasIndex; +/** returns the texture rect of the CCSprite in points */ +@property (nonatomic,readonly) CGRect textureRect; +/** returns whether or not the texture rectangle is rotated */ +@property (nonatomic,readonly) BOOL textureRectRotated; +/** whether or not the sprite is flipped horizontally. + It only flips the texture of the sprite, and not the texture of the sprite's children. + Also, flipping the texture doesn't alter the anchorPoint. + If you want to flip the anchorPoint too, and/or to flip the children too use: + + sprite.scaleX *= -1; + */ +@property (nonatomic,readwrite) BOOL flipX; +/** whether or not the sprite is flipped vertically. + It only flips the texture of the sprite, and not the texture of the sprite's children. + Also, flipping the texture doesn't alter the anchorPoint. + If you want to flip the anchorPoint too, and/or to flip the children too use: + + sprite.scaleY *= -1; + */ +@property (nonatomic,readwrite) BOOL flipY; +/** weak reference of the CCTextureAtlas used when the sprite is rendered using a CCSpriteBatchNode */ +@property (nonatomic,readwrite,assign) CCTextureAtlas *textureAtlas; +/** weak reference to the CCSpriteBatchNode that renders the CCSprite */ +@property (nonatomic,readwrite,assign) CCSpriteBatchNode *batchNode; +/** offset position in points of the sprite in points. Calculated automatically by editors like Zwoptex. + @since v0.99.0 + */ +@property (nonatomic,readonly) CGPoint offsetPosition; +/** conforms to CCTextureProtocol protocol */ +@property (nonatomic,readwrite) ccBlendFunc blendFunc; + +#pragma mark CCSprite - Initializers + +/** Creates an sprite with a texture. + The rect used will be the size of the texture. + The offset will be (0,0). + */ ++(id) spriteWithTexture:(CCTexture2D*)texture; + +/** Creates an sprite with a texture and a rect. + The offset will be (0,0). + */ ++(id) spriteWithTexture:(CCTexture2D*)texture rect:(CGRect)rect; + +/** Creates an sprite with an sprite frame. + */ ++(id) spriteWithSpriteFrame:(CCSpriteFrame*)spriteFrame; + +/** Creates an sprite with an sprite frame name. + An CCSpriteFrame will be fetched from the CCSpriteFrameCache by name. + If the CCSpriteFrame doesn't exist it will raise an exception. + @since v0.9 + */ ++(id) spriteWithSpriteFrameName:(NSString*)spriteFrameName; + +/** Creates an sprite with an image filename. + The rect used will be the size of the image. + The offset will be (0,0). + */ ++(id) spriteWithFile:(NSString*)filename; + +/** Creates an sprite with an image filename and a rect. + The offset will be (0,0). + */ ++(id) spriteWithFile:(NSString*)filename rect:(CGRect)rect; + +/** Creates an sprite with a CGImageRef and a key. + The key is used by the CCTextureCache to know if a texture was already created with this CGImage. + For example, a valid key is: @"_spriteframe_01". + If key is nil, then a new texture will be created each time by the CCTextureCache. + @since v0.99.0 + */ ++(id) spriteWithCGImage: (CGImageRef)image key:(NSString*)key; + +/** Initializes an sprite with a texture. + The rect used will be the size of the texture. + The offset will be (0,0). + */ +-(id) initWithTexture:(CCTexture2D*)texture; + +/** Initializes an sprite with a texture and a rect in points (unrotated) + The offset will be (0,0). + */ +-(id) initWithTexture:(CCTexture2D*)texture rect:(CGRect)rect; + +/** Initializes an sprite with a texture and a rect in points, optionally rotated. + The offset will be (0,0). + IMPORTANT: This is the designated initializer. + */ +- (id)initWithTexture:(CCTexture2D *)texture rect:(CGRect)rect rotated:(BOOL)rotated; + + +/** Initializes an sprite with an sprite frame. + */ +-(id) initWithSpriteFrame:(CCSpriteFrame*)spriteFrame; + +/** Initializes an sprite with an sprite frame name. + An CCSpriteFrame will be fetched from the CCSpriteFrameCache by name. + If the CCSpriteFrame doesn't exist it will raise an exception. + @since v0.9 + */ +-(id) initWithSpriteFrameName:(NSString*)spriteFrameName; + +/** Initializes an sprite with an image filename. + The rect used will be the size of the image. + The offset will be (0,0). + */ +-(id) initWithFile:(NSString*)filename; + +/** Initializes an sprite with an image filename, and a rect. + The offset will be (0,0). + */ +-(id) initWithFile:(NSString*)filename rect:(CGRect)rect; + +/** Initializes an sprite with a CGImageRef and a key + The key is used by the CCTextureCache to know if a texture was already created with this CGImage. + For example, a valid key is: @"_spriteframe_01". + If key is nil, then a new texture will be created each time by the CCTextureCache. + @since v0.99.0 + */ +-(id) initWithCGImage:(CGImageRef)image key:(NSString*)key; + +#pragma mark CCSprite - BatchNode methods + +/** updates the quad according the the rotation, position, scale values. + */ +-(void)updateTransform; + +#pragma mark CCSprite - Texture methods + +/** set the texture rect of the CCSprite in points. + It will call setTextureRect:rotated:untrimmedSize with rotated = NO, and utrimmedSize = rect.size. + */ +-(void) setTextureRect:(CGRect) rect; + +/** set the texture rect, rectRotated and untrimmed size of the CCSprite in points. + It will update the texture coordinates and the vertex rectangle. + */ +-(void) setTextureRect:(CGRect)rect rotated:(BOOL)rotated untrimmedSize:(CGSize)size; + +/** set the vertex rect. + It will be called internally by setTextureRect. Useful if you want to create 2x images from SD images in Retina Display. + Do not call it manually. Use setTextureRect instead. + */ +-(void)setVertexRect:(CGRect)rect; + + +#pragma mark CCSprite - Frames + +/** sets a new display frame to the CCSprite. */ +-(void) setDisplayFrame:(CCSpriteFrame*)newFrame; + +/** returns whether or not a CCSpriteFrame is being displayed */ +-(BOOL) isFrameDisplayed:(CCSpriteFrame*)frame; + +/** returns the current displayed frame. */ +-(CCSpriteFrame*) displayFrame; + +#pragma mark CCSprite - Animation + +/** changes the display frame with animation name and index. + The animation name will be get from the CCAnimationCache + @since v0.99.5 + */ +-(void) setDisplayFrameWithAnimationName:(NSString*)animationName index:(int) frameIndex; + +@end diff --git "a/21451198\345\215\242\350\266\205/project5/MyPlane/libs/cocos2d/CCSprite.m" "b/21451198\345\215\242\350\266\205/project5/MyPlane/libs/cocos2d/CCSprite.m" new file mode 100644 index 00000000..b5f74acc --- /dev/null +++ "b/21451198\345\215\242\350\266\205/project5/MyPlane/libs/cocos2d/CCSprite.m" @@ -0,0 +1,959 @@ +/* + * cocos2d for iPhone: http://www.cocos2d-iphone.org + * + * Copyright (c) 2008-2010 Ricardo Quesada + * Copyright (c) 2011 Zynga Inc. + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + * THE SOFTWARE. + * + */ + +#import "ccConfig.h" +#import "CCSpriteBatchNode.h" +#import "CCSprite.h" +#import "CCSpriteFrame.h" +#import "CCSpriteFrameCache.h" +#import "CCAnimation.h" +#import "CCAnimationCache.h" +#import "CCTextureCache.h" +#import "CCDrawingPrimitives.h" +#import "CCShaderCache.h" +#import "ccGLStateCache.h" +#import "CCGLProgram.h" +#import "CCDirector.h" +#import "Support/CGPointExtension.h" +#import "Support/TransformUtils.h" +#import "Support/CCProfiling.h" +#import "Support/OpenGL_Internal.h" + +// external +#import "kazmath/GL/matrix.h" + +#pragma mark - +#pragma mark CCSprite + +#if CC_SPRITEBATCHNODE_RENDER_SUBPIXEL +#define RENDER_IN_SUBPIXEL +#else +#define RENDER_IN_SUBPIXEL(__ARGS__) (ceil(__ARGS__)) +#endif + + +@interface CCSprite () +-(void) setTextureCoords:(CGRect)rect; +-(void) updateBlendFunc; +-(void) setReorderChildDirtyRecursively; +@end + +@implementation CCSprite + +@synthesize dirty = _dirty; +@synthesize quad = _quad; +@synthesize atlasIndex = _atlasIndex; +@synthesize textureRect = _rect; +@synthesize textureRectRotated = _rectRotated; +@synthesize blendFunc = _blendFunc; +@synthesize textureAtlas = _textureAtlas; +@synthesize offsetPosition = _offsetPosition; + + ++(id)spriteWithTexture:(CCTexture2D*)texture +{ + return [[[self alloc] initWithTexture:texture] autorelease]; +} + ++(id)spriteWithTexture:(CCTexture2D*)texture rect:(CGRect)rect +{ + return [[[self alloc] initWithTexture:texture rect:rect] autorelease]; +} + ++(id)spriteWithFile:(NSString*)filename +{ + return [[[self alloc] initWithFile:filename] autorelease]; +} + ++(id)spriteWithFile:(NSString*)filename rect:(CGRect)rect +{ + return [[[self alloc] initWithFile:filename rect:rect] autorelease]; +} + ++(id)spriteWithSpriteFrame:(CCSpriteFrame*)spriteFrame +{ + return [[[self alloc] initWithSpriteFrame:spriteFrame] autorelease]; +} + ++(id)spriteWithSpriteFrameName:(NSString*)spriteFrameName +{ + CCSpriteFrame *frame = [[CCSpriteFrameCache sharedSpriteFrameCache] spriteFrameByName:spriteFrameName]; + + NSAssert1(frame!=nil, @"Invalid spriteFrameName: %@", spriteFrameName); + return [self spriteWithSpriteFrame:frame]; +} + ++(id)spriteWithCGImage:(CGImageRef)image key:(NSString*)key +{ + return [[[self alloc] initWithCGImage:image key:key] autorelease]; +} + +-(id) init +{ + return [self initWithTexture:nil rect:CGRectZero]; +} + +// designated initializer +-(id) initWithTexture:(CCTexture2D*)texture rect:(CGRect)rect rotated:(BOOL)rotated +{ + if( (self = [super init]) ) + { + // shader program + self.shaderProgram = [[CCShaderCache sharedShaderCache] programForKey:kCCShader_PositionTextureColor]; + + _dirty = _recursiveDirty = NO; + + _opacityModifyRGB = YES; + + _blendFunc.src = CC_BLEND_SRC; + _blendFunc.dst = CC_BLEND_DST; + + _flipY = _flipX = NO; + + // default transform anchor: center + _anchorPoint = ccp(0.5f, 0.5f); + + // zwoptex default values + _offsetPosition = CGPointZero; + + _hasChildren = NO; + _batchNode = nil; + + // clean the Quad + bzero(&_quad, sizeof(_quad)); + + // Atlas: Color + ccColor4B tmpColor = {255,255,255,255}; + _quad.bl.colors = tmpColor; + _quad.br.colors = tmpColor; + _quad.tl.colors = tmpColor; + _quad.tr.colors = tmpColor; + + [self setTexture:texture]; + [self setTextureRect:rect rotated:rotated untrimmedSize:rect.size]; + + + // by default use "Self Render". + // if the sprite is added to a batchnode, then it will automatically switch to "batchnode Render" + [self setBatchNode:nil]; + + } + return self; +} + +-(id) initWithTexture:(CCTexture2D*)texture rect:(CGRect)rect +{ + return [self initWithTexture:texture rect:rect rotated:NO]; +} + +-(id) initWithTexture:(CCTexture2D*)texture +{ + NSAssert(texture!=nil, @"Invalid texture for sprite"); + + CGRect rect = CGRectZero; + rect.size = texture.contentSize; + return [self initWithTexture:texture rect:rect]; +} + +-(id) initWithFile:(NSString*)filename +{ + NSAssert(filename != nil, @"Invalid filename for sprite"); + + CCTexture2D *texture = [[CCTextureCache sharedTextureCache] addImage: filename]; + if( texture ) { + CGRect rect = CGRectZero; + rect.size = texture.contentSize; + return [self initWithTexture:texture rect:rect]; + } + + [self release]; + return nil; +} + +-(id) initWithFile:(NSString*)filename rect:(CGRect)rect +{ + NSAssert(filename!=nil, @"Invalid filename for sprite"); + + CCTexture2D *texture = [[CCTextureCache sharedTextureCache] addImage: filename]; + if( texture ) + return [self initWithTexture:texture rect:rect]; + + [self release]; + return nil; +} + +- (id) initWithSpriteFrame:(CCSpriteFrame*)spriteFrame +{ + NSAssert(spriteFrame!=nil, @"Invalid spriteFrame for sprite"); + + id ret = [self initWithTexture:spriteFrame.texture rect:spriteFrame.rect]; + [self setDisplayFrame:spriteFrame]; + return ret; +} + +-(id)initWithSpriteFrameName:(NSString*)spriteFrameName +{ + NSAssert(spriteFrameName!=nil, @"Invalid spriteFrameName for sprite"); + + CCSpriteFrame *frame = [[CCSpriteFrameCache sharedSpriteFrameCache] spriteFrameByName:spriteFrameName]; + return [self initWithSpriteFrame:frame]; +} + +- (id) initWithCGImage:(CGImageRef)image key:(NSString*)key +{ + NSAssert(image!=nil, @"Invalid CGImageRef for sprite"); + + // XXX: possible bug. See issue #349. New API should be added + CCTexture2D *texture = [[CCTextureCache sharedTextureCache] addCGImage:image forKey:key]; + + CGRect rect = CGRectZero; + rect.size = texture.contentSize; + + return [self initWithTexture:texture rect:rect]; +} + +- (NSString*) description +{ + return [NSString stringWithFormat:@"<%@ = %p | Rect = (%.2f,%.2f,%.2f,%.2f) | tag = %ld | atlasIndex = %ld>", [self class], self, + _rect.origin.x, _rect.origin.y, _rect.size.width, _rect.size.height, + (long)_tag, + (unsigned long)_atlasIndex + ]; +} + +- (void) dealloc +{ + [_texture release]; + [super dealloc]; +} + +-(CCSpriteBatchNode*) batchNode +{ + return _batchNode; +} + +-(void) setBatchNode:(CCSpriteBatchNode *)batchNode +{ + _batchNode = batchNode; // weak reference + + // self render + if( ! batchNode ) { + _atlasIndex = CCSpriteIndexNotInitialized; + _textureAtlas = nil; + _dirty = _recursiveDirty = NO; + + float x1 = _offsetPosition.x; + float y1 = _offsetPosition.y; + float x2 = x1 + _rect.size.width; + float y2 = y1 + _rect.size.height; + _quad.bl.vertices = (ccVertex3F) { x1, y1, 0 }; + _quad.br.vertices = (ccVertex3F) { x2, y1, 0 }; + _quad.tl.vertices = (ccVertex3F) { x1, y2, 0 }; + _quad.tr.vertices = (ccVertex3F) { x2, y2, 0 }; + + } else { + + // using batch + _transformToBatch = CGAffineTransformIdentity; + _textureAtlas = [batchNode textureAtlas]; // weak ref + } +} + +-(void) setTextureRect:(CGRect)rect +{ + [self setTextureRect:rect rotated:NO untrimmedSize:rect.size]; +} + +-(void) setTextureRect:(CGRect)rect rotated:(BOOL)rotated untrimmedSize:(CGSize)untrimmedSize +{ + _rectRotated = rotated; + + [self setContentSize:untrimmedSize]; + [self setVertexRect:rect]; + [self setTextureCoords:rect]; + + CGPoint relativeOffset = _unflippedOffsetPositionFromCenter; + + // issue #732 + if( _flipX ) + relativeOffset.x = -relativeOffset.x; + if( _flipY ) + relativeOffset.y = -relativeOffset.y; + + + _offsetPosition.x = relativeOffset.x + (_contentSize.width - _rect.size.width) / 2; + _offsetPosition.y = relativeOffset.y + (_contentSize.height - _rect.size.height) / 2; + + + // rendering using batch node + if( _batchNode ) { + // update _dirty, don't update _recursiveDirty + _dirty = YES; + } + + // self rendering + else + { + // Atlas: Vertex + float x1 = _offsetPosition.x; + float y1 = _offsetPosition.y; + float x2 = x1 + _rect.size.width; + float y2 = y1 + _rect.size.height; + + // Don't update Z. + _quad.bl.vertices = (ccVertex3F) { x1, y1, 0 }; + _quad.br.vertices = (ccVertex3F) { x2, y1, 0 }; + _quad.tl.vertices = (ccVertex3F) { x1, y2, 0 }; + _quad.tr.vertices = (ccVertex3F) { x2, y2, 0 }; + } +} + +// override this method to generate "double scale" sprites +-(void) setVertexRect:(CGRect)rect +{ + _rect = rect; +} + +-(void) setTextureCoords:(CGRect)rect +{ + rect = CC_RECT_POINTS_TO_PIXELS(rect); + + CCTexture2D *tex = (_batchNode) ? [_textureAtlas texture] : _texture; + if(!tex) + return; + + float atlasWidth = (float)tex.pixelsWide; + float atlasHeight = (float)tex.pixelsHigh; + + float left, right ,top , bottom; + + if(_rectRotated) + { +#if CC_FIX_ARTIFACTS_BY_STRECHING_TEXEL + left = (2*rect.origin.x+1)/(2*atlasWidth); + right = left+(rect.size.height*2-2)/(2*atlasWidth); + top = (2*rect.origin.y+1)/(2*atlasHeight); + bottom = top+(rect.size.width*2-2)/(2*atlasHeight); +#else + left = rect.origin.x/atlasWidth; + right = (rect.origin.x+rect.size.height) / atlasWidth; + top = rect.origin.y/atlasHeight; + bottom = (rect.origin.y+rect.size.width) / atlasHeight; +#endif // ! CC_FIX_ARTIFACTS_BY_STRECHING_TEXEL + + if( _flipX) + CC_SWAP(top,bottom); + if( _flipY) + CC_SWAP(left,right); + + _quad.bl.texCoords.u = left; + _quad.bl.texCoords.v = top; + _quad.br.texCoords.u = left; + _quad.br.texCoords.v = bottom; + _quad.tl.texCoords.u = right; + _quad.tl.texCoords.v = top; + _quad.tr.texCoords.u = right; + _quad.tr.texCoords.v = bottom; + } else { +#if CC_FIX_ARTIFACTS_BY_STRECHING_TEXEL + left = (2*rect.origin.x+1)/(2*atlasWidth); + right = left + (rect.size.width*2-2)/(2*atlasWidth); + top = (2*rect.origin.y+1)/(2*atlasHeight); + bottom = top + (rect.size.height*2-2)/(2*atlasHeight); +#else + left = rect.origin.x/atlasWidth; + right = (rect.origin.x + rect.size.width) / atlasWidth; + top = rect.origin.y/atlasHeight; + bottom = (rect.origin.y + rect.size.height) / atlasHeight; +#endif // ! CC_FIX_ARTIFACTS_BY_STRECHING_TEXEL + + if( _flipX) + CC_SWAP(left,right); + if( _flipY) + CC_SWAP(top,bottom); + + _quad.bl.texCoords.u = left; + _quad.bl.texCoords.v = bottom; + _quad.br.texCoords.u = right; + _quad.br.texCoords.v = bottom; + _quad.tl.texCoords.u = left; + _quad.tl.texCoords.v = top; + _quad.tr.texCoords.u = right; + _quad.tr.texCoords.v = top; + } +} + +-(void)updateTransform +{ + NSAssert( _batchNode, @"updateTransform is only valid when CCSprite is being rendered using an CCSpriteBatchNode"); + + // recaculate matrix only if it is dirty + if( self.dirty ) { + + // If it is not visible, or one of its ancestors is not visible, then do nothing: + if( !_visible || ( _parent && _parent != _batchNode && ((CCSprite*)_parent)->_shouldBeHidden) ) { + _quad.br.vertices = _quad.tl.vertices = _quad.tr.vertices = _quad.bl.vertices = (ccVertex3F){0,0,0}; + _shouldBeHidden = YES; + } + + else { + + _shouldBeHidden = NO; + + if( ! _parent || _parent == _batchNode ) + _transformToBatch = [self nodeToParentTransform]; + + else { + NSAssert( [_parent isKindOfClass:[CCSprite class]], @"Logic error in CCSprite. Parent must be a CCSprite"); + + _transformToBatch = CGAffineTransformConcat( [self nodeToParentTransform] , ((CCSprite*)_parent)->_transformToBatch ); + } + + // + // calculate the Quad based on the Affine Matrix + // + + CGSize size = _rect.size; + + float x1 = _offsetPosition.x; + float y1 = _offsetPosition.y; + + float x2 = x1 + size.width; + float y2 = y1 + size.height; + float x = _transformToBatch.tx; + float y = _transformToBatch.ty; + + float cr = _transformToBatch.a; + float sr = _transformToBatch.b; + float cr2 = _transformToBatch.d; + float sr2 = -_transformToBatch.c; + float ax = x1 * cr - y1 * sr2 + x; + float ay = x1 * sr + y1 * cr2 + y; + + float bx = x2 * cr - y1 * sr2 + x; + float by = x2 * sr + y1 * cr2 + y; + + float cx = x2 * cr - y2 * sr2 + x; + float cy = x2 * sr + y2 * cr2 + y; + + float dx = x1 * cr - y2 * sr2 + x; + float dy = x1 * sr + y2 * cr2 + y; + + _quad.bl.vertices = (ccVertex3F) { RENDER_IN_SUBPIXEL(ax), RENDER_IN_SUBPIXEL(ay), _vertexZ }; + _quad.br.vertices = (ccVertex3F) { RENDER_IN_SUBPIXEL(bx), RENDER_IN_SUBPIXEL(by), _vertexZ }; + _quad.tl.vertices = (ccVertex3F) { RENDER_IN_SUBPIXEL(dx), RENDER_IN_SUBPIXEL(dy), _vertexZ }; + _quad.tr.vertices = (ccVertex3F) { RENDER_IN_SUBPIXEL(cx), RENDER_IN_SUBPIXEL(cy), _vertexZ }; + } + + [_textureAtlas updateQuad:&_quad atIndex:_atlasIndex]; + _dirty = _recursiveDirty = NO; + } + + // recursively iterate over children + if( _hasChildren ) + [_children makeObjectsPerformSelector:@selector(updateTransform)]; + +#if CC_SPRITE_DEBUG_DRAW + // draw bounding box + CGPoint vertices[4] = { + ccp( _quad.bl.vertices.x, _quad.bl.vertices.y ), + ccp( _quad.br.vertices.x, _quad.br.vertices.y ), + ccp( _quad.tr.vertices.x, _quad.tr.vertices.y ), + ccp( _quad.tl.vertices.x, _quad.tl.vertices.y ), + }; + ccDrawPoly(vertices, 4, YES); +#endif // CC_SPRITE_DEBUG_DRAW + +} + +#pragma mark CCSprite - draw + +-(void) draw +{ + CC_PROFILER_START_CATEGORY(kCCProfilerCategorySprite, @"CCSprite - draw"); + + NSAssert(!_batchNode, @"If CCSprite is being rendered by CCSpriteBatchNode, CCSprite#draw SHOULD NOT be called"); + + CC_NODE_DRAW_SETUP(); + + ccGLBlendFunc( _blendFunc.src, _blendFunc.dst ); + + ccGLBindTexture2D( [_texture name] ); + + // + // Attributes + // + + ccGLEnableVertexAttribs( kCCVertexAttribFlag_PosColorTex ); + +#define kQuadSize sizeof(_quad.bl) + long offset = (long)&_quad; + + // vertex + NSInteger diff = offsetof( ccV3F_C4B_T2F, vertices); + glVertexAttribPointer(kCCVertexAttrib_Position, 3, GL_FLOAT, GL_FALSE, kQuadSize, (void*) (offset + diff)); + + // texCoods + diff = offsetof( ccV3F_C4B_T2F, texCoords); + glVertexAttribPointer(kCCVertexAttrib_TexCoords, 2, GL_FLOAT, GL_FALSE, kQuadSize, (void*)(offset + diff)); + + // color + diff = offsetof( ccV3F_C4B_T2F, colors); + glVertexAttribPointer(kCCVertexAttrib_Color, 4, GL_UNSIGNED_BYTE, GL_TRUE, kQuadSize, (void*)(offset + diff)); + + + glDrawArrays(GL_TRIANGLE_STRIP, 0, 4); + + CHECK_GL_ERROR_DEBUG(); + + +#if CC_SPRITE_DEBUG_DRAW == 1 + // draw bounding box + CGPoint vertices[4]={ + ccp(_quad.tl.vertices.x,_quad.tl.vertices.y), + ccp(_quad.bl.vertices.x,_quad.bl.vertices.y), + ccp(_quad.br.vertices.x,_quad.br.vertices.y), + ccp(_quad.tr.vertices.x,_quad.tr.vertices.y), + }; + ccDrawPoly(vertices, 4, YES); +#elif CC_SPRITE_DEBUG_DRAW == 2 + // draw texture box + CGSize s = self.textureRect.size; + CGPoint offsetPix = self.offsetPosition; + CGPoint vertices[4] = { + ccp(offsetPix.x,offsetPix.y), ccp(offsetPix.x+s.width,offsetPix.y), + ccp(offsetPix.x+s.width,offsetPix.y+s.height), ccp(offsetPix.x,offsetPix.y+s.height) + }; + ccDrawPoly(vertices, 4, YES); +#endif // CC_SPRITE_DEBUG_DRAW + + CC_INCREMENT_GL_DRAWS(1); + + CC_PROFILER_STOP_CATEGORY(kCCProfilerCategorySprite, @"CCSprite - draw"); +} + +#pragma mark CCSprite - CCNode overrides + +-(void) addChild:(CCSprite*)child z:(NSInteger)z tag:(NSInteger) aTag +{ + NSAssert( child != nil, @"Argument must be non-nil"); + + if( _batchNode ) { + NSAssert( [child isKindOfClass:[CCSprite class]], @"CCSprite only supports CCSprites as children when using CCSpriteBatchNode"); + NSAssert( child.texture.name == _textureAtlas.texture.name, @"CCSprite is not using the same texture id"); + + //put it in descendants array of batch node + [_batchNode appendChild:child]; + + if (!_isReorderChildDirty) + [self setReorderChildDirtyRecursively]; + } + + //CCNode already sets _isReorderChildDirty so this needs to be after batchNode check + [super addChild:child z:z tag:aTag]; + + _hasChildren = YES; +} + +-(void) reorderChild:(CCSprite*)child z:(NSInteger)z +{ + NSAssert( child != nil, @"Child must be non-nil"); + NSAssert( [_children containsObject:child], @"Child doesn't belong to Sprite" ); + + if( z == child.zOrder ) + return; + + if( _batchNode && ! _isReorderChildDirty) + { + [self setReorderChildDirtyRecursively]; + [_batchNode reorderBatch:YES]; + } + + [super reorderChild:child z:z]; +} + +-(void)removeChild: (CCSprite *)sprite cleanup:(BOOL)doCleanup +{ + if( _batchNode ) + [_batchNode removeSpriteFromAtlas:sprite]; + + [super removeChild:sprite cleanup:doCleanup]; + + _hasChildren = ( [_children count] > 0 ); +} + +-(void)removeAllChildrenWithCleanup:(BOOL)doCleanup +{ + if( _batchNode ) { + CCSprite *child; + CCARRAY_FOREACH(_children, child) + [_batchNode removeSpriteFromAtlas:child]; + } + + [super removeAllChildrenWithCleanup:doCleanup]; + + _hasChildren = NO; +} + +- (void) sortAllChildren +{ + if (_isReorderChildDirty) + { + NSInteger i,j,length = _children->data->num; + CCNode** x = _children->data->arr; + CCNode *tempItem; + + // insertion sort + for(i=1; i=0 && ( tempItem.zOrder < x[j].zOrder || ( tempItem.zOrder == x[j].zOrder && tempItem.orderOfArrival < x[j].orderOfArrival ) ) ) + { + x[j+1] = x[j]; + j = j-1; + } + x[j+1] = tempItem; + } + + if ( _batchNode) + [_children makeObjectsPerformSelector:@selector(sortAllChildren)]; + + _isReorderChildDirty=NO; + } +} + +// +// CCNode property overloads +// used only when parent is CCSpriteBatchNode +// +#pragma mark CCSprite - property overloads + +-(void) setReorderChildDirtyRecursively +{ + //only set parents flag the first time + + if ( ! _isReorderChildDirty ) + { + _isReorderChildDirty = YES; + CCNode* node = (CCNode*) _parent; + while (node && node != _batchNode) + { + [(CCSprite*)node setReorderChildDirtyRecursively]; + node=node.parent; + } + } +} + +-(void) setDirtyRecursively:(BOOL)b +{ + _dirty = _recursiveDirty = b; + // recursively set dirty + if( _hasChildren ) { + CCSprite *child; + CCARRAY_FOREACH(_children, child) + [child setDirtyRecursively:YES]; + } +} + +// XXX HACK: optimization +#define SET_DIRTY_RECURSIVELY() { \ + if( _batchNode && ! _recursiveDirty ) { \ + _dirty = _recursiveDirty = YES; \ + if( _hasChildren) \ + [self setDirtyRecursively:YES]; \ + } \ + } + +-(void)setPosition:(CGPoint)pos +{ + [super setPosition:pos]; + SET_DIRTY_RECURSIVELY(); +} + +-(void)setRotation:(float)rot +{ + [super setRotation:rot]; + SET_DIRTY_RECURSIVELY(); +} + +-(void)setRotationX:(float)rot +{ + [super setRotationX:rot]; + SET_DIRTY_RECURSIVELY(); +} + +-(void)setRotationY:(float)rot +{ + [super setRotationY:rot]; + SET_DIRTY_RECURSIVELY(); +} + +-(void)setSkewX:(float)sx +{ + [super setSkewX:sx]; + SET_DIRTY_RECURSIVELY(); +} + +-(void)setSkewY:(float)sy +{ + [super setSkewY:sy]; + SET_DIRTY_RECURSIVELY(); +} + +-(void)setScaleX:(float) sx +{ + [super setScaleX:sx]; + SET_DIRTY_RECURSIVELY(); +} + +-(void)setScaleY:(float) sy +{ + [super setScaleY:sy]; + SET_DIRTY_RECURSIVELY(); +} + +-(void)setScale:(float) s +{ + [super setScale:s]; + SET_DIRTY_RECURSIVELY(); +} + +-(void) setVertexZ:(float)z +{ + [super setVertexZ:z]; + SET_DIRTY_RECURSIVELY(); +} + +-(void)setAnchorPoint:(CGPoint)anchor +{ + [super setAnchorPoint:anchor]; + SET_DIRTY_RECURSIVELY(); +} + +-(void) setIgnoreAnchorPointForPosition:(BOOL)value +{ + NSAssert( ! _batchNode, @"ignoreAnchorPointForPosition is invalid in CCSprite"); + [super setIgnoreAnchorPointForPosition:value]; +} + +-(void)setVisible:(BOOL)v +{ + [super setVisible:v]; + SET_DIRTY_RECURSIVELY(); +} + +-(void)setFlipX:(BOOL)b +{ + if( _flipX != b ) { + _flipX = b; + [self setTextureRect:_rect rotated:_rectRotated untrimmedSize:_contentSize]; + } +} +-(BOOL) flipX +{ + return _flipX; +} + +-(void) setFlipY:(BOOL)b +{ + if( _flipY != b ) { + _flipY = b; + [self setTextureRect:_rect rotated:_rectRotated untrimmedSize:_contentSize]; + } +} +-(BOOL) flipY +{ + return _flipY; +} + +// +// RGBA protocol +// +#pragma mark CCSprite - RGBA protocol +-(void) updateColor +{ + ccColor4B color4 = {_displayedColor.r, _displayedColor.g, _displayedColor.b, _displayedOpacity}; + + + // special opacity for premultiplied textures + if ( _opacityModifyRGB ) { + color4.r *= _displayedOpacity/255.0f; + color4.g *= _displayedOpacity/255.0f; + color4.b *= _displayedOpacity/255.0f; + } + + _quad.bl.colors = color4; + _quad.br.colors = color4; + _quad.tl.colors = color4; + _quad.tr.colors = color4; + + // renders using batch node + if( _batchNode ) { + if( _atlasIndex != CCSpriteIndexNotInitialized) + [_textureAtlas updateQuad:&_quad atIndex:_atlasIndex]; + else + // no need to set it recursively + // update _dirty, don't update _recursiveDirty + _dirty = YES; + } + // self render + // do nothing +} + +-(void) setColor:(ccColor3B)color3 +{ + [super setColor:color3]; + [self updateColor]; +} + +-(void)updateDisplayedColor:(ccColor3B)parentColor +{ + [super updateDisplayedColor:parentColor]; + [self updateColor]; +} + +-(void) setOpacity:(GLubyte)opacity +{ + [super setOpacity:opacity]; + [self updateColor]; +} + +-(void) setOpacityModifyRGB:(BOOL)modify +{ + if( _opacityModifyRGB != modify ) { + _opacityModifyRGB = modify; + [self updateColor]; + } +} + +-(BOOL) doesOpacityModifyRGB +{ + return _opacityModifyRGB; +} + +-(void)updateDisplayedOpacity:(GLubyte)parentOpacity +{ + [super updateDisplayedOpacity:parentOpacity]; + [self updateColor]; +} + + +// +// Frames +// +#pragma mark CCSprite - Frames + +-(void) setDisplayFrame:(CCSpriteFrame*)frame +{ + _unflippedOffsetPositionFromCenter = frame.offset; + + CCTexture2D *newTexture = [frame texture]; + // update texture before updating texture rect + if ( newTexture.name != _texture.name ) + [self setTexture: newTexture]; + + // update rect + _rectRotated = frame.rotated; + + [self setTextureRect:frame.rect rotated:_rectRotated untrimmedSize:frame.originalSize]; +} + +-(void) setDisplayFrameWithAnimationName: (NSString*) animationName index:(int) frameIndex +{ + NSAssert( animationName, @"CCSprite#setDisplayFrameWithAnimationName. animationName must not be nil"); + + CCAnimation *a = [[CCAnimationCache sharedAnimationCache] animationByName:animationName]; + + NSAssert( a, @"CCSprite#setDisplayFrameWithAnimationName: Frame not found"); + + CCAnimationFrame *frame = [[a frames] objectAtIndex:frameIndex]; + + NSAssert( frame, @"CCSprite#setDisplayFrame. Invalid frame"); + + [self setDisplayFrame:frame.spriteFrame]; +} + + +-(BOOL) isFrameDisplayed:(CCSpriteFrame*)frame +{ + CGRect r = [frame rect]; + return ( CGRectEqualToRect(r, _rect) && + frame.texture.name == self.texture.name && + CGPointEqualToPoint( frame.offset, _unflippedOffsetPositionFromCenter ) ); +} + +-(CCSpriteFrame*) displayFrame +{ + return [CCSpriteFrame frameWithTexture:_texture + rectInPixels:CC_RECT_POINTS_TO_PIXELS(_rect) + rotated:_rectRotated + offset:CC_POINT_POINTS_TO_PIXELS(_unflippedOffsetPositionFromCenter) + originalSize:CC_SIZE_POINTS_TO_PIXELS(_contentSize)]; +} + +#pragma mark CCSprite - CocosNodeTexture protocol + +-(void) updateBlendFunc +{ + NSAssert( ! _batchNode, @"CCSprite: updateBlendFunc doesn't work when the sprite is rendered using a CCSpriteBatchNode"); + + // it is possible to have an untextured sprite + if( !_texture || ! [_texture hasPremultipliedAlpha] ) { + _blendFunc.src = GL_SRC_ALPHA; + _blendFunc.dst = GL_ONE_MINUS_SRC_ALPHA; + [self setOpacityModifyRGB:NO]; + } else { + _blendFunc.src = CC_BLEND_SRC; + _blendFunc.dst = CC_BLEND_DST; + [self setOpacityModifyRGB:YES]; + } +} + +-(void) setTexture:(CCTexture2D*)texture +{ + // If batchnode, then texture id should be the same + NSAssert( !_batchNode || texture.name == _batchNode.texture.name , @"CCSprite: Batched sprites should use the same texture as the batchnode"); + + // accept texture==nil as argument + NSAssert( !texture || [texture isKindOfClass:[CCTexture2D class]], @"setTexture expects a CCTexture2D. Invalid argument"); + + if( ! _batchNode && _texture != texture ) { + [_texture release]; + _texture = [texture retain]; + + [self updateBlendFunc]; + } +} + +-(CCTexture2D*) texture +{ + return _texture; +} + +@end diff --git "a/21451198\345\215\242\350\266\205/project5/MyPlane/libs/cocos2d/CCSpriteBatchNode.h" "b/21451198\345\215\242\350\266\205/project5/MyPlane/libs/cocos2d/CCSpriteBatchNode.h" new file mode 100644 index 00000000..7133101a --- /dev/null +++ "b/21451198\345\215\242\350\266\205/project5/MyPlane/libs/cocos2d/CCSpriteBatchNode.h" @@ -0,0 +1,145 @@ +/* + * cocos2d for iPhone: http://www.cocos2d-iphone.org + * + * Copyright (C) 2009 Matt Oswald + * + * Copyright (c) 2009-2010 Ricardo Quesada + * Copyright (c) 2011 Zynga Inc. + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + * THE SOFTWARE. + * + */ + + +#import "CCNode.h" +#import "CCProtocols.h" +#import "CCTextureAtlas.h" +#import "ccMacros.h" + +#pragma mark CCSpriteBatchNode + +@class CCSprite; + +/** CCSpriteBatchNode is like a batch node: if it contains children, it will draw them in 1 single OpenGL call + * (often known as "batch draw"). + * + * A CCSpriteBatchNode can reference one and only one texture (one image file, one texture atlas). + * Only the CCSprites that are contained in that texture can be added to the CCSpriteBatchNode. + * All CCSprites added to a CCSpriteBatchNode are drawn in one OpenGL ES draw call. + * If the CCSprites are not added to a CCSpriteBatchNode then an OpenGL ES draw call will be needed for each one, which is less efficient. + * + * + * Limitations: + * - The only object that is accepted as child (or grandchild, grand-grandchild, etc...) is CCSprite or any subclass of CCSprite. eg: particles, labels and layer can't be added to a CCSpriteBatchNode. + * - Either all its children are Aliased or Antialiased. It can't be a mix. This is because "alias" is a property of the texture, and all the sprites share the same texture. + * + * @since v0.7.1 + */ +@interface CCSpriteBatchNode : CCNode +{ + CCTextureAtlas *_textureAtlas; + ccBlendFunc _blendFunc; + + // all descendants: children, grandchildren, etc... + CCArray *_descendants; +} + +/** returns the TextureAtlas that is used */ +@property (nonatomic,readwrite,retain) CCTextureAtlas * textureAtlas; + +/** conforms to CCTextureProtocol protocol */ +@property (nonatomic,readwrite) ccBlendFunc blendFunc; + +/** descendants (children, grandchildren, etc) */ +@property (nonatomic,readonly) CCArray *descendants; + +/** creates a CCSpriteBatchNode with a texture2d and a default capacity of 29 children. + The capacity will be increased in 33% in runtime if it run out of space. + */ ++(id)batchNodeWithTexture:(CCTexture2D *)tex; + +/** creates a CCSpriteBatchNode with a texture2d and capacity of children. + The capacity will be increased in 33% in runtime if it run out of space. + */ ++(id)batchNodeWithTexture:(CCTexture2D *)tex capacity:(NSUInteger)capacity; + +/** creates a CCSpriteBatchNode with a file image (.png, .jpeg, .pvr, etc) with a default capacity of 29 children. + The capacity will be increased in 33% in runtime if it run out of space. + The file will be loaded using the TextureMgr. + */ ++(id)batchNodeWithFile:(NSString*) fileImage; + +/** creates a CCSpriteBatchNode with a file image (.png, .jpeg, .pvr, etc) and capacity of children. + The capacity will be increased in 33% in runtime if it run out of space. + The file will be loaded using the TextureMgr. +*/ ++(id)batchNodeWithFile:(NSString*)fileImage capacity:(NSUInteger)capacity; + +/** initializes a CCSpriteBatchNode with a texture2d and capacity of children. + The capacity will be increased in 33% in runtime if it run out of space. + */ +-(id)initWithTexture:(CCTexture2D *)tex capacity:(NSUInteger)capacity; +/** initializes a CCSpriteBatchNode with a file image (.png, .jpeg, .pvr, etc) and a capacity of children. + The capacity will be increased in 33% in runtime if it run out of space. + The file will be loaded using the TextureMgr. + */ +-(id)initWithFile:(NSString*)fileImage capacity:(NSUInteger)capacity; + +-(void) increaseAtlasCapacity; + +/** removes a child given a certain index. It will also cleanup the running actions depending on the cleanup parameter. + @warning Removing a child from a CCSpriteBatchNode is very slow + */ +-(void)removeChildAtIndex:(NSUInteger)index cleanup:(BOOL)doCleanup; + +/** removes a child given a reference. It will also cleanup the running actions depending on the cleanup parameter. + @warning Removing a child from a CCSpriteBatchNode is very slow + */ +-(void)removeChild: (CCSprite *)sprite cleanup:(BOOL)doCleanup; + +-(void) insertChild:(CCSprite*)child inAtlasAtIndex:(NSUInteger)index; +-(void) appendChild:(CCSprite*)sprite; +-(void) removeSpriteFromAtlas:(CCSprite*)sprite; + +-(NSUInteger) rebuildIndexInOrder:(CCSprite*)parent atlasIndex:(NSUInteger)index; +-(NSUInteger) atlasIndexForChild:(CCSprite*)sprite atZ:(NSInteger)z; +/* Sprites use this to start sortChildren, don't call this manually */ +- (void) reorderBatch:(BOOL) reorder; + +@end + +@interface CCSpriteBatchNode (QuadExtensions) +/** Inserts a quad at a certain index into the texture atlas. The CCSprite won't be added into the children array. + This method should be called only when you are dealing with very big AtlasSrite and when most of the CCSprite won't be updated. + For example: a tile map (CCTMXMap) or a label with lots of characters (CCLabelBMFont) + */ +-(void) insertQuadFromSprite:(CCSprite*)sprite quadIndex:(NSUInteger)index; + +/** Updates a quad at a certain index into the texture atlas. The CCSprite won't be added into the children array. + This method should be called only when you are dealing with very big AtlasSrite and when most of the CCSprite won't be updated. + For example: a tile map (CCTMXMap) or a label with lots of characters (CCLabelBMFont) + */ +-(void) updateQuadFromSprite:(CCSprite*)sprite quadIndex:(NSUInteger)index; + +/* This is the opposite of "addQuadFromSprite". + It adds the sprite to the children and descendants array, but it doesn't add it to the texture atlas. + */ +-(id) addSpriteWithoutQuad:(CCSprite*)child z:(NSUInteger)z tag:(NSInteger)aTag; + +@end diff --git "a/21451198\345\215\242\350\266\205/project5/MyPlane/libs/cocos2d/CCSpriteBatchNode.m" "b/21451198\345\215\242\350\266\205/project5/MyPlane/libs/cocos2d/CCSpriteBatchNode.m" new file mode 100644 index 00000000..a8fb50a3 --- /dev/null +++ "b/21451198\345\215\242\350\266\205/project5/MyPlane/libs/cocos2d/CCSpriteBatchNode.m" @@ -0,0 +1,686 @@ +/* + * cocos2d for iPhone: http://www.cocos2d-iphone.org + * + * Copyright (C) 2009 Matt Oswald + * + * Copyright (c) 2009-2010 Ricardo Quesada + * Copyright (c) 2011 Zynga Inc. + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + * THE SOFTWARE. + * + */ + + +#import "ccConfig.h" +#import "CCSprite.h" +#import "CCSpriteBatchNode.h" +#import "CCGrid.h" +#import "CCDrawingPrimitives.h" +#import "CCTextureCache.h" +#import "CCShaderCache.h" +#import "CCGLProgram.h" +#import "ccGLStateCache.h" +#import "CCDirector.h" +#import "Support/CGPointExtension.h" +#import "Support/TransformUtils.h" +#import "Support/CCProfiling.h" + +// external +#import "kazmath/GL/matrix.h" + +const NSUInteger defaultCapacity = 29; + +#pragma mark - +#pragma mark CCSpriteBatchNode + +@interface CCSpriteBatchNode (private) +-(void) updateAtlasIndex:(CCSprite*) sprite currentIndex:(NSInteger*) curIndex; +-(void) swap:(NSInteger) oldIndex withNewIndex:(NSInteger) newIndex; +-(void) updateBlendFunc; +@end + +@implementation CCSpriteBatchNode + +@synthesize textureAtlas = _textureAtlas; +@synthesize blendFunc = _blendFunc; +@synthesize descendants = _descendants; + + +/* + * creation with CCTexture2D + */ ++(id)batchNodeWithTexture:(CCTexture2D *)tex +{ + return [[[self alloc] initWithTexture:tex capacity:defaultCapacity] autorelease]; +} + ++(id)batchNodeWithTexture:(CCTexture2D *)tex capacity:(NSUInteger)capacity +{ + return [[[self alloc] initWithTexture:tex capacity:capacity] autorelease]; +} + +/* + * creation with File Image + */ ++(id)batchNodeWithFile:(NSString*)fileImage capacity:(NSUInteger)capacity +{ + return [[[self alloc] initWithFile:fileImage capacity:capacity] autorelease]; +} + ++(id)batchNodeWithFile:(NSString*) imageFile +{ + return [[[self alloc] initWithFile:imageFile capacity:defaultCapacity] autorelease]; +} + +-(id)init +{ + return [self initWithTexture:[[[CCTexture2D alloc] init] autorelease] capacity:0]; +} + +-(id)initWithFile:(NSString *)fileImage capacity:(NSUInteger)capacity +{ + CCTexture2D *tex = [[CCTextureCache sharedTextureCache] addImage:fileImage]; + return [self initWithTexture:tex capacity:capacity]; +} + +// Designated initializer +-(id)initWithTexture:(CCTexture2D *)tex capacity:(NSUInteger)capacity +{ + if( (self=[super init])) { + + _blendFunc.src = CC_BLEND_SRC; + _blendFunc.dst = CC_BLEND_DST; + _textureAtlas = [[CCTextureAtlas alloc] initWithTexture:tex capacity:capacity]; + + [self updateBlendFunc]; + + // no lazy alloc in this node + _children = [[CCArray alloc] initWithCapacity:capacity]; + _descendants = [[CCArray alloc] initWithCapacity:capacity]; + + self.shaderProgram = [[CCShaderCache sharedShaderCache] programForKey:kCCShader_PositionTextureColor]; + } + + return self; +} + + +- (NSString*) description +{ + return [NSString stringWithFormat:@"<%@ = %p | Tag = %ld>", [self class], self, (long)_tag ]; +} + +-(void)dealloc +{ + [_textureAtlas release]; + [_descendants release]; + + [super dealloc]; +} + +#pragma mark CCSpriteBatchNode - composition + +// override visit. +// Don't call visit on its children +-(void) visit +{ + CC_PROFILER_START_CATEGORY(kCCProfilerCategoryBatchSprite, @"CCSpriteBatchNode - visit"); + + NSAssert(_parent != nil, @"CCSpriteBatchNode should NOT be root node"); + + // CAREFUL: + // This visit is almost identical to CCNode#visit + // with the exception that it doesn't call visit on its children + // + // The alternative is to have a void CCSprite#visit, but + // although this is less mantainable, is faster + // + if (!_visible) + return; + + kmGLPushMatrix(); + + if ( _grid && _grid.active) { + [_grid beforeDraw]; + [self transformAncestors]; + } + + [self sortAllChildren]; + [self transform]; + [self draw]; + + if ( _grid && _grid.active) + [_grid afterDraw:self]; + + kmGLPopMatrix(); + + _orderOfArrival = 0; + + CC_PROFILER_STOP_CATEGORY(kCCProfilerCategoryBatchSprite, @"CCSpriteBatchNode - visit"); +} + +// override addChild: +-(void) addChild:(CCSprite*)child z:(NSInteger)z tag:(NSInteger) aTag +{ + NSAssert( child != nil, @"Argument must be non-nil"); + NSAssert( [child isKindOfClass:[CCSprite class]], @"CCSpriteBatchNode only supports CCSprites as children"); + NSAssert( child.texture.name == _textureAtlas.texture.name, @"CCSprite is not using the same texture id"); + + [super addChild:child z:z tag:aTag]; + + [self appendChild:child]; +} + +// override reorderChild +-(void) reorderChild:(CCSprite*)child z:(NSInteger)z +{ + NSAssert( child != nil, @"Child must be non-nil"); + NSAssert( [_children containsObject:child], @"Child doesn't belong to Sprite" ); + + if( z == child.zOrder ) + return; + + //set the z-order and sort later + [super reorderChild:child z:z]; +} + +// override removeChild: +-(void)removeChild: (CCSprite *)sprite cleanup:(BOOL)doCleanup +{ + // explicit nil handling + if (sprite == nil) + return; + + NSAssert([_children containsObject:sprite], @"CCSpriteBatchNode doesn't contain the sprite. Can't remove it"); + + // cleanup before removing + [self removeSpriteFromAtlas:sprite]; + + [super removeChild:sprite cleanup:doCleanup]; +} + +-(void)removeChildAtIndex:(NSUInteger)index cleanup:(BOOL)doCleanup +{ + [self removeChild:(CCSprite *)[_children objectAtIndex:index] cleanup:doCleanup]; +} + +-(void)removeAllChildrenWithCleanup:(BOOL)doCleanup +{ + // Invalidate atlas index. issue #569 + // useSelfRender should be performed on all descendants. issue #1216 + [_descendants makeObjectsPerformSelector:@selector(setBatchNode:) withObject:nil]; + + [super removeAllChildrenWithCleanup:doCleanup]; + + [_descendants removeAllObjects]; + [_textureAtlas removeAllQuads]; +} + +//override sortAllChildren +- (void) sortAllChildren +{ + if (_isReorderChildDirty) + { + NSInteger i,j,length = _children->data->num; + CCNode ** x = _children->data->arr; + CCNode *tempItem; + CCSprite *child; + + //insertion sort + for(i=1; i=0 && ( tempItem.zOrder < x[j].zOrder || ( tempItem.zOrder == x[j].zOrder && tempItem.orderOfArrival < x[j].orderOfArrival ) ) ) + { + x[j+1] = x[j]; + j--; + } + + x[j+1] = tempItem; + } + + //sorted now check all children + if ([_children count] > 0) + { + //first sort all children recursively based on zOrder + [_children makeObjectsPerformSelector:@selector(sortAllChildren)]; + + NSInteger index=0; + + //fast dispatch, give every child a new atlasIndex based on their relative zOrder (keep parent -> child relations intact) + // and at the same time reorder descedants and the quads to the right index + CCARRAY_FOREACH(_children, child) + [self updateAtlasIndex:child currentIndex:&index]; + } + + _isReorderChildDirty=NO; + } +} + +-(void) updateAtlasIndex:(CCSprite*) sprite currentIndex:(NSInteger*) curIndex +{ + CCArray *array = [sprite children]; + NSUInteger count = [array count]; + NSInteger oldIndex; + + if( count == 0 ) + { + oldIndex = sprite.atlasIndex; + sprite.atlasIndex = *curIndex; + sprite.orderOfArrival = 0; + if (oldIndex != *curIndex) + [self swap:oldIndex withNewIndex:*curIndex]; + (*curIndex)++; + } + else + { + BOOL needNewIndex=YES; + + if (((CCSprite*) (array->data->arr[0])).zOrder >= 0) + { + //all children are in front of the parent + oldIndex = sprite.atlasIndex; + sprite.atlasIndex = *curIndex; + sprite.orderOfArrival = 0; + if (oldIndex != *curIndex) + [self swap:oldIndex withNewIndex:*curIndex]; + (*curIndex)++; + + needNewIndex = NO; + } + + CCSprite* child; + CCARRAY_FOREACH(array,child) + { + if (needNewIndex && child.zOrder >= 0) + { + oldIndex = sprite.atlasIndex; + sprite.atlasIndex = *curIndex; + sprite.orderOfArrival = 0; + if (oldIndex != *curIndex) + [self swap:oldIndex withNewIndex:*curIndex]; + (*curIndex)++; + needNewIndex = NO; + + } + + [self updateAtlasIndex:child currentIndex:curIndex]; + } + + if (needNewIndex) + {//all children have a zOrder < 0) + oldIndex=sprite.atlasIndex; + sprite.atlasIndex=*curIndex; + sprite.orderOfArrival=0; + if (oldIndex!=*curIndex) + [self swap:oldIndex withNewIndex:*curIndex]; + (*curIndex)++; + } + } +} + +- (void) swap:(NSInteger) oldIndex withNewIndex:(NSInteger) newIndex +{ + id* x = _descendants->data->arr; + ccV3F_C4B_T2F_Quad* quads = _textureAtlas.quads; + + id tempItem = x[oldIndex]; + ccV3F_C4B_T2F_Quad tempItemQuad=quads[oldIndex]; + + //update the index of other swapped item + ((CCSprite*) x[newIndex]).atlasIndex=oldIndex; + + x[oldIndex]=x[newIndex]; + quads[oldIndex]=quads[newIndex]; + x[newIndex]=tempItem; + quads[newIndex]=tempItemQuad; +} + +- (void) reorderBatch:(BOOL) reorder +{ + _isReorderChildDirty=reorder; +} + +#pragma mark CCSpriteBatchNode - draw +-(void) draw +{ + CC_PROFILER_START(@"CCSpriteBatchNode - draw"); + + // Optimization: Fast Dispatch + if( _textureAtlas.totalQuads == 0 ) + return; + + CC_NODE_DRAW_SETUP(); + + [_children makeObjectsPerformSelector:@selector(updateTransform)]; + + ccGLBlendFunc( _blendFunc.src, _blendFunc.dst ); + + [_textureAtlas drawQuads]; + + CC_PROFILER_STOP(@"CCSpriteBatchNode - draw"); +} + +#pragma mark CCSpriteBatchNode - private +-(void) increaseAtlasCapacity +{ + // if we're going beyond the current CCTextureAtlas's capacity, + // all the previously initialized sprites will need to redo their texture coords + // this is likely computationally expensive + NSUInteger quantity = (_textureAtlas.capacity + 1) * 4 / 3; + + CCLOG(@"cocos2d: CCSpriteBatchNode: resizing TextureAtlas capacity from [%lu] to [%lu].", + (long)_textureAtlas.capacity, + (long)quantity); + + + if( ! [_textureAtlas resizeCapacity:quantity] ) { + // serious problems + CCLOGWARN(@"cocos2d: WARNING: Not enough memory to resize the atlas"); + NSAssert(NO,@"XXX: CCSpriteBatchNode#increaseAtlasCapacity SHALL handle this assert"); + } +} + + +#pragma mark CCSpriteBatchNode - Atlas Index Stuff + +-(NSUInteger) rebuildIndexInOrder:(CCSprite*)node atlasIndex:(NSUInteger)index +{ + CCSprite *sprite; + CCARRAY_FOREACH(node.children, sprite){ + if( sprite.zOrder < 0 ) + index = [self rebuildIndexInOrder:sprite atlasIndex:index]; + } + + // ignore self (batch node) + if( ! [node isEqual:self]) { + node.atlasIndex = index; + index++; + } + + CCARRAY_FOREACH(node.children, sprite){ + if( sprite.zOrder >= 0 ) + index = [self rebuildIndexInOrder:sprite atlasIndex:index]; + } + + return index; +} + +-(NSUInteger) highestAtlasIndexInChild:(CCSprite*)sprite +{ + CCArray *array = [sprite children]; + NSUInteger count = [array count]; + if( count == 0 ) + return sprite.atlasIndex; + else + return [self highestAtlasIndexInChild:[array lastObject]]; +} + +-(NSUInteger) lowestAtlasIndexInChild:(CCSprite*)sprite +{ + CCArray *array = [sprite children]; + NSUInteger count = [array count]; + if( count == 0 ) + return sprite.atlasIndex; + else + return [self lowestAtlasIndexInChild:[array objectAtIndex:0] ]; +} + + +-(NSUInteger)atlasIndexForChild:(CCSprite*)sprite atZ:(NSInteger)z +{ + CCArray *brothers = [[sprite parent] children]; + NSUInteger childIndex = [brothers indexOfObject:sprite]; + + // ignore parent Z if parent is batchnode + BOOL ignoreParent = ( sprite.parent == self ); + CCSprite *previous = nil; + if( childIndex > 0 ) + previous = [brothers objectAtIndex:childIndex-1]; + + // first child of the sprite sheet + if( ignoreParent ) { + if( childIndex == 0 ) + return 0; + // else + return [self highestAtlasIndexInChild: previous] + 1; + } + + // parent is a CCSprite, so, it must be taken into account + + // first child of an CCSprite ? + if( childIndex == 0 ) + { + CCSprite *p = (CCSprite*) sprite.parent; + + // less than parent and brothers + if( z < 0 ) + return p.atlasIndex; + else + return p.atlasIndex+1; + + } else { + // previous & sprite belong to the same branch + if( ( previous.zOrder < 0 && z < 0 )|| (previous.zOrder >= 0 && z >= 0) ) + return [self highestAtlasIndexInChild:previous] + 1; + + // else (previous < 0 and sprite >= 0 ) + CCSprite *p = (CCSprite*) sprite.parent; + return p.atlasIndex + 1; + } + + NSAssert( NO, @"Should not happen. Error calculating Z on Batch Node"); + return 0; +} + +#pragma mark CCSpriteBatchNode - add / remove / reorder helper methods +// add child helper +-(void) insertChild:(CCSprite*)sprite inAtlasAtIndex:(NSUInteger)index +{ + [sprite setBatchNode:self]; + [sprite setAtlasIndex:index]; + [sprite setDirty: YES]; + + if(_textureAtlas.totalQuads == _textureAtlas.capacity) + [self increaseAtlasCapacity]; + + ccV3F_C4B_T2F_Quad quad = [sprite quad]; + [_textureAtlas insertQuad:&quad atIndex:index]; + + ccArray *descendantsData = _descendants->data; + + ccArrayInsertObjectAtIndex(descendantsData, sprite, index); + + // update indices + NSUInteger i = index+1; + CCSprite *child; + for(; inum; i++){ + child = descendantsData->arr[i]; + child.atlasIndex = child.atlasIndex + 1; + } + + // add children recursively + CCARRAY_FOREACH(sprite.children, child){ + NSUInteger idx = [self atlasIndexForChild:child atZ: child.zOrder]; + [self insertChild:child inAtlasAtIndex:idx]; + } +} + +// addChild helper, faster than insertChild +-(void) appendChild:(CCSprite*)sprite +{ + _isReorderChildDirty=YES; + [sprite setBatchNode:self]; + [sprite setDirty: YES]; + + if(_textureAtlas.totalQuads == _textureAtlas.capacity) + [self increaseAtlasCapacity]; + + ccArray *descendantsData = _descendants->data; + + ccArrayAppendObjectWithResize(descendantsData, sprite); + + NSUInteger index=descendantsData->num-1; + + sprite.atlasIndex=index; + + ccV3F_C4B_T2F_Quad quad = [sprite quad]; + [_textureAtlas insertQuad:&quad atIndex:index]; + + // add children recursively + CCSprite* child; + CCARRAY_FOREACH(sprite.children, child) + [self appendChild:child]; +} + + +// remove child helper +-(void) removeSpriteFromAtlas:(CCSprite*)sprite +{ + // remove from TextureAtlas + [_textureAtlas removeQuadAtIndex:sprite.atlasIndex]; + + // Cleanup sprite. It might be reused (issue #569) + [sprite setBatchNode:nil]; + + ccArray *descendantsData = _descendants->data; + NSUInteger index = ccArrayGetIndexOfObject(descendantsData, sprite); + if( index != NSNotFound ) { + ccArrayRemoveObjectAtIndex(descendantsData, index); + + // update all sprites beyond this one + NSUInteger count = descendantsData->num; + + for(; index < count; index++) + { + CCSprite *s = descendantsData->arr[index]; + s.atlasIndex = s.atlasIndex - 1; + } + } + + // remove children recursively + CCSprite *child; + CCARRAY_FOREACH(sprite.children, child) + [self removeSpriteFromAtlas:child]; +} + +#pragma mark CCSpriteBatchNode - CocosNodeTexture protocol + +-(void) updateBlendFunc +{ + if( ! [_textureAtlas.texture hasPremultipliedAlpha] ) { + _blendFunc.src = GL_SRC_ALPHA; + _blendFunc.dst = GL_ONE_MINUS_SRC_ALPHA; + } +} + +-(void) setTexture:(CCTexture2D*)texture +{ + _textureAtlas.texture = texture; + [self updateBlendFunc]; +} + +-(CCTexture2D*) texture +{ + return _textureAtlas.texture; +} +@end + +#pragma mark - CCSpriteBatchNode Extension + + +@implementation CCSpriteBatchNode (QuadExtension) + +-(void) insertQuadFromSprite:(CCSprite*)sprite quadIndex:(NSUInteger)index +{ + NSAssert( sprite != nil, @"Argument must be non-nil"); + NSAssert( [sprite isKindOfClass:[CCSprite class]], @"CCSpriteBatchNode only supports CCSprites as children"); + + // make needed room + while(index >= _textureAtlas.capacity || _textureAtlas.capacity == _textureAtlas.totalQuads ) + [self increaseAtlasCapacity]; + + // + // update the quad directly. Don't add the sprite to the scene graph + // + + [sprite setBatchNode:self]; + [sprite setAtlasIndex:index]; + + ccV3F_C4B_T2F_Quad quad = [sprite quad]; + [_textureAtlas insertQuad:&quad atIndex:index]; + + // XXX: updateTransform will update the textureAtlas too, using updateQuad. + // XXX: so, it should be AFTER the insertQuad + [sprite setDirty:YES]; + [sprite updateTransform]; +} + +-(void) updateQuadFromSprite:(CCSprite*)sprite quadIndex:(NSUInteger)index +{ + NSAssert( sprite != nil, @"Argument must be non-nil"); + NSAssert( [sprite isKindOfClass:[CCSprite class]], @"CCSpriteBatchNode only supports CCSprites as children"); + + // make needed room + while(index >= _textureAtlas.capacity || _textureAtlas.capacity == _textureAtlas.totalQuads ) + [self increaseAtlasCapacity]; + + // + // update the quad directly. Don't add the sprite to the scene graph + // + [sprite setBatchNode:self]; + [sprite setAtlasIndex:index]; + + [sprite setDirty:YES]; + + // UpdateTransform updates the textureAtlas quad + [sprite updateTransform]; +} + + +-(id) addSpriteWithoutQuad:(CCSprite*)child z:(NSUInteger)z tag:(NSInteger)aTag +{ + NSAssert( child != nil, @"Argument must be non-nil"); + NSAssert( [child isKindOfClass:[CCSprite class]], @"CCSpriteBatchNode only supports CCSprites as children"); + + // quad index is Z + [child setAtlasIndex:z]; + + // XXX: optimize with a binary search + int i=0; + for( CCSprite *c in _descendants ) { + if( c.atlasIndex >= z ) + break; + i++; + } + [_descendants insertObject:child atIndex:i]; + + + // IMPORTANT: Call super, and not self. Avoid adding it to the texture atlas array + [super addChild:child z:z tag:aTag]; + + //#issue 1262 don't use lazy sorting, tiles are added as quads not as sprites, so sprites need to be added in order + [self reorderBatch:NO]; + return self; +} +@end + diff --git "a/21451198\345\215\242\350\266\205/project5/MyPlane/libs/cocos2d/CCSpriteFrame.h" "b/21451198\345\215\242\350\266\205/project5/MyPlane/libs/cocos2d/CCSpriteFrame.h" new file mode 100644 index 00000000..379e6889 --- /dev/null +++ "b/21451198\345\215\242\350\266\205/project5/MyPlane/libs/cocos2d/CCSpriteFrame.h" @@ -0,0 +1,126 @@ +/* + * cocos2d for iPhone: http://www.cocos2d-iphone.org + * + * Copyright (c) 2008-2011 Ricardo Quesada + * Copyright (c) 2011 Zynga Inc. + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + * THE SOFTWARE. + * + */ + +#import +#import "CCNode.h" +#import "CCProtocols.h" + +/** A CCSpriteFrame has: + - texture: A CCTexture2D that will be used by the CCSprite + - rectangle: A rectangle of the texture + + + You can modify the frame of a CCSprite by doing: + + CCSpriteFrame *frame = [CCSpriteFrame frameWithTexture:texture rect:rect offset:offset]; + [sprite setDisplayFrame:frame]; + */ +@interface CCSpriteFrame : NSObject +{ + CGRect _rect; + CGRect _rectInPixels; + BOOL _rotated; + CGPoint _offset; + CGPoint _offsetInPixels; + CGSize _originalSize; + CGSize _originalSizeInPixels; + CCTexture2D *_texture; + NSString *_textureFilename; +} +/** rect of the frame in points. If it is updated, then rectInPixels will be updated too. */ +@property (nonatomic,readwrite) CGRect rect; + +/** rect of the frame in pixels. If it is updated, then rect (points) will be updated too. */ +@property (nonatomic,readwrite) CGRect rectInPixels; + +/** whether or not the rect of the frame is rotated ( x = x+width, y = y+height, width = height, height = width ) */ +@property (nonatomic,readwrite) BOOL rotated; + +/** offset of the frame in points */ +@property (nonatomic,readwrite) CGPoint offset; + +/** offset of the frame in pixels */ +@property (nonatomic,readwrite) CGPoint offsetInPixels; + +/** original size of the trimmed image in points */ +@property (nonatomic,readwrite) CGSize originalSize; + +/** original size of the trimmed image in pixels */ +@property (nonatomic,readwrite) CGSize originalSizeInPixels; + +/** texture of the frame */ +@property (nonatomic, retain, readwrite) CCTexture2D *texture; + +/** texture file name of the frame */ +@property (nonatomic, retain, readonly) NSString *textureFilename; + +/** Create a CCSpriteFrame with a texture, rect in points. + It is assumed that the frame was not trimmed. + */ ++(id) frameWithTexture:(CCTexture2D*)texture rect:(CGRect)rect; + +/** Create a CCSpriteFrame with a texture filename, rect in points. + It is assumed that the frame was not trimmed. + */ ++(id) frameWithTextureFilename:(NSString*)filename rect:(CGRect)rect; + +/** Create a CCSpriteFrame with a texture, rect, rotated, offset and originalSize in pixels. + The originalSize is the size in pixels of the frame before being trimmed. + */ ++(id) frameWithTexture:(CCTexture2D*)texture rectInPixels:(CGRect)rect rotated:(BOOL)rotated offset:(CGPoint)offset originalSize:(CGSize)originalSize; + + +/** Create a CCSpriteFrame with a texture filename, rect, rotated, offset and originalSize in pixels. + The originalSize is the size in pixels of the frame before being trimmed. + */ ++(id) frameWithTextureFilename:(NSString*)filename rectInPixels:(CGRect)rect rotated:(BOOL)rotated offset:(CGPoint)offset originalSize:(CGSize)originalSize; + + +/** Initializes a CCSpriteFrame with a texture, rect in points; + It is assumed that the frame was not trimmed. + */ +-(id) initWithTexture:(CCTexture2D*)texture rect:(CGRect)rect; + +/** Initializes a CCSpriteFrame with a texture filename, rect in points; + It is assumed that the frame was not trimmed. + */ +-(id) initWithTextureFilename:(NSString*)filename rect:(CGRect)rect; + + +/** Initializes a CCSpriteFrame with a texture, rect, rotated, offset and originalSize in pixels. + The originalSize is the size in pixels of the frame before being trimmed. + */ +-(id) initWithTexture:(CCTexture2D*)texture rectInPixels:(CGRect)rect rotated:(BOOL)rotated offset:(CGPoint)offset originalSize:(CGSize)originalSize; + +/** Initializes a CCSpriteFrame with a texture, rect, rotated, offset and originalSize in pixels. + The originalSize is the size in pixels of the frame before being trimmed. + + @since v1.1 + */ +-(id) initWithTextureFilename:(NSString*)filename rectInPixels:(CGRect)rect rotated:(BOOL)rotated offset:(CGPoint)offset originalSize:(CGSize)originalSize; + +@end + diff --git "a/21451198\345\215\242\350\266\205/project5/MyPlane/libs/cocos2d/CCSpriteFrame.m" "b/21451198\345\215\242\350\266\205/project5/MyPlane/libs/cocos2d/CCSpriteFrame.m" new file mode 100644 index 00000000..d12fa212 --- /dev/null +++ "b/21451198\345\215\242\350\266\205/project5/MyPlane/libs/cocos2d/CCSpriteFrame.m" @@ -0,0 +1,185 @@ +/* + * cocos2d for iPhone: http://www.cocos2d-iphone.org + * + * Copyright (c) 2008-2011 Ricardo Quesada + * Copyright (c) 2011 Zynga Inc. + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + * THE SOFTWARE. + * + */ + + +#import "CCTextureCache.h" +#import "CCSpriteFrame.h" +#import "ccMacros.h" + +@implementation CCSpriteFrame +@synthesize offsetInPixels = _offsetInPixels, offset = _offset; +@synthesize originalSize = _originalSize, originalSizeInPixels = _originalSizeInPixels; +@synthesize textureFilename = _textureFilename; +@synthesize rotated = _rotated; + ++(id) frameWithTexture:(CCTexture2D*)texture rect:(CGRect)rect +{ + return [[[self alloc] initWithTexture:texture rect:rect] autorelease]; +} + ++(id) frameWithTextureFilename:(NSString*)filename rect:(CGRect)rect +{ + return [[[self alloc] initWithTextureFilename:filename rect:rect] autorelease]; +} + ++(id) frameWithTexture:(CCTexture2D*)texture rectInPixels:(CGRect)rect rotated:(BOOL)rotated offset:(CGPoint)offset originalSize:(CGSize)originalSize +{ + return [[[self alloc] initWithTexture:texture rectInPixels:rect rotated:rotated offset:offset originalSize:originalSize] autorelease]; +} + ++(id) frameWithTextureFilename:(NSString*)filename rectInPixels:(CGRect)rect rotated:(BOOL)rotated offset:(CGPoint)offset originalSize:(CGSize)originalSize +{ + return [[[self alloc] initWithTextureFilename:filename rectInPixels:rect rotated:rotated offset:offset originalSize:originalSize] autorelease]; +} + +-(id) initWithTexture:(CCTexture2D*)texture rect:(CGRect)rect +{ + CGRect rectInPixels = CC_RECT_POINTS_TO_PIXELS( rect ); + return [self initWithTexture:texture rectInPixels:rectInPixels rotated:NO offset:CGPointZero originalSize:rectInPixels.size]; +} + +-(id) initWithTextureFilename:(NSString*)filename rect:(CGRect)rect +{ + CGRect rectInPixels = CC_RECT_POINTS_TO_PIXELS( rect ); + return [self initWithTextureFilename:filename rectInPixels:rectInPixels rotated:NO offset:CGPointZero originalSize:rectInPixels.size]; +} + +-(id) initWithTexture:(CCTexture2D*)texture rectInPixels:(CGRect)rect rotated:(BOOL)rotated offset:(CGPoint)offset originalSize:(CGSize)originalSize +{ + if( (self=[super init]) ) + { + self.texture = texture; + _rectInPixels = rect; + _rect = CC_RECT_PIXELS_TO_POINTS( rect ); + _offsetInPixels = offset; + _offset = CC_POINT_PIXELS_TO_POINTS( _offsetInPixels ); + _originalSizeInPixels = originalSize; + _originalSize = CC_SIZE_PIXELS_TO_POINTS( _originalSizeInPixels ); + _rotated = rotated; + } + return self; +} + +-(id) initWithTextureFilename:(NSString *)filename rectInPixels:(CGRect)rect rotated:(BOOL)rotated offset:(CGPoint)offset originalSize:(CGSize)originalSize +{ + if( (self=[super init]) ) + { + _texture = nil; + _textureFilename = [filename copy]; + _rectInPixels = rect; + _rect = CC_RECT_PIXELS_TO_POINTS( rect ); + _offsetInPixels = offset; + _offset = CC_POINT_PIXELS_TO_POINTS( _offsetInPixels ); + _originalSizeInPixels = originalSize; + _originalSize = CC_SIZE_PIXELS_TO_POINTS( _originalSizeInPixels ); + _rotated = rotated; + } + return self; +} + +- (NSString*) description +{ + return [NSString stringWithFormat:@"<%@ = %p | Texture=%@, Rect = (%.2f,%.2f,%.2f,%.2f)> rotated:%d offset=(%.2f,%.2f)", [self class], self, + _textureFilename, + _rect.origin.x, + _rect.origin.y, + _rect.size.width, + _rect.size.height, + _rotated, + _offsetInPixels.x, + _offsetInPixels.y + ]; +} + +- (void) dealloc +{ + CCLOGINFO( @"cocos2d: deallocing %@",self); + [_texture release]; + [_textureFilename release]; + [super dealloc]; +} + +-(id) copyWithZone: (NSZone*) zone +{ + CCSpriteFrame *copy = [[[self class] allocWithZone: zone] initWithTextureFilename:_textureFilename rectInPixels:_rectInPixels rotated:_rotated offset:_offsetInPixels originalSize:_originalSizeInPixels]; + copy.texture = _texture; + return copy; +} + +-(CGRect) rect +{ + return _rect; +} + +-(CGRect) rectInPixels +{ + return _rectInPixels; +} + +-(void) setRect:(CGRect)rect +{ + _rect = rect; + _rectInPixels = CC_RECT_POINTS_TO_PIXELS(_rect); +} + +-(void) setRectInPixels:(CGRect)rectInPixels +{ + _rectInPixels = rectInPixels; + _rect = CC_RECT_PIXELS_TO_POINTS( _rectInPixels ); +} + +-(void) setOffset:(CGPoint)offsets +{ + _offset = offsets; + _offsetInPixels = CC_POINT_POINTS_TO_PIXELS( _offset ); +} + +-(void) setOffsetInPixels:(CGPoint)offsetInPixels +{ + _offsetInPixels = offsetInPixels; + _offset = CC_POINT_PIXELS_TO_POINTS( _offsetInPixels ); +} + +-(void) setTexture:(CCTexture2D *)texture +{ + if( _texture != texture ) { + [_texture release]; + _texture = [texture retain]; + } +} + +-(CCTexture2D*) texture +{ + if( _texture ) + return _texture; + + if( _textureFilename ) + return [[CCTextureCache sharedTextureCache] addImage:_textureFilename]; + + // no texture or texture filename + return nil; +} +@end diff --git "a/21451198\345\215\242\350\266\205/project5/MyPlane/libs/cocos2d/CCSpriteFrameCache.h" "b/21451198\345\215\242\350\266\205/project5/MyPlane/libs/cocos2d/CCSpriteFrameCache.h" new file mode 100644 index 00000000..00243217 --- /dev/null +++ "b/21451198\345\215\242\350\266\205/project5/MyPlane/libs/cocos2d/CCSpriteFrameCache.h" @@ -0,0 +1,121 @@ +/* + * cocos2d for iPhone: http://www.cocos2d-iphone.org + * + * Copyright (c) 2009 Jason Booth + * + * Copyright (c) 2009 Robert J Payne + * + * Copyright (c) 2008-2010 Ricardo Quesada + * Copyright (c) 2011 Zynga Inc. + * + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + * THE SOFTWARE. + * + */ + + +/* + * To create sprite frames and texture atlas, use this tool: + * http://zwoptex.zwopple.com/ + */ + +#import + +#import "CCSpriteFrame.h" + +@class CCSprite; +@class CCTexture2D; + +/** Singleton that handles the loading of the sprite frames. + It saves in a cache the sprite frames. + @since v0.9 + */ +@interface CCSpriteFrameCache : NSObject +{ + NSMutableDictionary *_spriteFrames; + NSMutableDictionary *_spriteFramesAliases; + NSMutableSet *_loadedFilenames; +} + +/** Retruns ths shared instance of the Sprite Frame cache */ ++ (CCSpriteFrameCache *) sharedSpriteFrameCache; + +/** Purges the cache. It releases all the Sprite Frames and the retained instance. + */ ++(void)purgeSharedSpriteFrameCache; + + +/** Adds multiple Sprite Frames from a plist file. + * A texture will be loaded automatically. The texture name will composed by replacing the .plist suffix with .png . + * If you want to use another texture, you should use the addSpriteFramesWithFile:texture method. + */ +-(void) addSpriteFramesWithFile:(NSString*)plist; + +/** Adds multiple Sprite Frames from a plist file. The texture filename will be associated with the created sprite frames. + */ +-(void) addSpriteFramesWithFile:(NSString*)plist textureFilename:(NSString*)filename; + +/** Adds multiple Sprite Frames from a plist file. The texture will be associated with the created sprite frames. + */ +-(void) addSpriteFramesWithFile:(NSString*)plist texture:(CCTexture2D*)texture; + +/** Adds an sprite frame with a given name. + If the name already exists, then the contents of the old name will be replaced with the new one. + */ +-(void) addSpriteFrame:(CCSpriteFrame*)frame name:(NSString*)frameName; + + +/** Purges the dictionary of loaded sprite frames. + * Call this method if you receive the "Memory Warning". + * In the short term: it will free some resources preventing your app from being killed. + * In the medium term: it will allocate more resources. + * In the long term: it will be the same. + */ +-(void) removeSpriteFrames; + +/** Removes unused sprite frames. + * Sprite Frames that have a retain count of 1 will be deleted. + * It is convenient to call this method after when starting a new Scene. + */ +-(void) removeUnusedSpriteFrames; + +/** Deletes an sprite frame from the sprite frame cache. + */ +-(void) removeSpriteFrameByName:(NSString*)name; + +/** Removes multiple Sprite Frames from a plist file. +* Sprite Frames stored in this file will be removed. +* It is convenient to call this method when a specific texture needs to be removed. +* @since v0.99.5 +*/ +- (void) removeSpriteFramesFromFile:(NSString*) plist; + +/** Removes all Sprite Frames associated with the specified textures. + * It is convenient to call this method when a specific texture needs to be removed. + * @since v0.995. + */ +- (void) removeSpriteFramesFromTexture:(CCTexture2D*) texture; + +/** Returns an Sprite Frame that was previously added. + If the name is not found it will return nil. + You should retain the returned copy if you are going to use it. + */ +-(CCSpriteFrame*) spriteFrameByName:(NSString*)name; + +@end diff --git "a/21451198\345\215\242\350\266\205/project5/MyPlane/libs/cocos2d/CCSpriteFrameCache.m" "b/21451198\345\215\242\350\266\205/project5/MyPlane/libs/cocos2d/CCSpriteFrameCache.m" new file mode 100644 index 00000000..6a38e91b --- /dev/null +++ "b/21451198\345\215\242\350\266\205/project5/MyPlane/libs/cocos2d/CCSpriteFrameCache.m" @@ -0,0 +1,413 @@ +/* + * cocos2d for iPhone: http://www.cocos2d-iphone.org + * + * Copyright (c) 2009 Jason Booth + * + * Copyright (c) 2009 Robert J Payne + * + * Copyright (c) 2008-2010 Ricardo Quesada + * Copyright (c) 2011 Zynga Inc. + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + * THE SOFTWARE. + * + */ + +/* + * To create sprite frames and texture atlas, use any of these tools: + * http://zwoptexapp.com/ + * http://www.texturepacker.com/ + * + */ + +#import "Platforms/CCNS.h" +#import "ccMacros.h" +#import "CCTextureCache.h" +#import "CCSpriteFrameCache.h" +#import "CCSpriteFrame.h" +#import "CCSprite.h" +#import "Support/CCFileUtils.h" + +@interface CCSpriteFrameCache () +- (void) addSpriteFramesWithDictionary:(NSDictionary*)dictionary textureFilename:(NSString*)filename; +- (void) addSpriteFramesWithDictionary:(NSDictionary *)dictionary texture:(CCTexture2D *)texture; +- (void) removeSpriteFramesFromDictionary:(NSDictionary*) dictionary; +@end + + +@implementation CCSpriteFrameCache + +#pragma mark CCSpriteFrameCache - Alloc, Init & Dealloc + +static CCSpriteFrameCache *_sharedSpriteFrameCache=nil; + ++ (CCSpriteFrameCache *)sharedSpriteFrameCache +{ + if (!_sharedSpriteFrameCache) + _sharedSpriteFrameCache = [[CCSpriteFrameCache alloc] init]; + + return _sharedSpriteFrameCache; +} + ++(id)alloc +{ + NSAssert(_sharedSpriteFrameCache == nil, @"Attempted to allocate a second instance of a singleton."); + return [super alloc]; +} + ++(void)purgeSharedSpriteFrameCache +{ + [_sharedSpriteFrameCache release]; + _sharedSpriteFrameCache = nil; +} + +-(id) init +{ + if( (self=[super init]) ) { + _spriteFrames = [[NSMutableDictionary alloc] initWithCapacity: 100]; + _spriteFramesAliases = [[NSMutableDictionary alloc] initWithCapacity:10]; + _loadedFilenames = [[NSMutableSet alloc] initWithCapacity:30]; + } + + return self; +} + +- (NSString*) description +{ + return [NSString stringWithFormat:@"<%@ = %p | num of sprite frames = %lu>", [self class], self, (unsigned long)[_spriteFrames count]]; +} + +-(void) dealloc +{ + CCLOGINFO(@"cocos2d: deallocing %@", self); + + [_spriteFrames release]; + [_spriteFramesAliases release]; + [_loadedFilenames release]; + + [super dealloc]; +} + +#pragma mark CCSpriteFrameCache - loading sprite frames + +-(void) addSpriteFramesWithDictionary:(NSDictionary*)dictionary textureReference:(id)textureReference +{ + /* + Supported Zwoptex Formats: + ZWTCoordinatesFormatOptionXMLLegacy = 0, // Flash Version + ZWTCoordinatesFormatOptionXML1_0 = 1, // Desktop Version 0.0 - 0.4b + ZWTCoordinatesFormatOptionXML1_1 = 2, // Desktop Version 1.0.0 - 1.0.1 + ZWTCoordinatesFormatOptionXML1_2 = 3, // Desktop Version 1.0.2+ + */ + NSDictionary *metadataDict = [dictionary objectForKey:@"metadata"]; + NSDictionary *framesDict = [dictionary objectForKey:@"frames"]; + + int format = 0; + + // get the format + if(metadataDict != nil) + format = [[metadataDict objectForKey:@"format"] intValue]; + + // check the format + NSAssert( format >= 0 && format <= 3, @"format is not supported for CCSpriteFrameCache addSpriteFramesWithDictionary:textureFilename:"); + + // SpriteFrame info + CGRect rectInPixels; + BOOL isRotated; + CGPoint frameOffset; + CGSize originalSize; + + // add real frames + for(NSString *frameDictKey in framesDict) { + NSDictionary *frameDict = [framesDict objectForKey:frameDictKey]; + CCSpriteFrame *spriteFrame=nil; + if(format == 0) { + float x = [[frameDict objectForKey:@"x"] floatValue]; + float y = [[frameDict objectForKey:@"y"] floatValue]; + float w = [[frameDict objectForKey:@"width"] floatValue]; + float h = [[frameDict objectForKey:@"height"] floatValue]; + float ox = [[frameDict objectForKey:@"offsetX"] floatValue]; + float oy = [[frameDict objectForKey:@"offsetY"] floatValue]; + int ow = [[frameDict objectForKey:@"originalWidth"] intValue]; + int oh = [[frameDict objectForKey:@"originalHeight"] intValue]; + // check ow/oh + if(!ow || !oh) + CCLOGWARN(@"cocos2d: WARNING: originalWidth/Height not found on the CCSpriteFrame. AnchorPoint won't work as expected. Regenerate the .plist"); + + // abs ow/oh + ow = abs(ow); + oh = abs(oh); + + // set frame info + rectInPixels = CGRectMake(x, y, w, h); + isRotated = NO; + frameOffset = CGPointMake(ox, oy); + originalSize = CGSizeMake(ow, oh); + } else if(format == 1 || format == 2) { + CGRect frame = CCRectFromString([frameDict objectForKey:@"frame"]); + BOOL rotated = NO; + + // rotation + if(format == 2) + rotated = [[frameDict objectForKey:@"rotated"] boolValue]; + + CGPoint offset = CCPointFromString([frameDict objectForKey:@"offset"]); + CGSize sourceSize = CCSizeFromString([frameDict objectForKey:@"sourceSize"]); + + // set frame info + rectInPixels = frame; + isRotated = rotated; + frameOffset = offset; + originalSize = sourceSize; + } else if(format == 3) { + // get values + CGSize spriteSize = CCSizeFromString([frameDict objectForKey:@"spriteSize"]); + CGPoint spriteOffset = CCPointFromString([frameDict objectForKey:@"spriteOffset"]); + CGSize spriteSourceSize = CCSizeFromString([frameDict objectForKey:@"spriteSourceSize"]); + CGRect textureRect = CCRectFromString([frameDict objectForKey:@"textureRect"]); + BOOL textureRotated = [[frameDict objectForKey:@"textureRotated"] boolValue]; + + // get aliases + NSArray *aliases = [frameDict objectForKey:@"aliases"]; + for(NSString *alias in aliases) { + if( [_spriteFramesAliases objectForKey:alias] ) + CCLOGWARN(@"cocos2d: WARNING: an alias with name %@ already exists",alias); + + [_spriteFramesAliases setObject:frameDictKey forKey:alias]; + } + + // set frame info + rectInPixels = CGRectMake(textureRect.origin.x, textureRect.origin.y, spriteSize.width, spriteSize.height); + isRotated = textureRotated; + frameOffset = spriteOffset; + originalSize = spriteSourceSize; + } + + NSString *textureFileName = nil; + CCTexture2D * texture = nil; + + if ( [textureReference isKindOfClass:[NSString class]] ) + { + textureFileName = textureReference; + } + else if ( [textureReference isKindOfClass:[CCTexture2D class]] ) + { + texture = textureReference; + } + + if ( textureFileName ) + { + spriteFrame = [[CCSpriteFrame alloc] initWithTextureFilename:textureFileName rectInPixels:rectInPixels rotated:isRotated offset:frameOffset originalSize:originalSize]; + } + else + { + spriteFrame = [[CCSpriteFrame alloc] initWithTexture:texture rectInPixels:rectInPixels rotated:isRotated offset:frameOffset originalSize:originalSize]; + } + + // add sprite frame + [_spriteFrames setObject:spriteFrame forKey:frameDictKey]; + [spriteFrame release]; + } +} + +-(void) addSpriteFramesWithDictionary:(NSDictionary*)dictionary textureFilename:(NSString*)textureFilename +{ + return [self addSpriteFramesWithDictionary:dictionary textureReference:textureFilename]; +} + +-(void) addSpriteFramesWithDictionary:(NSDictionary *)dictionary texture:(CCTexture2D *)texture +{ + return [self addSpriteFramesWithDictionary:dictionary textureReference:texture]; +} + +-(void) addSpriteFramesWithFile:(NSString*)plist textureReference:(id)textureReference +{ + NSAssert(textureReference, @"textureReference should not be nil"); + NSAssert(plist, @"plist filename should not be nil"); + + if( ! [_loadedFilenames member:plist] ) { + + NSString *path = [[CCFileUtils sharedFileUtils] fullPathForFilename:plist]; + NSDictionary *dict = [NSDictionary dictionaryWithContentsOfFile:path]; + + [self addSpriteFramesWithDictionary:dict textureReference:textureReference]; + + [_loadedFilenames addObject:plist]; + } + else + CCLOGINFO(@"cocos2d: CCSpriteFrameCache: file already loaded: %@", plist); +} + +-(void) addSpriteFramesWithFile:(NSString*)plist textureFilename:(NSString*)textureFilename +{ + return [self addSpriteFramesWithFile:plist textureReference:textureFilename]; +} + +-(void) addSpriteFramesWithFile:(NSString*)plist texture:(CCTexture2D*)texture +{ + return [self addSpriteFramesWithFile:plist textureReference:texture]; +} + + +-(void) addSpriteFramesWithFile:(NSString*)plist +{ + NSAssert(plist, @"plist filename should not be nil"); + + if( ! [_loadedFilenames member:plist] ) { + + NSString *path = [[CCFileUtils sharedFileUtils] fullPathForFilename:plist]; + NSDictionary *dict = [NSDictionary dictionaryWithContentsOfFile:path]; + + NSString *texturePath = nil; + NSDictionary *metadataDict = [dict objectForKey:@"metadata"]; + if( metadataDict ) + // try to read texture file name from meta data + texturePath = [metadataDict objectForKey:@"textureFileName"]; + + + if( texturePath ) + { + // build texture path relative to plist file + NSString *textureBase = [plist stringByDeletingLastPathComponent]; + texturePath = [textureBase stringByAppendingPathComponent:texturePath]; + } else { + // build texture path by replacing file extension + texturePath = [plist stringByDeletingPathExtension]; + texturePath = [texturePath stringByAppendingPathExtension:@"png"]; + + CCLOG(@"cocos2d: CCSpriteFrameCache: Trying to use file '%@' as texture", texturePath); + } + + [self addSpriteFramesWithDictionary:dict textureFilename:texturePath]; + + [_loadedFilenames addObject:plist]; + } + else + CCLOGINFO(@"cocos2d: CCSpriteFrameCache: file already loaded: %@", plist); + +} + +-(void) addSpriteFrame:(CCSpriteFrame*)frame name:(NSString*)frameName +{ + [_spriteFrames setObject:frame forKey:frameName]; +} + +#pragma mark CCSpriteFrameCache - removing + +-(void) removeSpriteFrames +{ + [_spriteFrames removeAllObjects]; + [_spriteFramesAliases removeAllObjects]; + [_loadedFilenames removeAllObjects]; +} + +-(void) removeUnusedSpriteFrames +{ + BOOL removed_ = NO; + NSArray *keys = [_spriteFrames allKeys]; + for( id key in keys ) { + id value = [_spriteFrames objectForKey:key]; + if( [value retainCount] == 1 ) { + CCLOG(@"cocos2d: CCSpriteFrameCache: removing unused frame: %@", key); + [_spriteFrames removeObjectForKey:key]; + removed_ = YES; + } + } + + // XXX. Since we don't know the .plist file that originated the frame, we must remove all .plist from the cache + if( removed_ ) + [_loadedFilenames removeAllObjects]; +} + +-(void) removeSpriteFrameByName:(NSString*)name +{ + // explicit nil handling + if( ! name ) + return; + + // Is this an alias ? + NSString *key = [_spriteFramesAliases objectForKey:name]; + + if( key ) { + [_spriteFrames removeObjectForKey:key]; + [_spriteFramesAliases removeObjectForKey:name]; + + } else + [_spriteFrames removeObjectForKey:name]; + + // XXX. Since we don't know the .plist file that originated the frame, we must remove all .plist from the cache + [_loadedFilenames removeAllObjects]; +} + +- (void) removeSpriteFramesFromFile:(NSString*) plist +{ + NSString *path = [[CCFileUtils sharedFileUtils] fullPathForFilename:plist]; + NSDictionary *dict = [NSDictionary dictionaryWithContentsOfFile:path]; + + [self removeSpriteFramesFromDictionary:dict]; + + // remove it from the cache + id ret = [_loadedFilenames member:plist]; + if( ret ) + [_loadedFilenames removeObject:ret]; +} + +- (void) removeSpriteFramesFromDictionary:(NSDictionary*) dictionary +{ + NSDictionary *framesDict = [dictionary objectForKey:@"frames"]; + NSMutableArray *keysToRemove=[NSMutableArray array]; + + for(NSString *frameDictKey in framesDict) + { + if ([_spriteFrames objectForKey:frameDictKey]!=nil) + [keysToRemove addObject:frameDictKey]; + } + [_spriteFrames removeObjectsForKeys:keysToRemove]; +} + +- (void) removeSpriteFramesFromTexture:(CCTexture2D*) texture +{ + NSMutableArray *keysToRemove=[NSMutableArray array]; + + for (NSString *spriteFrameKey in _spriteFrames) + { + if ([[_spriteFrames valueForKey:spriteFrameKey] texture] == texture) + [keysToRemove addObject:spriteFrameKey]; + + } + [_spriteFrames removeObjectsForKeys:keysToRemove]; +} + +#pragma mark CCSpriteFrameCache - getting + +-(CCSpriteFrame*) spriteFrameByName:(NSString*)name +{ + CCSpriteFrame *frame = [_spriteFrames objectForKey:name]; + if( ! frame ) { + // try alias dictionary + NSString *key = [_spriteFramesAliases objectForKey:name]; + frame = [_spriteFrames objectForKey:key]; + + if( ! frame ) + CCLOG(@"cocos2d: CCSpriteFrameCache: Frame '%@' not found", name); + } + + return frame; +} + +@end diff --git "a/21451198\345\215\242\350\266\205/project5/MyPlane/libs/cocos2d/CCTMXLayer.h" "b/21451198\345\215\242\350\266\205/project5/MyPlane/libs/cocos2d/CCTMXLayer.h" new file mode 100644 index 00000000..7bf5150b --- /dev/null +++ "b/21451198\345\215\242\350\266\205/project5/MyPlane/libs/cocos2d/CCTMXLayer.h" @@ -0,0 +1,164 @@ +/* + * cocos2d for iPhone: http://www.cocos2d-iphone.org + * + * Copyright (c) 2009-2010 Ricardo Quesada + * Copyright (c) 2011 Zynga Inc. + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + * THE SOFTWARE. + * + * + * TMX Tiled Map support: + * http://www.mapeditor.org + * + */ + + +#import "CCAtlasNode.h" +#import "CCSpriteBatchNode.h" +#import "CCTMXXMLParser.h" + +@class CCTMXMapInfo; +@class CCTMXLayerInfo; +@class CCTMXTilesetInfo; + + +/** CCTMXLayer represents the TMX layer. + + It is a subclass of CCSpriteBatchNode. By default the tiles are rendered using a CCTextureAtlas. + If you mofify a tile on runtime, then, that tile will become a CCSprite, otherwise no CCSprite objects are created. + The benefits of using CCSprite objects as tiles are: + - tiles (CCSprite) can be rotated/scaled/moved with a nice API + + cocos2d v2.0 doesn't support the cc_vertexz value. Whenever a the cc_vertexz property is found, it will raise an exception. + + "value" by default is 0, but you can change it from Tiled by adding the "cc_alpha_func" property to the layer. + The value 0 should work for most cases, but if you have tiles that are semi-transparent, then you might want to use a differnt + value, like 0.5. + + For further information, please see the programming guide: + + http://www.cocos2d-iphone.org/wiki/doku.php/prog_guide:tiled_maps + + @since v0.8.1 + + Tiles can have tile flags for additional properties. At the moment only flip horizontal and flip vertical are used. These bit flags are defined in CCTMXXMLParser.h. + + @since 1.1 + */ +@interface CCTMXLayer : CCSpriteBatchNode +{ + CCTMXTilesetInfo *_tileset; + NSString *_layerName; + CGSize _layerSize; + CGSize _mapTileSize; + uint32_t *_tiles; // GID are 32 bit + NSUInteger _layerOrientation; + NSMutableDictionary *_properties; + + unsigned char _opacity; // TMX Layer supports opacity + + NSUInteger _minGID; + NSUInteger _maxGID; + + // Only used when vertexZ is used + NSInteger _vertexZvalue; + BOOL _useAutomaticVertexZ; + + // used for optimization + CCSprite *_reusedTile; + ccCArray *_atlasIndexArray; +} +/** name of the layer */ +@property (nonatomic,readwrite,retain) NSString *layerName; +/** size of the layer in tiles */ +@property (nonatomic,readwrite) CGSize layerSize; +/** size of the map's tile (could be different from the tile's size) */ +@property (nonatomic,readwrite) CGSize mapTileSize; +/** pointer to the map of tiles */ +@property (nonatomic,readwrite) uint32_t *tiles; +/** Tileset information for the layer */ +@property (nonatomic,readwrite,retain) CCTMXTilesetInfo *tileset; +/** Layer orientation, which is the same as the map orientation */ +@property (nonatomic,readwrite) NSUInteger layerOrientation; +/** properties from the layer. They can be added using Tiled */ +@property (nonatomic,readwrite,retain) NSMutableDictionary *properties; + +/** creates a CCTMXLayer with an tileset info, a layer info and a map info */ ++(id) layerWithTilesetInfo:(CCTMXTilesetInfo*)tilesetInfo layerInfo:(CCTMXLayerInfo*)layerInfo mapInfo:(CCTMXMapInfo*)mapInfo; +/** initializes a CCTMXLayer with a tileset info, a layer info and a map info */ +-(id) initWithTilesetInfo:(CCTMXTilesetInfo*)tilesetInfo layerInfo:(CCTMXLayerInfo*)layerInfo mapInfo:(CCTMXMapInfo*)mapInfo; + +/** dealloc the map that contains the tile position from memory. + Unless you want to know at runtime the tiles positions, you can safely call this method. + If you are going to call [layer tileGIDAt:] then, don't release the map + */ +-(void) releaseMap; + +/** returns the tile (CCSprite) at a given a tile coordinate. + The returned CCSprite will be already added to the CCTMXLayer. Don't add it again. + The CCSprite can be treated like any other CCSprite: rotated, scaled, translated, opacity, color, etc. + You can remove either by calling: + - [layer removeChild:sprite cleanup:cleanup]; + - or [layer removeTileAt:ccp(x,y)]; + */ +-(CCSprite*) tileAt:(CGPoint)tileCoordinate; + +/** returns the tile gid at a given tile coordinate. + if it returns 0, it means that the tile is empty. + This method requires the the tile map has not been previously released (eg. don't call [layer releaseMap]) + */ +-(uint32_t) tileGIDAt:(CGPoint)tileCoordinate; + +/** returns the tile gid at a given tile coordinate. It also returns the tile flags. + This method requires the the tile map has not been previously released (eg. don't call [layer releaseMap]) + */ +-(uint32_t) tileGIDAt:(CGPoint)pos withFlags:(ccTMXTileFlags*)flags; + +/** sets the tile gid (gid = tile global id) at a given tile coordinate. + The Tile GID can be obtained by using the method "tileGIDAt" or by using the TMX editor -> Tileset Mgr +1. + If a tile is already placed at that position, then it will be removed. + */ +-(void) setTileGID:(uint32_t)gid at:(CGPoint)tileCoordinate; + +/** sets the tile gid (gid = tile global id) at a given tile coordinate. + The Tile GID can be obtained by using the method "tileGIDAt" or by using the TMX editor -> Tileset Mgr +1. + If a tile is already placed at that position, then it will be removed. + + Use withFlags if the tile flags need to be changed as well + */ + +-(void) setTileGID:(uint32_t)gid at:(CGPoint)pos withFlags:(ccTMXTileFlags)flags; + +/** removes a tile at given tile coordinate */ +-(void) removeTileAt:(CGPoint)tileCoordinate; + +/** returns the position in points of a given tile coordinate */ +-(CGPoint) positionAt:(CGPoint)tileCoordinate; + +/** return the value for the specific property name */ +-(id) propertyNamed:(NSString *)propertyName; + +/** Creates the tiles */ +-(void) setupTiles; + +/** CCTMXLayer doesn't support adding a CCSprite manually. + @warning addchild:z:tag: is not supported on CCTMXLayer. Instead of setTileGID:at:/tileAt: + */ +-(void) addChild: (CCNode*)node z:(NSInteger)z tag:(NSInteger)tag; +@end diff --git "a/21451198\345\215\242\350\266\205/project5/MyPlane/libs/cocos2d/CCTMXLayer.m" "b/21451198\345\215\242\350\266\205/project5/MyPlane/libs/cocos2d/CCTMXLayer.m" new file mode 100644 index 00000000..258e7956 --- /dev/null +++ "b/21451198\345\215\242\350\266\205/project5/MyPlane/libs/cocos2d/CCTMXLayer.m" @@ -0,0 +1,697 @@ +/* + * cocos2d for iPhone: http://www.cocos2d-iphone.org + * + * Copyright (c) 2009-2010 Ricardo Quesada + * Copyright (c) 2011 Zynga Inc. + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + * THE SOFTWARE. + * + * + * TMX Tiled Map support: + * http://www.mapeditor.org + * + */ + +#import "CCTMXLayer.h" +#import "CCTMXTiledMap.h" +#import "CCTMXXMLParser.h" +#import "CCSprite.h" +#import "CCSpriteBatchNode.h" +#import "CCTextureCache.h" +#import "CCShaderCache.h" +#import "CCGLProgram.h" +#import "Support/CGPointExtension.h" + + +#pragma mark - +#pragma mark CCTMXLayer + +int compareInts (const void * a, const void * b); + + +@interface CCTMXLayer () +-(CGPoint) positionForIsoAt:(CGPoint)pos; +-(CGPoint) positionForOrthoAt:(CGPoint)pos; +-(CGPoint) positionForHexAt:(CGPoint)pos; + +-(CGPoint) calculateLayerOffset:(CGPoint)offset; + +/* optimization methos */ +-(CCSprite*) appendTileForGID:(uint32_t)gid at:(CGPoint)pos; +-(CCSprite*) insertTileForGID:(uint32_t)gid at:(CGPoint)pos; +-(CCSprite*) updateTileForGID:(uint32_t)gid at:(CGPoint)pos; + +/* The layer recognizes some special properties, like cc_vertez */ +-(void) parseInternalProperties; +- (void) setupTileSprite:(CCSprite*) sprite position:(CGPoint)pos withGID:(uint32_t)gid; + +-(NSInteger) vertexZForPos:(CGPoint)pos; + +// index +-(NSUInteger) atlasIndexForExistantZ:(NSUInteger)z; +-(NSUInteger) atlasIndexForNewZ:(NSUInteger)z; +@end + +@implementation CCTMXLayer +@synthesize layerSize = _layerSize, layerName = _layerName, tiles = _tiles; +@synthesize tileset = _tileset; +@synthesize layerOrientation = _layerOrientation; +@synthesize mapTileSize = _mapTileSize; +@synthesize properties = _properties; + +#pragma mark CCTMXLayer - init & alloc & dealloc + ++(id) layerWithTilesetInfo:(CCTMXTilesetInfo*)tilesetInfo layerInfo:(CCTMXLayerInfo*)layerInfo mapInfo:(CCTMXMapInfo*)mapInfo +{ + return [[[self alloc] initWithTilesetInfo:tilesetInfo layerInfo:layerInfo mapInfo:mapInfo] autorelease]; +} + +-(id) initWithTilesetInfo:(CCTMXTilesetInfo*)tilesetInfo layerInfo:(CCTMXLayerInfo*)layerInfo mapInfo:(CCTMXMapInfo*)mapInfo +{ + // XXX: is 35% a good estimate ? + CGSize size = layerInfo.layerSize; + float totalNumberOfTiles = size.width * size.height; + float capacity = totalNumberOfTiles * 0.35f + 1; // 35 percent is occupied ? + + CCTexture2D *tex = nil; + if( tilesetInfo ) + tex = [[CCTextureCache sharedTextureCache] addImage:tilesetInfo.sourceImage]; + + if((self = [super initWithTexture:tex capacity:capacity])) { + + // layerInfo + self.layerName = layerInfo.name; + _layerSize = size; + _tiles = layerInfo.tiles; + _minGID = layerInfo.minGID; + _maxGID = layerInfo.maxGID; + _opacity = layerInfo.opacity; + self.properties = [NSMutableDictionary dictionaryWithDictionary:layerInfo.properties]; + + // tilesetInfo + self.tileset = tilesetInfo; + + // mapInfo + _mapTileSize = mapInfo.tileSize; + _layerOrientation = mapInfo.orientation; + + // offset (after layer orientation is set); + CGPoint offset = [self calculateLayerOffset:layerInfo.offset]; + [self setPosition:CC_POINT_PIXELS_TO_POINTS(offset)]; + + _atlasIndexArray = ccCArrayNew(totalNumberOfTiles); + + [self setContentSize:CC_SIZE_PIXELS_TO_POINTS(CGSizeMake( _layerSize.width * _mapTileSize.width, _layerSize.height * _mapTileSize.height ))]; + + _useAutomaticVertexZ= NO; + _vertexZvalue = 0; + } + + return self; +} + +- (void) dealloc +{ + [_layerName release]; + [_tileset release]; + [_reusedTile release]; + [_properties release]; + + if( _atlasIndexArray ) { + ccCArrayFree(_atlasIndexArray); + _atlasIndexArray = NULL; + } + + if( _tiles ) { + free(_tiles); + _tiles = NULL; + } + + [super dealloc]; +} + +-(void) releaseMap +{ + if( _tiles) { + free( _tiles); + _tiles = NULL; + } + + if( _atlasIndexArray ) { + ccCArrayFree(_atlasIndexArray); + _atlasIndexArray = NULL; + } +} + +#pragma mark CCTMXLayer - setup Tiles + +-(CCSprite*) reusedTileWithRect:(CGRect)rect +{ + if( ! _reusedTile ) { + _reusedTile = [[CCSprite alloc] initWithTexture:_textureAtlas.texture rect:rect rotated:NO]; + [_reusedTile setBatchNode:self]; + } + else + { + // XXX HACK: Needed because if "batch node" is nil, + // then the Sprite'squad will be reset + [_reusedTile setBatchNode:nil]; + + // Re-init the sprite + [_reusedTile setTextureRect:rect rotated:NO untrimmedSize:rect.size]; + + // restore the batch node + [_reusedTile setBatchNode:self]; + } + + return _reusedTile; +} + +-(void) setupTiles +{ + // Optimization: quick hack that sets the image size on the tileset + _tileset.imageSize = [_textureAtlas.texture contentSizeInPixels]; + + // By default all the tiles are aliased + // pros: + // - easier to render + // cons: + // - difficult to scale / rotate / etc. + [_textureAtlas.texture setAliasTexParameters]; + + // Parse cocos2d properties + [self parseInternalProperties]; + + for( NSUInteger y = 0; y < _layerSize.height; y++ ) { + for( NSUInteger x = 0; x < _layerSize.width; x++ ) { + + NSUInteger pos = x + _layerSize.width * y; + uint32_t gid = _tiles[ pos ]; + + // gid are stored in little endian. + // if host is big endian, then swap + gid = CFSwapInt32LittleToHost( gid ); + + // XXX: gid == 0 --> empty tile + if( gid != 0 ) { + [self appendTileForGID:gid at:ccp(x,y)]; + + // Optimization: update min and max GID rendered by the layer + _minGID = MIN(gid, _minGID); + _maxGID = MAX(gid, _maxGID); +// _minGID = MIN((gid & kFlippedMask), _minGID); +// _maxGID = MAX((gid & kFlippedMask), _maxGID); + } + } + } + + NSAssert( _maxGID >= _tileset.firstGid && + _minGID >= _tileset.firstGid, @"TMX: Only 1 tilset per layer is supported"); +} + +#pragma mark CCTMXLayer - Properties + +-(id) propertyNamed:(NSString *)propertyName +{ + return [_properties valueForKey:propertyName]; +} + +-(void) parseInternalProperties +{ + // if cc_vertex=automatic, then tiles will be rendered using vertexz + + NSString *vertexz = [self propertyNamed:@"cc_vertexz"]; + if( vertexz ) { + + // If "automatic" is on, then parse the "cc_alpha_func" too + if( [vertexz isEqualToString:@"automatic"] ) { + _useAutomaticVertexZ = YES; + + NSString *alphaFuncVal = [self propertyNamed:@"cc_alpha_func"]; + float alphaFuncValue = [alphaFuncVal floatValue]; + + self.shaderProgram = [[CCShaderCache sharedShaderCache] programForKey:kCCShader_PositionTextureColorAlphaTest]; + + GLint alphaValueLocation = glGetUniformLocation(self.shaderProgram.program, kCCUniformAlphaTestValue_s); + + // NOTE: alpha test shader is hard-coded to use the equivalent of a glAlphaFunc(GL_GREATER) comparison + [self.shaderProgram setUniformLocation:alphaValueLocation withF1:alphaFuncValue]; + } + else + _vertexZvalue = [vertexz intValue]; + } +} + +#pragma mark CCTMXLayer - obtaining tiles/gids + +-(CCSprite*) tileAt:(CGPoint)pos +{ + NSAssert( pos.x < _layerSize.width && pos.y < _layerSize.height && pos.x >=0 && pos.y >=0, @"TMXLayer: invalid position"); + NSAssert( _tiles && _atlasIndexArray, @"TMXLayer: the tiles map has been released"); + + CCSprite *tile = nil; + uint32_t gid = [self tileGIDAt:pos]; + + // if GID == 0, then no tile is present + if( gid ) { + int z = pos.x + pos.y * _layerSize.width; + tile = (CCSprite*) [self getChildByTag:z]; + + // tile not created yet. create it + if( ! tile ) { + CGRect rect = [_tileset rectForGID:gid]; + rect = CC_RECT_PIXELS_TO_POINTS(rect); + tile = [[CCSprite alloc] initWithTexture:self.texture rect:rect]; + [tile setBatchNode:self]; + + CGPoint p = [self positionAt:pos]; + [tile setPosition:p]; + [tile setVertexZ: [self vertexZForPos:pos]]; + tile.anchorPoint = CGPointZero; + [tile setOpacity:_opacity]; + + NSUInteger indexForZ = [self atlasIndexForExistantZ:z]; + [self addSpriteWithoutQuad:tile z:indexForZ tag:z]; + [tile release]; + } + } + return tile; +} + +-(uint32_t) tileGIDAt:(CGPoint)pos +{ + return [self tileGIDAt:pos withFlags:NULL]; +} + +-(uint32_t) tileGIDAt:(CGPoint)pos withFlags:(ccTMXTileFlags*)flags +{ + NSAssert( pos.x < _layerSize.width && pos.y < _layerSize.height && pos.x >=0 && pos.y >=0, @"TMXLayer: invalid position"); + NSAssert( _tiles && _atlasIndexArray, @"TMXLayer: the tiles map has been released"); + + NSInteger idx = pos.x + pos.y * _layerSize.width; + + // Bits on the far end of the 32-bit global tile ID are used for tile flags + + uint32_t tile = _tiles[idx]; + + // issue1264, flipped tiles can be changed dynamically + if (flags) + *flags = tile & kCCFlipedAll; + + return ( tile & kCCFlippedMask); +} + +#pragma mark CCTMXLayer - adding helper methods + +- (void) setupTileSprite:(CCSprite*) sprite position:(CGPoint)pos withGID:(uint32_t)gid +{ + [sprite setPosition: [self positionAt:pos]]; + [sprite setVertexZ: [self vertexZForPos:pos]]; + //sprite.anchorPoint = CGPointZero; // was the default + [sprite setOpacity:_opacity]; + + //issue 1264, flip can be undone as well + sprite.flipX = NO; + sprite.flipY = NO; + sprite.rotation = 0; + //sprite.anchorPoint = ccp(0,0); // was the default + + // All tile sprites in the layer should have the same anchorpoint. + // The default anchor point is defined in the TMX file (within the tileset node) and stored in the + // CCTMXTilesetInfo* property of the CCTMXLayer. + sprite.anchorPoint = _tileset.tileAnchorPoint; + + // Rotation in tiled is achieved using 3 flipped states, flipping across the horizontal, vertical, and diagonal axes of the tiles. + if (gid & kCCTMXTileDiagonalFlag) + { + // put the anchor in the middle for ease of rotation. + sprite.anchorPoint = ccp(0.5f,0.5f); + [sprite setPosition: ccp([self positionAt:pos].x + sprite.contentSize.height/2, + [self positionAt:pos].y + sprite.contentSize.width/2 ) + ]; + + uint32_t flag = gid & (kCCTMXTileHorizontalFlag | kCCTMXTileVerticalFlag ); + + // handle the 4 diagonally flipped states. + if (flag == kCCTMXTileHorizontalFlag) + { + sprite.rotation = 90; + } + else if (flag == kCCTMXTileVerticalFlag) + { + sprite.rotation = 270; + } + else if (flag == (kCCTMXTileVerticalFlag | kCCTMXTileHorizontalFlag) ) + { + sprite.rotation = 90; + sprite.flipX = YES; + } + else + { + sprite.rotation = 270; + sprite.flipX = YES; + } + } + else + { + if (gid & kCCTMXTileHorizontalFlag) + sprite.flipX = YES; + + if (gid & kCCTMXTileVerticalFlag) + sprite.flipY = YES; + } +} + +-(CCSprite*) insertTileForGID:(uint32_t)gid at:(CGPoint)pos +{ + CGRect rect = [_tileset rectForGID:gid]; + rect = CC_RECT_PIXELS_TO_POINTS(rect); + + NSInteger z = pos.x + pos.y * _layerSize.width; + + CCSprite *tile = [self reusedTileWithRect:rect]; + + [self setupTileSprite:tile position:pos withGID:gid]; + + // get atlas index + NSUInteger indexForZ = [self atlasIndexForNewZ:z]; + + // Optimization: add the quad without adding a child + [self insertQuadFromSprite:tile quadIndex:indexForZ]; + + // insert it into the local atlasindex array + ccCArrayInsertValueAtIndex(_atlasIndexArray, (void*)z, indexForZ); + + // update possible children + CCSprite *sprite; + CCARRAY_FOREACH(_children, sprite) { + NSUInteger ai = [sprite atlasIndex]; + if( ai >= indexForZ) + [sprite setAtlasIndex: ai+1]; + } + + _tiles[z] = gid; + + return tile; +} + +-(CCSprite*) updateTileForGID:(uint32_t)gid at:(CGPoint)pos +{ + CGRect rect = [_tileset rectForGID:gid]; + rect = CC_RECT_PIXELS_TO_POINTS(rect); + + int z = pos.x + pos.y * _layerSize.width; + + CCSprite *tile = [self reusedTileWithRect:rect]; + + [self setupTileSprite:tile position:pos withGID:gid]; + + // get atlas index + NSUInteger indexForZ = [self atlasIndexForExistantZ:z]; + + [tile setAtlasIndex:indexForZ]; + [tile setDirty:YES]; + [tile updateTransform]; + _tiles[z] = gid; + + return tile; +} + + +// used only when parsing the map. useless after the map was parsed +// since lot's of assumptions are no longer true +-(CCSprite*) appendTileForGID:(uint32_t)gid at:(CGPoint)pos +{ + CGRect rect = [_tileset rectForGID:gid]; + rect = CC_RECT_PIXELS_TO_POINTS(rect); + + NSInteger z = pos.x + pos.y * _layerSize.width; + + CCSprite *tile = [self reusedTileWithRect:rect]; + + [self setupTileSprite:tile position:pos withGID:gid]; + + // optimization: + // The difference between appendTileForGID and insertTileforGID is that append is faster, since + // it appends the tile at the end of the texture atlas + NSUInteger indexForZ = _atlasIndexArray->num; + + + // don't add it using the "standard" way. + [self insertQuadFromSprite:tile quadIndex:indexForZ]; + + + // append should be after addQuadFromSprite since it modifies the quantity values + ccCArrayInsertValueAtIndex(_atlasIndexArray, (void*)z, indexForZ); + + return tile; +} + +#pragma mark CCTMXLayer - atlasIndex and Z + +int compareInts (const void * a, const void * b) +{ + return ( *(int*)a - *(int*)b ); +} + +-(NSUInteger) atlasIndexForExistantZ:(NSUInteger)z +{ + NSInteger key = z; + NSInteger *item = bsearch((void*)&key, (void*)&_atlasIndexArray->arr[0], _atlasIndexArray->num, sizeof(void*), compareInts); + + NSAssert( item, @"TMX atlas index not found. Shall not happen"); + + NSUInteger index = ((NSInteger)item - (NSInteger)_atlasIndexArray->arr) / sizeof(void*); + return index; +} + +-(NSUInteger)atlasIndexForNewZ:(NSUInteger)z +{ + // XXX: This can be improved with a sort of binary search + NSUInteger i = 0; + for(i = 0; i< _atlasIndexArray->num; i++) { + NSUInteger val = (NSUInteger) _atlasIndexArray->arr[i]; + if( z < val ) + break; + } + return i; +} + +#pragma mark CCTMXLayer - adding / remove tiles +-(void) setTileGID:(uint32_t)gid at:(CGPoint)pos +{ + [self setTileGID:gid at:pos withFlags:NO]; +} + +-(void) setTileGID:(uint32_t)gid at:(CGPoint)pos withFlags:(ccTMXTileFlags)flags +{ + NSAssert( pos.x < _layerSize.width && pos.y < _layerSize.height && pos.x >=0 && pos.y >=0, @"TMXLayer: invalid position"); + NSAssert( _tiles && _atlasIndexArray, @"TMXLayer: the tiles map has been released"); + NSAssert( gid == 0 || gid >= _tileset.firstGid, @"TMXLayer: invalid gid" ); + + ccTMXTileFlags currentFlags; + uint32_t currentGID = [self tileGIDAt:pos withFlags:¤tFlags]; + + if (currentGID != gid || currentFlags != flags ) + { + uint32_t gidAndFlags = gid | flags; + + // setting gid=0 is equal to remove the tile + if( gid == 0 ) + [self removeTileAt:pos]; + + // empty tile. create a new one + else if( currentGID == 0 ) + [self insertTileForGID:gidAndFlags at:pos]; + + // modifying an existing tile with a non-empty tile + else { + + NSUInteger z = pos.x + pos.y * _layerSize.width; + CCSprite *sprite = (CCSprite*)[self getChildByTag:z]; + if( sprite ) { + CGRect rect = [_tileset rectForGID:gid]; + rect = CC_RECT_PIXELS_TO_POINTS(rect); + + [sprite setTextureRect:rect rotated:NO untrimmedSize:rect.size]; + + if (flags) + [self setupTileSprite:sprite position:[sprite position] withGID:gidAndFlags]; + + _tiles[z] = gidAndFlags; + } else + [self updateTileForGID:gidAndFlags at:pos]; + } + } +} + +-(void) addChild: (CCNode*)node z:(NSInteger)z tag:(NSInteger)tag +{ + NSAssert(NO, @"addChild: is not supported on CCTMXLayer. Instead use setTileGID:at:/tileAt:"); +} + +-(void) removeChild:(CCSprite*)sprite cleanup:(BOOL)cleanup +{ + // allows removing nil objects + if( ! sprite ) + return; + + NSAssert( [_children containsObject:sprite], @"Tile does not belong to TMXLayer"); + + NSUInteger atlasIndex = [sprite atlasIndex]; + NSUInteger zz = (NSUInteger) _atlasIndexArray->arr[atlasIndex]; + _tiles[zz] = 0; + ccCArrayRemoveValueAtIndex(_atlasIndexArray, atlasIndex); + [super removeChild:sprite cleanup:cleanup]; +} + +-(void) removeTileAt:(CGPoint)pos +{ + NSAssert( pos.x < _layerSize.width && pos.y < _layerSize.height && pos.x >=0 && pos.y >=0, @"TMXLayer: invalid position"); + NSAssert( _tiles && _atlasIndexArray, @"TMXLayer: the tiles map has been released"); + + uint32_t gid = [self tileGIDAt:pos]; + + if( gid ) { + + NSUInteger z = pos.x + pos.y * _layerSize.width; + NSUInteger atlasIndex = [self atlasIndexForExistantZ:z]; + + // remove tile from GID map + _tiles[z] = 0; + + // remove tile from atlas position array + ccCArrayRemoveValueAtIndex(_atlasIndexArray, atlasIndex); + + // remove it from sprites and/or texture atlas + id sprite = [self getChildByTag:z]; + if( sprite ) + [super removeChild:sprite cleanup:YES]; + else { + [_textureAtlas removeQuadAtIndex:atlasIndex]; + + // update possible children + CCARRAY_FOREACH(_children, sprite) { + NSUInteger ai = [sprite atlasIndex]; + if( ai >= atlasIndex) { + [sprite setAtlasIndex: ai-1]; + } + } + } + } +} + +#pragma mark CCTMXLayer - obtaining positions, offset + +-(CGPoint) calculateLayerOffset:(CGPoint)pos +{ + CGPoint ret = CGPointZero; + switch( _layerOrientation ) { + case CCTMXOrientationOrtho: + ret = ccp( pos.x * _mapTileSize.width, -pos.y *_mapTileSize.height); + break; + case CCTMXOrientationIso: + ret = ccp( (_mapTileSize.width /2) * (pos.x - pos.y), + (_mapTileSize.height /2 ) * (-pos.x - pos.y) ); + break; + case CCTMXOrientationHex: + NSAssert(CGPointEqualToPoint(pos, CGPointZero), @"offset for hexagonal map not implemented yet"); + break; + } + return ret; +} + +-(CGPoint) positionAt:(CGPoint)pos +{ + CGPoint ret = CGPointZero; + switch( _layerOrientation ) { + case CCTMXOrientationOrtho: + ret = [self positionForOrthoAt:pos]; + break; + case CCTMXOrientationIso: + ret = [self positionForIsoAt:pos]; + break; + case CCTMXOrientationHex: + ret = [self positionForHexAt:pos]; + break; + } + + ret = CC_POINT_PIXELS_TO_POINTS( ret ); + return ret; +} + +-(CGPoint) positionForOrthoAt:(CGPoint)pos +{ + CGPoint xy = { + pos.x * _mapTileSize.width, + (_layerSize.height - pos.y - 1) * _mapTileSize.height, + }; + return xy; +} + +-(CGPoint) positionForIsoAt:(CGPoint)pos +{ + CGPoint xy = { + _mapTileSize.width /2 * ( _layerSize.width + pos.x - pos.y - 1), + _mapTileSize.height /2 * (( _layerSize.height * 2 - pos.x - pos.y) - 2), + }; + return xy; +} + +-(CGPoint) positionForHexAt:(CGPoint)pos +{ + float diffY = 0; + if( (int)pos.x % 2 == 1 ) + diffY = -_mapTileSize.height/2 ; + + CGPoint xy = { + pos.x * _mapTileSize.width*3/4, + (_layerSize.height - pos.y - 1) * _mapTileSize.height + diffY + }; + return xy; +} + +-(NSInteger) vertexZForPos:(CGPoint)pos +{ + NSInteger ret = 0; + NSUInteger maxVal = 0; + if( _useAutomaticVertexZ ) { + switch( _layerOrientation ) { + case CCTMXOrientationIso: + maxVal = _layerSize.width + _layerSize.height; + ret = -(maxVal - (pos.x + pos.y)); + break; + case CCTMXOrientationOrtho: + ret = -(_layerSize.height-pos.y); + break; + case CCTMXOrientationHex: + NSAssert(NO,@"TMX Hexa zOrder not supported"); + break; + default: + NSAssert(NO,@"TMX invalid value"); + break; + } + } else + ret = _vertexZvalue; + + return ret; +} + +@end + diff --git "a/21451198\345\215\242\350\266\205/project5/MyPlane/libs/cocos2d/CCTMXObjectGroup.h" "b/21451198\345\215\242\350\266\205/project5/MyPlane/libs/cocos2d/CCTMXObjectGroup.h" new file mode 100644 index 00000000..0ce4b273 --- /dev/null +++ "b/21451198\345\215\242\350\266\205/project5/MyPlane/libs/cocos2d/CCTMXObjectGroup.h" @@ -0,0 +1,67 @@ +/* + * cocos2d for iPhone: http://www.cocos2d-iphone.org + * + * Copyright (c) 2010 Neophit + * + * Copyright (c) 2010 Ricardo Quesada + * Copyright (c) 2011 Zynga Inc. + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + * THE SOFTWARE. + * + * + * TMX Tiled Map support: + * http://www.mapeditor.org + * + */ + +#import "CCNode.h" + + +@class CCTMXObjectGroup; + + +/** CCTMXObjectGroup represents the TMX object group. +@since v0.99.0 +*/ +@interface CCTMXObjectGroup : NSObject +{ + NSString *_groupName; + CGPoint _positionOffset; + NSMutableArray *_objects; + NSMutableDictionary *_properties; +} + +/** name of the group */ +@property (nonatomic,readwrite,retain) NSString *groupName; +/** offset position of child objects */ +@property (nonatomic,readwrite,assign) CGPoint positionOffset; +/** array of the objects */ +@property (nonatomic,readwrite,retain) NSMutableArray *objects; +/** list of properties stored in a dictionary */ +@property (nonatomic,readwrite,retain) NSMutableDictionary *properties; + +/** return the value for the specific property name */ +-(id) propertyNamed:(NSString *)propertyName; + +/** return the dictionary for the specific object name. + It will return the 1st object found on the array for the given name. + */ +-(NSMutableDictionary*) objectNamed:(NSString *)objectName; + +@end diff --git "a/21451198\345\215\242\350\266\205/project5/MyPlane/libs/cocos2d/CCTMXObjectGroup.m" "b/21451198\345\215\242\350\266\205/project5/MyPlane/libs/cocos2d/CCTMXObjectGroup.m" new file mode 100644 index 00000000..38d1acaf --- /dev/null +++ "b/21451198\345\215\242\350\266\205/project5/MyPlane/libs/cocos2d/CCTMXObjectGroup.m" @@ -0,0 +1,86 @@ +/* + * cocos2d for iPhone: http://www.cocos2d-iphone.org + * + * Copyright (c) 2010 Neophit + * + * Copyright (c) 2010 Ricardo Quesada + * Copyright (c) 2011 Zynga Inc. + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + * THE SOFTWARE. + * + * + * TMX Tiled Map support: + * http://www.mapeditor.org + * + */ + +#import "CCTMXObjectGroup.h" +#import "CCTMXXMLParser.h" +#import "ccMacros.h" +#import "Support/CGPointExtension.h" + + +#pragma mark - +#pragma mark TMXObjectGroup + +@implementation CCTMXObjectGroup + +@synthesize groupName = _groupName; +@synthesize objects = _objects; +@synthesize positionOffset = _positionOffset; +@synthesize properties = _properties; + +-(id) init +{ + if (( self=[super init] )) { + self.groupName = nil; + self.positionOffset = CGPointZero; + self.objects = [NSMutableArray arrayWithCapacity:10]; + self.properties = [NSMutableDictionary dictionaryWithCapacity:5]; + } + return self; +} + +-(void) dealloc +{ + CCLOGINFO( @"cocos2d: deallocing %@", self ); + + [_groupName release]; + [_objects release]; + [_properties release]; + [super dealloc]; +} + +-(NSMutableDictionary*) objectNamed:(NSString *)objectName +{ + for( id object in _objects ) { + if( [[object valueForKey:@"name"] isEqual:objectName] ) + return object; + } + + // object not found + return nil; +} + +-(id) propertyNamed:(NSString *)propertyName +{ + return [_properties valueForKey:propertyName]; +} + +@end diff --git "a/21451198\345\215\242\350\266\205/project5/MyPlane/libs/cocos2d/CCTMXTiledMap.h" "b/21451198\345\215\242\350\266\205/project5/MyPlane/libs/cocos2d/CCTMXTiledMap.h" new file mode 100644 index 00000000..d6337264 --- /dev/null +++ "b/21451198\345\215\242\350\266\205/project5/MyPlane/libs/cocos2d/CCTMXTiledMap.h" @@ -0,0 +1,145 @@ +/* + * cocos2d for iPhone: http://www.cocos2d-iphone.org + * + * Copyright (c) 2009-2010 Ricardo Quesada + * Copyright (c) 2011 Zynga Inc. + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + * THE SOFTWARE. + * + * + * TMX Tiled Map support: + * http://www.mapeditor.org + * + */ + +#import "CCNode.h" + +@class CCTMXLayer; +@class CCTMXObjectGroup; + +/** Possible oritentations of the TMX map */ +enum +{ + /** Orthogonal orientation */ + CCTMXOrientationOrtho, + + /** Hexagonal orientation */ + CCTMXOrientationHex, + + /** Isometric orientation */ + CCTMXOrientationIso, +}; + +/** CCTMXTiledMap knows how to parse and render a TMX map. + + It adds support for the TMX tiled map format used by http://www.mapeditor.org + It supports isometric, hexagonal and orthogonal tiles. + It also supports object groups, objects, and properties. + + Features: + - Each tile will be treated as an CCSprite + - The sprites are created on demand. They will be created only when you call "[layer tileAt:]" + - Each tile can be rotated / moved / scaled / tinted / "opacitied", since each tile is a CCSprite + - Tiles can be added/removed in runtime + - The z-order of the tiles can be modified in runtime + - Each tile has an anchorPoint of (0,0) + - The anchorPoint of the TMXTileMap is (0,0) + - The TMX layers will be added as a child + - The TMX layers will be aliased by default + - The tileset image will be loaded using the CCTextureCache + - Each tile will have a unique tag + - Each tile will have a unique z value. top-left: z=1, bottom-right: z=max z + - Each object group will be treated as an NSMutableArray + - Object class which will contain all the properties in a dictionary + - Properties can be assigned to the Map, Layer, Object Group, and Object + + Limitations: + - It only supports one tileset per layer. + - Embedded images are not supported + - It only supports the XML format (the JSON format is not supported) + + Technical description: + Each layer is created using an CCTMXLayer (subclass of CCSpriteBatchNode). If you have 5 layers, then 5 CCTMXLayer will be created, + unless the layer visibility is off. In that case, the layer won't be created at all. + You can obtain the layers (CCTMXLayer objects) at runtime by: + - [map getChildByTag: tax_number]; // 0=1st layer, 1=2nd layer, 2=3rd layer, etc... + - [map layerNamed: name_of_the_layer]; + + Each object group is created using a CCTMXObjectGroup which is a subclass of NSMutableArray. + You can obtain the object groups at runtime by: + - [map objectGroupNamed: name_of_the_object_group]; + + Each object is a CCTMXObject. + + Each property is stored as a key-value pair in an NSMutableDictionary. + You can obtain the properties at runtime by: + + [map propertyNamed: name_of_the_property]; + [layer propertyNamed: name_of_the_property]; + [objectGroup propertyNamed: name_of_the_property]; + [object propertyNamed: name_of_the_property]; + + @since v0.8.1 + */ +@interface CCTMXTiledMap : CCNode +{ + CGSize _mapSize; + CGSize _tileSize; + int _mapOrientation; + NSMutableArray *_objectGroups; + NSMutableDictionary *_properties; + NSMutableDictionary *_tileProperties; +} + +/** the map's size property measured in tiles */ +@property (nonatomic,readonly) CGSize mapSize; +/** the tiles's size property measured in pixels */ +@property (nonatomic,readonly) CGSize tileSize; +/** map orientation */ +@property (nonatomic,readonly) int mapOrientation; +/** object groups */ +@property (nonatomic,readwrite,retain) NSMutableArray *objectGroups; +/** properties */ +@property (nonatomic,readwrite,retain) NSMutableDictionary *properties; + +/** creates a TMX Tiled Map with a TMX file.*/ ++(id) tiledMapWithTMXFile:(NSString*)tmxFile; + +/** initializes a TMX Tiled Map with a TMX formatted XML string and a path to TMX resources */ ++(id) tiledMapWithXML:(NSString*)tmxString resourcePath:(NSString*)resourcePath; + +/** initializes a TMX Tiled Map with a TMX file */ +-(id) initWithTMXFile:(NSString*)tmxFile; + +/** initializes a TMX Tiled Map with a TMX formatted XML string and a path to TMX resources */ +-(id) initWithXML:(NSString*)tmxString resourcePath:(NSString*)resourcePath; + +/** return the TMXLayer for the specific layer */ +-(CCTMXLayer*) layerNamed:(NSString *)layerName; + +/** return the TMXObjectGroup for the specific group */ +-(CCTMXObjectGroup*) objectGroupNamed:(NSString *)groupName; + +/** return the value for the specific property name */ +-(id) propertyNamed:(NSString *)propertyName; + +/** return properties dictionary for tile GID */ +-(NSDictionary*)propertiesForGID:(unsigned int)GID; +@end + diff --git "a/21451198\345\215\242\350\266\205/project5/MyPlane/libs/cocos2d/CCTMXTiledMap.m" "b/21451198\345\215\242\350\266\205/project5/MyPlane/libs/cocos2d/CCTMXTiledMap.m" new file mode 100644 index 00000000..96a10d38 --- /dev/null +++ "b/21451198\345\215\242\350\266\205/project5/MyPlane/libs/cocos2d/CCTMXTiledMap.m" @@ -0,0 +1,217 @@ +/* + * cocos2d for iPhone: http://www.cocos2d-iphone.org + * + * Copyright (c) 2009-2010 Ricardo Quesada + * Copyright (c) 2011 Zynga Inc. + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + * THE SOFTWARE. + * + * + * TMX Tiled Map support: + * http://www.mapeditor.org + * + */ + +#import "CCTMXTiledMap.h" +#import "CCTMXXMLParser.h" +#import "CCTMXLayer.h" +#import "CCTMXObjectGroup.h" +#import "CCSprite.h" +#import "CCTextureCache.h" +#import "Support/CGPointExtension.h" + + +#pragma mark - +#pragma mark CCTMXTiledMap + +@interface CCTMXTiledMap (Private) +-(id) parseLayer:(CCTMXLayerInfo*)layer map:(CCTMXMapInfo*)mapInfo; +-(CCTMXTilesetInfo*) tilesetForLayer:(CCTMXLayerInfo*)layerInfo map:(CCTMXMapInfo*)mapInfo; +-(void) buildWithMapInfo:(CCTMXMapInfo*)mapInfo; +@end + +@implementation CCTMXTiledMap +@synthesize mapSize = _mapSize; +@synthesize tileSize = _tileSize; +@synthesize mapOrientation = _mapOrientation; +@synthesize objectGroups = _objectGroups; +@synthesize properties = _properties; + ++(id) tiledMapWithTMXFile:(NSString*)tmxFile +{ + return [[[self alloc] initWithTMXFile:tmxFile] autorelease]; +} + ++(id) tiledMapWithXML:(NSString*)tmxString resourcePath:(NSString*)resourcePath +{ + return [[[self alloc] initWithXML:tmxString resourcePath:resourcePath] autorelease]; +} + +-(void) buildWithMapInfo:(CCTMXMapInfo*)mapInfo +{ + _mapSize = mapInfo.mapSize; + _tileSize = mapInfo.tileSize; + _mapOrientation = mapInfo.orientation; + _objectGroups = [mapInfo.objectGroups retain]; + _properties = [mapInfo.properties retain]; + _tileProperties = [mapInfo.tileProperties retain]; + + int idx=0; + + for( CCTMXLayerInfo *layerInfo in mapInfo.layers ) { + + if( layerInfo.visible ) { + CCNode *child = [self parseLayer:layerInfo map:mapInfo]; + [self addChild:child z:idx tag:idx]; + + // update content size with the max size + CGSize childSize = [child contentSize]; + CGSize currentSize = [self contentSize]; + currentSize.width = MAX( currentSize.width, childSize.width ); + currentSize.height = MAX( currentSize.height, childSize.height ); + [self setContentSize:currentSize]; + + idx++; + } + } +} + +-(id) initWithXML:(NSString*)tmxString resourcePath:(NSString*)resourcePath +{ + if ((self=[super init])) { + + [self setContentSize:CGSizeZero]; + + CCTMXMapInfo *mapInfo = [CCTMXMapInfo formatWithXML:tmxString resourcePath:resourcePath]; + + NSAssert( [mapInfo.tilesets count] != 0, @"TMXTiledMap: Map not found. Please check the filename."); + [self buildWithMapInfo:mapInfo]; + } + + return self; +} + +-(id) initWithTMXFile:(NSString*)tmxFile +{ + NSAssert(tmxFile != nil, @"TMXTiledMap: tmx file should not bi nil"); + + if ((self=[super init])) { + + [self setContentSize:CGSizeZero]; + + CCTMXMapInfo *mapInfo = [CCTMXMapInfo formatWithTMXFile:tmxFile]; + + NSAssert( [mapInfo.tilesets count] != 0, @"TMXTiledMap: Map not found. Please check the filename."); + [self buildWithMapInfo:mapInfo]; + } + + return self; +} + +-(void) dealloc +{ + [_objectGroups release]; + [_properties release]; + [_tileProperties release]; + [super dealloc]; +} + +// private +-(id) parseLayer:(CCTMXLayerInfo*)layerInfo map:(CCTMXMapInfo*)mapInfo +{ + CCTMXTilesetInfo *tileset = [self tilesetForLayer:layerInfo map:mapInfo]; + CCTMXLayer *layer = [CCTMXLayer layerWithTilesetInfo:tileset layerInfo:layerInfo mapInfo:mapInfo]; + + // tell the layerinfo to release the ownership of the tiles map. + layerInfo.ownTiles = NO; + + [layer setupTiles]; + + return layer; +} + +-(CCTMXTilesetInfo*) tilesetForLayer:(CCTMXLayerInfo*)layerInfo map:(CCTMXMapInfo*)mapInfo +{ + CGSize size = layerInfo.layerSize; + + id iter = [mapInfo.tilesets reverseObjectEnumerator]; + for( CCTMXTilesetInfo* tileset in iter) { + for( unsigned int y = 0; y < size.height; y++ ) { + for( unsigned int x = 0; x < size.width; x++ ) { + + unsigned int pos = x + size.width * y; + unsigned int gid = layerInfo.tiles[ pos ]; + + // gid are stored in little endian. + // if host is big endian, then swap + gid = CFSwapInt32LittleToHost( gid ); + + // XXX: gid == 0 --> empty tile + if( gid != 0 ) { + + // Optimization: quick return + // if the layer is invalid (more than 1 tileset per layer) an assert will be thrown later + if( (gid & kCCFlippedMask) >= tileset.firstGid ) + return tileset; + } + } + } + } + + // If all the tiles are 0, return empty tileset + CCLOG(@"cocos2d: Warning: TMX Layer '%@' has no tiles", layerInfo.name); + return nil; +} + + +// public + +-(CCTMXLayer*) layerNamed:(NSString *)layerName +{ + CCTMXLayer *layer; + CCARRAY_FOREACH(_children, layer) { + if([layer isKindOfClass:[CCTMXLayer class]]) + if([layer.layerName isEqual:layerName]) + return layer; + } + + // layer not found + return nil; +} + +-(CCTMXObjectGroup*) objectGroupNamed:(NSString *)groupName +{ + for( CCTMXObjectGroup *objectGroup in _objectGroups ) { + if( [objectGroup.groupName isEqual:groupName] ) + return objectGroup; + } + + // objectGroup not found + return nil; +} + +-(id) propertyNamed:(NSString *)propertyName +{ + return [_properties valueForKey:propertyName]; +} +-(NSDictionary*)propertiesForGID:(unsigned int)GID{ + return [_tileProperties objectForKey:[NSNumber numberWithInt:GID]]; +} +@end + diff --git "a/21451198\345\215\242\350\266\205/project5/MyPlane/libs/cocos2d/CCTMXXMLParser.h" "b/21451198\345\215\242\350\266\205/project5/MyPlane/libs/cocos2d/CCTMXXMLParser.h" new file mode 100644 index 00000000..62f5551b --- /dev/null +++ "b/21451198\345\215\242\350\266\205/project5/MyPlane/libs/cocos2d/CCTMXXMLParser.h" @@ -0,0 +1,228 @@ +/* + * cocos2d for iPhone: http://www.cocos2d-iphone.org + * + * Copyright (c) 2009-2010 Ricardo Quesada + * Copyright (c) 2011 Zynga Inc. + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + * THE SOFTWARE. + * + * + * TMX Tiled Map support: + * http://www.mapeditor.org + * + */ + +/* + * Internal TMX parser + * + * IMPORTANT: These classed should not be documented using doxygen strings + * since the user should not use them. + * + */ + + +#import + +#import "ccMacros.h" + +enum { + TMXLayerAttribNone = 1 << 0, + TMXLayerAttribBase64 = 1 << 1, + TMXLayerAttribGzip = 1 << 2, + TMXLayerAttribZlib = 1 << 3, +}; + +enum { + TMXPropertyNone, + TMXPropertyMap, + TMXPropertyLayer, + TMXPropertyObjectGroup, + TMXPropertyObject, + TMXPropertyTile +}; + +typedef enum ccTMXTileFlags_ { + kCCTMXTileHorizontalFlag = 0x80000000, + kCCTMXTileVerticalFlag = 0x40000000, + kCCTMXTileDiagonalFlag = 0x20000000, + + kCCFlipedAll = (kCCTMXTileHorizontalFlag|kCCTMXTileVerticalFlag|kCCTMXTileDiagonalFlag), + kCCFlippedMask = ~(kCCFlipedAll), +} ccTMXTileFlags; + +// Bits on the far end of the 32-bit global tile ID (GID's) are used for tile flags + +/* CCTMXLayerInfo contains the information about the layers like: + - Layer name + - Layer size + - Layer opacity at creation time (it can be modified at runtime) + - Whether the layer is visible (if it is not visible, then the CCNode won't be created) + + This information is obtained from the TMX file. + */ +@interface CCTMXLayerInfo : NSObject +{ + NSString *_name; + CGSize _layerSize; + unsigned int *_tiles; + BOOL _visible; + unsigned char _opacity; + BOOL _ownTiles; + unsigned int _minGID; + unsigned int _maxGID; + NSMutableDictionary *_properties; + CGPoint _offset; +} + +@property (nonatomic,readwrite,retain) NSString *name; +@property (nonatomic,readwrite) CGSize layerSize; +@property (nonatomic,readwrite) unsigned int *tiles; +@property (nonatomic,readwrite) BOOL visible; +@property (nonatomic,readwrite) unsigned char opacity; +@property (nonatomic,readwrite) BOOL ownTiles; +@property (nonatomic,readwrite) unsigned int minGID; +@property (nonatomic,readwrite) unsigned int maxGID; +@property (nonatomic,readwrite,retain) NSMutableDictionary *properties; +@property (nonatomic,readwrite) CGPoint offset; +@end + +/* CCTMXTilesetInfo contains the information about the tilesets like: + - Tileset name + - Tilset spacing + - Tileset margin + - size of the tiles + - Image used for the tiles + - Image size + + This information is obtained from the TMX file. + */ +@interface CCTMXTilesetInfo : NSObject +{ + NSString *_name; + unsigned int _firstGid; + CGSize _tileSize; + unsigned int _spacing; + unsigned int _margin; + + // Offset of tiles. New TMX XML node introduced here: https://github.com/bjorn/tiled/issues/16 . + // Node structure: + // (...) + // + // + // (...) + CGPoint _tileOffset; + CGPoint _tileAnchorPoint; //normalized anchor point + + // filename containing the tiles (should be spritesheet / texture atlas) + NSString *_sourceImage; + + // size in pixels of the image + CGSize _imageSize; +} +@property (nonatomic,readwrite,retain) NSString *name; +@property (nonatomic,readwrite,assign) unsigned int firstGid; +@property (nonatomic,readwrite,assign) CGSize tileSize; +@property (nonatomic,readwrite,assign) unsigned int spacing; +@property (nonatomic,readwrite,assign) unsigned int margin; +@property (nonatomic,readwrite,retain) NSString *sourceImage; +@property (nonatomic,readwrite,assign) CGSize imageSize; +@property (nonatomic,readwrite,assign) CGPoint tileOffset; //setter has a custom implementation +@property (nonatomic,readonly,assign) CGPoint tileAnchorPoint; //set automatically when tileOffset changes + +-(CGRect) rectForGID:(unsigned int)gid; +@end + +/* CCTMXMapInfo contains the information about the map like: + - Map orientation (hexagonal, isometric or orthogonal) + - Tile size + - Map size + + And it also contains: + - Layers (an array of TMXLayerInfo objects) + - Tilesets (an array of TMXTilesetInfo objects) + - ObjectGroups (an array of TMXObjectGroupInfo objects) + + This information is obtained from the TMX file. + + */ +@interface CCTMXMapInfo : NSObject +{ + NSMutableString *_currentString; + BOOL _storingCharacters; + int _layerAttribs; + int _parentElement; + unsigned int _parentGID; + unsigned int _currentFirstGID; + + // tmx filename + NSString *_filename; + + // tmx resource path + NSString *_resources; + + // map orientation + int _orientation; + + // map width & height + CGSize _mapSize; + + // tiles width & height + CGSize _tileSize; + + // Layers + NSMutableArray *_layers; + + // tilesets + NSMutableArray *_tilesets; + + // ObjectGroups + NSMutableArray *_objectGroups; + + // properties + NSMutableDictionary *_properties; + + // tile properties + NSMutableDictionary *_tileProperties; +} + +@property (nonatomic,readwrite,assign) int orientation; +@property (nonatomic,readwrite,assign) CGSize mapSize; +@property (nonatomic,readwrite,assign) CGSize tileSize; +@property (nonatomic,readwrite,retain) NSMutableArray *layers; +@property (nonatomic,readwrite,retain) NSMutableArray *tilesets; +@property (nonatomic,readwrite,retain) NSString *filename; +@property (nonatomic,readwrite,retain) NSString *resources; +@property (nonatomic,readwrite,retain) NSMutableArray *objectGroups; +@property (nonatomic,readwrite,retain) NSMutableDictionary *properties; +@property (nonatomic,readwrite,retain) NSMutableDictionary *tileProperties; + +/** creates a TMX Format with a tmx file */ ++(id) formatWithTMXFile:(NSString*)tmxFile; + +/** creates a TMX Format with an XML string and a TMX resource path */ ++(id) formatWithXML:(NSString*)tmxString resourcePath:(NSString*)resourcePath; + +/** initializes a TMX format with a tmx file */ +-(id) initWithTMXFile:(NSString*)tmxFile; + +/** initializes a TMX format with an XML string and a TMX resource path */ +-(id) initWithXML:(NSString*)tmxString resourcePath:(NSString*)resourcePath; + +@end + diff --git "a/21451198\345\215\242\350\266\205/project5/MyPlane/libs/cocos2d/CCTMXXMLParser.m" "b/21451198\345\215\242\350\266\205/project5/MyPlane/libs/cocos2d/CCTMXXMLParser.m" new file mode 100644 index 00000000..388bb048 --- /dev/null +++ "b/21451198\345\215\242\350\266\205/project5/MyPlane/libs/cocos2d/CCTMXXMLParser.m" @@ -0,0 +1,552 @@ +/* + * cocos2d for iPhone: http://www.cocos2d-iphone.org + * + * Copyright (c) 2009-2010 Ricardo Quesada + * Copyright (c) 2011 Zynga Inc. + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + * THE SOFTWARE. + * + * + * TMX Tiled Map support: + * http://www.mapeditor.org + * + */ + + +#import +#include + +#import "ccMacros.h" +#import "Support/CGPointExtension.h" +#import "CCTMXXMLParser.h" +#import "CCTMXTiledMap.h" +#import "CCTMXObjectGroup.h" +#import "Support/base64.h" +#import "Support/ZipUtils.h" +#import "Support/CCFileUtils.h" + +#pragma mark - +#pragma mark TMXLayerInfo + + +@implementation CCTMXLayerInfo + +@synthesize name = _name, layerSize = _layerSize, tiles = _tiles, visible = _visible, opacity = _opacity, ownTiles = _ownTiles, minGID = _minGID, maxGID = _maxGID, properties = _properties; +@synthesize offset = _offset; +-(id) init +{ + if( (self=[super init])) { + _ownTiles = YES; + _minGID = 100000; + _maxGID = 0; + self.name = nil; + _tiles = NULL; + _offset = CGPointZero; + self.properties = [NSMutableDictionary dictionaryWithCapacity:5]; + } + return self; +} +- (void) dealloc +{ + CCLOGINFO(@"cocos2d: deallocing %@",self); + + [_name release]; + [_properties release]; + + if( _ownTiles && _tiles ) { + free( _tiles ); + _tiles = NULL; + } + [super dealloc]; +} + +@end + +#pragma mark - +#pragma mark TMXTilesetInfo +@implementation CCTMXTilesetInfo + +@synthesize name = _name, firstGid = _firstGid, tileSize = _tileSize, spacing = _spacing, margin = _margin, sourceImage = _sourceImage, imageSize = _imageSize; +@synthesize tileOffset = _tileOffset, tileAnchorPoint = _tileAnchorPoint; + +/** + Custom Setter: + Sets the _tileOffset property (expressed in pixels) as specified in the TMX file (should be double for retina). + Then it calculates the anchorPoint for the tiles (expressed as %), and stores it in the _tileAnchorPoint readonly property. + The CCTMXLayer is then responsible for setting the anchorPoint of its tile sprites. + (implemented in -[CCTMXLayer setupTileSprite:position:withGID:]) + */ +- (void)setTileOffset:(CGPoint)tileOffset +{ + _tileOffset = tileOffset; + NSAssert((self.tileSize.width > 0 && self.tileSize.height > 0), @"Error in [CCTMXTilesetInfo setTileOffset:], tileSize is Zero"); + float normalizedOffsetX = tileOffset.x / _tileSize.width; + float normalizedOffsetY = tileOffset.y / _tileSize.height; + _tileAnchorPoint = CGPointMake(normalizedOffsetX, normalizedOffsetY); +} + +- (void) dealloc +{ + CCLOGINFO(@"cocos2d: deallocing %@", self); + [_sourceImage release]; + [_name release]; + [super dealloc]; +} + +-(CGRect) rectForGID:(unsigned int)gid +{ + CGRect rect; + rect.size = _tileSize; + + gid &= kCCFlippedMask; + gid = gid - _firstGid; + + int max_x = (_imageSize.width - _margin*2 + _spacing) / (_tileSize.width + _spacing); + // int max_y = (imageSize.height - margin*2 + spacing) / (tileSize.height + spacing); + + rect.origin.x = (gid % max_x) * (_tileSize.width + _spacing) + _margin; + rect.origin.y = (gid / max_x) * (_tileSize.height + _spacing) + _margin; + + return rect; +} +@end + +#pragma mark - +#pragma mark CCTMXMapInfo + +@interface CCTMXMapInfo (Private) +/* initalises parsing of an XML file, either a tmx (Map) file or tsx (Tileset) file */ +-(void) parseXMLFile:(NSString *)xmlFilename; +/* initalises parsing of an XML string, either a tmx (Map) string or tsx (Tileset) string */ +- (void) parseXMLString:(NSString *)xmlString; +/* handles the work of parsing for parseXMLFile: and parseXMLString: */ +- (void) parseXMLData:(NSData*)data; +@end + +@implementation CCTMXMapInfo + +@synthesize orientation = _orientation, mapSize = _mapSize, layers = _layers, tilesets = _tilesets, tileSize = _tileSize, filename = _filename, resources = _resources, objectGroups = _objectGroups, properties = _properties; +@synthesize tileProperties = _tileProperties; + ++(id) formatWithTMXFile:(NSString*)tmxFile +{ + return [[[self alloc] initWithTMXFile:tmxFile] autorelease]; +} + ++(id) formatWithXML:(NSString*)tmxString resourcePath:(NSString*)resourcePath +{ + return [[[self alloc] initWithXML:tmxString resourcePath:resourcePath] autorelease]; +} + +- (void) internalInit:(NSString*)tmxFileName resourcePath:(NSString*)resourcePath +{ + self.tilesets = [NSMutableArray arrayWithCapacity:4]; + self.layers = [NSMutableArray arrayWithCapacity:4]; + self.filename = tmxFileName; + self.resources = resourcePath; + self.objectGroups = [NSMutableArray arrayWithCapacity:4]; + self.properties = [NSMutableDictionary dictionaryWithCapacity:5]; + self.tileProperties = [NSMutableDictionary dictionaryWithCapacity:5]; + + // tmp vars + _currentString = [[NSMutableString alloc] initWithCapacity:1024]; + _storingCharacters = NO; + _layerAttribs = TMXLayerAttribNone; + _parentElement = TMXPropertyNone; + _currentFirstGID = 0; +} + +-(id) initWithXML:(NSString *)tmxString resourcePath:(NSString*)resourcePath +{ + if( (self=[super init])) { + [self internalInit:nil resourcePath:resourcePath]; + [self parseXMLString:tmxString]; + } + return self; +} + +-(id) initWithTMXFile:(NSString*)tmxFile +{ + if( (self=[super init])) { + [self internalInit:tmxFile resourcePath:nil]; + [self parseXMLFile:_filename]; + } + return self; +} + +- (void) dealloc +{ + CCLOGINFO(@"cocos2d: deallocing %@", self); + [_tilesets release]; + [_layers release]; + [_filename release]; + [_resources release]; + [_currentString release]; + [_objectGroups release]; + [_properties release]; + [_tileProperties release]; + [super dealloc]; +} + +- (void) parseXMLData:(NSData*)data +{ + NSXMLParser *parser = [[[NSXMLParser alloc] initWithData:data] autorelease]; + + // we'll do the parsing + [parser setDelegate:self]; + [parser setShouldProcessNamespaces:NO]; + [parser setShouldReportNamespacePrefixes:NO]; + [parser setShouldResolveExternalEntities:NO]; + [parser parse]; + + NSAssert1( ![parser parserError], @"Error parsing TMX data: %@.", [NSString stringWithCharacters:[data bytes] length:[data length]] ); +} + +- (void) parseXMLString:(NSString *)xmlString +{ + NSData* data = [xmlString dataUsingEncoding:NSUTF8StringEncoding]; + [self parseXMLData:data]; +} + +- (void) parseXMLFile:(NSString *)xmlFilename +{ + NSURL *url = [NSURL fileURLWithPath:[[CCFileUtils sharedFileUtils] fullPathForFilename:xmlFilename] ]; + NSData *data = [NSData dataWithContentsOfURL:url]; + [self parseXMLData:data]; +} + +// the XML parser calls here with all the elements +-(void)parser:(NSXMLParser *)parser didStartElement:(NSString *)elementName namespaceURI:(NSString *)namespaceURI qualifiedName:(NSString *)qName attributes:(NSDictionary *)attributeDict +{ + if([elementName isEqualToString:@"map"]) { + NSString *version = [attributeDict objectForKey:@"version"]; + if( ! [version isEqualToString:@"1.0"] ) + CCLOG(@"cocos2d: TMXFormat: Unsupported TMX version: %@", version); + NSString *orientationStr = [attributeDict objectForKey:@"orientation"]; + if( [orientationStr isEqualToString:@"orthogonal"]) + _orientation = CCTMXOrientationOrtho; + else if ( [orientationStr isEqualToString:@"isometric"]) + _orientation = CCTMXOrientationIso; + else if( [orientationStr isEqualToString:@"hexagonal"]) + _orientation = CCTMXOrientationHex; + else + CCLOG(@"cocos2d: TMXFomat: Unsupported orientation: %d", _orientation); + + _mapSize.width = [[attributeDict objectForKey:@"width"] intValue]; + _mapSize.height = [[attributeDict objectForKey:@"height"] intValue]; + _tileSize.width = [[attributeDict objectForKey:@"tilewidth"] intValue]; + _tileSize.height = [[attributeDict objectForKey:@"tileheight"] intValue]; + + // The parent element is now "map" + _parentElement = TMXPropertyMap; + } else if([elementName isEqualToString:@"tileset"]) { + + // If this is an external tileset then start parsing that + NSString *externalTilesetFilename = [attributeDict objectForKey:@"source"]; + if (externalTilesetFilename) { + // Tileset file will be relative to the map file. So we need to convert it to an absolute path + NSString *dir = [_filename stringByDeletingLastPathComponent]; // Directory of map file + if (!dir) + dir = _resources; + externalTilesetFilename = [dir stringByAppendingPathComponent:externalTilesetFilename]; // Append path to tileset file + + _currentFirstGID = [[attributeDict objectForKey:@"firstgid"] intValue]; + + [self parseXMLFile:externalTilesetFilename]; + } else { + CCTMXTilesetInfo *tileset = [CCTMXTilesetInfo new]; + tileset.name = [attributeDict objectForKey:@"name"]; + if(_currentFirstGID == 0) { + tileset.firstGid = [[attributeDict objectForKey:@"firstgid"] intValue]; + } else { + tileset.firstGid = _currentFirstGID; + _currentFirstGID = 0; + } + tileset.spacing = [[attributeDict objectForKey:@"spacing"] intValue]; + tileset.margin = [[attributeDict objectForKey:@"margin"] intValue]; + CGSize s; + s.width = [[attributeDict objectForKey:@"tilewidth"] intValue]; + s.height = [[attributeDict objectForKey:@"tileheight"] intValue]; + tileset.tileSize = s; + tileset.tileOffset = CGPointZero; //default offset (0,0) + + [_tilesets addObject:tileset]; + [tileset release]; + } + + } + else if([elementName isEqualToString:@"tileoffset"]) { + //should only be found within a tileset. Getting the parent. + CCTMXTilesetInfo *tileset = [_tilesets lastObject]; + CGPoint offset = CGPointMake([[attributeDict objectForKey:@"x"] floatValue], + [[attributeDict objectForKey:@"y"] floatValue]); + tileset.tileOffset = offset; + } + else if([elementName isEqualToString:@"tile"]) { + CCTMXTilesetInfo* info = [_tilesets lastObject]; + NSMutableDictionary* dict = [NSMutableDictionary dictionaryWithCapacity:3]; + _parentGID = [info firstGid] + [[attributeDict objectForKey:@"id"] intValue]; + [_tileProperties setObject:dict forKey:[NSNumber numberWithInt:_parentGID]]; + + _parentElement = TMXPropertyTile; + + } else if([elementName isEqualToString:@"layer"]) { + CCTMXLayerInfo *layer = [CCTMXLayerInfo new]; + layer.name = [attributeDict objectForKey:@"name"]; + + CGSize s; + s.width = [[attributeDict objectForKey:@"width"] intValue]; + s.height = [[attributeDict objectForKey:@"height"] intValue]; + layer.layerSize = s; + + layer.visible = ![[attributeDict objectForKey:@"visible"] isEqualToString:@"0"]; + + if( [attributeDict objectForKey:@"opacity"] ) + layer.opacity = 255 * [[attributeDict objectForKey:@"opacity"] floatValue]; + else + layer.opacity = 255; + + int x = [[attributeDict objectForKey:@"x"] intValue]; + int y = [[attributeDict objectForKey:@"y"] intValue]; + layer.offset = ccp(x,y); + + [_layers addObject:layer]; + [layer release]; + + // The parent element is now "layer" + _parentElement = TMXPropertyLayer; + + } else if([elementName isEqualToString:@"objectgroup"]) { + + CCTMXObjectGroup *objectGroup = [[CCTMXObjectGroup alloc] init]; + objectGroup.groupName = [attributeDict objectForKey:@"name"]; + CGPoint positionOffset; + positionOffset.x = [[attributeDict objectForKey:@"x"] intValue] * _tileSize.width; + positionOffset.y = [[attributeDict objectForKey:@"y"] intValue] * _tileSize.height; + objectGroup.positionOffset = positionOffset; + + [_objectGroups addObject:objectGroup]; + [objectGroup release]; + + // The parent element is now "objectgroup" + _parentElement = TMXPropertyObjectGroup; + + } else if([elementName isEqualToString:@"image"]) { + + CCTMXTilesetInfo *tileset = [_tilesets lastObject]; + + // build full path + NSString *imagename = [attributeDict objectForKey:@"source"]; + NSString *path = [_filename stringByDeletingLastPathComponent]; + if (!path) + path = _resources; + tileset.sourceImage = [path stringByAppendingPathComponent:imagename]; + + } else if([elementName isEqualToString:@"data"]) { + NSString *encoding = [attributeDict objectForKey:@"encoding"]; + NSString *compression = [attributeDict objectForKey:@"compression"]; + + if( [encoding isEqualToString:@"base64"] ) { + _layerAttribs |= TMXLayerAttribBase64; + _storingCharacters = YES; + + if( [compression isEqualToString:@"gzip"] ) + _layerAttribs |= TMXLayerAttribGzip; + + else if( [compression isEqualToString:@"zlib"] ) + _layerAttribs |= TMXLayerAttribZlib; + + NSAssert( !compression || [compression isEqualToString:@"gzip"] || [compression isEqualToString:@"zlib"], @"TMX: unsupported compression method" ); + } + + NSAssert( _layerAttribs != TMXLayerAttribNone, @"TMX tile map: Only base64 and/or gzip/zlib maps are supported" ); + + } else if([elementName isEqualToString:@"object"]) { + + CCTMXObjectGroup *objectGroup = [_objectGroups lastObject]; + + // The value for "type" was blank or not a valid class name + // Create an instance of TMXObjectInfo to store the object and its properties + NSMutableDictionary *dict = [[NSMutableDictionary alloc] initWithCapacity:10]; + + // Parse everything automatically + NSArray *array = [NSArray arrayWithObjects:@"name", @"type", @"width", @"height", @"gid", nil]; + for( id key in array ) { + NSObject *obj = [attributeDict objectForKey:key]; + if( obj ) + [dict setObject:obj forKey:key]; + } + + // But X and Y since they need special treatment + // X + NSString *value = [attributeDict objectForKey:@"x"]; + if( value ) { + int x = [value intValue] + objectGroup.positionOffset.x; + [dict setObject:[NSNumber numberWithInt:x] forKey:@"x"]; + } + + // Y + value = [attributeDict objectForKey:@"y"]; + if( value ) { + int y = [value intValue] + objectGroup.positionOffset.y; + + // Correct y position. (Tiled uses Flipped, cocos2d uses Standard) + y = (_mapSize.height * _tileSize.height) - y - [[attributeDict objectForKey:@"height"] intValue]; + [dict setObject:[NSNumber numberWithInt:y] forKey:@"y"]; + } + + // Add the object to the objectGroup + [[objectGroup objects] addObject:dict]; + [dict release]; + + // The parent element is now "object" + _parentElement = TMXPropertyObject; + + } else if([elementName isEqualToString:@"property"]) { + + if ( _parentElement == TMXPropertyNone ) { + + CCLOG( @"TMX tile map: Parent element is unsupported. Cannot add property named '%@' with value '%@'", + [attributeDict objectForKey:@"name"], [attributeDict objectForKey:@"value"] ); + + } else if ( _parentElement == TMXPropertyMap ) { + + // The parent element is the map + [_properties setObject:[attributeDict objectForKey:@"value"] forKey:[attributeDict objectForKey:@"name"]]; + + } else if ( _parentElement == TMXPropertyLayer ) { + + // The parent element is the last layer + CCTMXLayerInfo *layer = [_layers lastObject]; + // Add the property to the layer + [[layer properties] setObject:[attributeDict objectForKey:@"value"] forKey:[attributeDict objectForKey:@"name"]]; + + } else if ( _parentElement == TMXPropertyObjectGroup ) { + + // The parent element is the last object group + CCTMXObjectGroup *objectGroup = [_objectGroups lastObject]; + [[objectGroup properties] setObject:[attributeDict objectForKey:@"value"] forKey:[attributeDict objectForKey:@"name"]]; + + } else if ( _parentElement == TMXPropertyObject ) { + + // The parent element is the last object + CCTMXObjectGroup *objectGroup = [_objectGroups lastObject]; + NSMutableDictionary *dict = [[objectGroup objects] lastObject]; + + NSString *propertyName = [attributeDict objectForKey:@"name"]; + NSString *propertyValue = [attributeDict objectForKey:@"value"]; + + [dict setObject:propertyValue forKey:propertyName]; + + } else if ( _parentElement == TMXPropertyTile ) { + + NSMutableDictionary* dict = [_tileProperties objectForKey:[NSNumber numberWithInt:_parentGID]]; + NSString *propertyName = [attributeDict objectForKey:@"name"]; + NSString *propertyValue = [attributeDict objectForKey:@"value"]; + [dict setObject:propertyValue forKey:propertyName]; + } + + } else if ([elementName isEqualToString:@"polygon"]) { + + // find parent object's dict and add polygon-points to it + CCTMXObjectGroup *objectGroup = [_objectGroups lastObject]; + NSMutableDictionary *dict = [[objectGroup objects] lastObject]; + [dict setObject:[attributeDict objectForKey:@"points"] forKey:@"polygonPoints"]; + + } else if ([elementName isEqualToString:@"polyline"]) { + + // find parent object's dict and add polyline-points to it + CCTMXObjectGroup *objectGroup = [_objectGroups lastObject]; + NSMutableDictionary *dict = [[objectGroup objects] lastObject]; + [dict setObject:[attributeDict objectForKey:@"points"] forKey:@"polylinePoints"]; + } +} + +- (void)parser:(NSXMLParser *)parser didEndElement:(NSString *)elementName namespaceURI:(NSString *)namespaceURI qualifiedName:(NSString *)qName +{ + int len = 0; + + if([elementName isEqualToString:@"data"] && _layerAttribs&TMXLayerAttribBase64) { + _storingCharacters = NO; + + CCTMXLayerInfo *layer = [_layers lastObject]; + + unsigned char *buffer; + len = base64Decode((unsigned char*)[_currentString UTF8String], (unsigned int) [_currentString length], &buffer); + if( ! buffer ) { + CCLOG(@"cocos2d: TiledMap: decode data error"); + return; + } + + if( _layerAttribs & (TMXLayerAttribGzip | TMXLayerAttribZlib) ) { + unsigned char *deflated; + CGSize s = [layer layerSize]; + int sizeHint = s.width * s.height * sizeof(uint32_t); + + int inflatedLen = ccInflateMemoryWithHint(buffer, len, &deflated, sizeHint); + NSAssert( inflatedLen == sizeHint, @"CCTMXXMLParser: Hint failed!"); + + inflatedLen = (int)&inflatedLen; // XXX: to avoid warings in compiler + + free( buffer ); + + if( ! deflated ) { + CCLOG(@"cocos2d: TiledMap: inflate data error"); + return; + } + + layer.tiles = (unsigned int*) deflated; + } else + layer.tiles = (unsigned int*) buffer; + + [_currentString setString:@""]; + + } else if ([elementName isEqualToString:@"map"]) { + // The map element has ended + _parentElement = TMXPropertyNone; + + } else if ([elementName isEqualToString:@"layer"]) { + // The layer element has ended + _parentElement = TMXPropertyNone; + + } else if ([elementName isEqualToString:@"objectgroup"]) { + // The objectgroup element has ended + _parentElement = TMXPropertyNone; + + } else if ([elementName isEqualToString:@"object"]) { + // The object element has ended + _parentElement = TMXPropertyNone; + } +} + +- (void)parser:(NSXMLParser *)parser foundCharacters:(NSString *)string +{ + if (_storingCharacters) + [_currentString appendString:string]; +} + + +// +// the level did not load, file not found, etc. +// +-(void)parser:(NSXMLParser *)parser parseErrorOccurred:(NSError *)parseError{ + CCLOG(@"cocos2d: Error on XML Parse: %@", [parseError localizedDescription] ); +} + +@end diff --git "a/21451198\345\215\242\350\266\205/project5/MyPlane/libs/cocos2d/CCTexture2D.h" "b/21451198\345\215\242\350\266\205/project5/MyPlane/libs/cocos2d/CCTexture2D.h" new file mode 100644 index 00000000..6d296775 --- /dev/null +++ "b/21451198\345\215\242\350\266\205/project5/MyPlane/libs/cocos2d/CCTexture2D.h" @@ -0,0 +1,353 @@ +/* + +===== IMPORTANT ===== + +This is sample code demonstrating API, technology or techniques in development. +Although this sample code has been reviewed for technical accuracy, it is not +final. Apple is supplying this information to help you plan for the adoption of +the technologies and programming interfaces described herein. This information +is subject to change, and software implemented based on this sample code should +be tested with final operating system software and final documentation. Newer +versions of this sample code may be provided with future seeds of the API or +technology. For information about updates to this and other developer +documentation, view the New & Updated sidebars in subsequent documentation +seeds. + +===================== + +File: Texture2D.h +Abstract: Creates OpenGL 2D textures from images or text. + +Version: 1.6 + +Disclaimer: IMPORTANT: This Apple software is supplied to you by Apple Inc. +("Apple") in consideration of your agreement to the following terms, and your +use, installation, modification or redistribution of this Apple software +constitutes acceptance of these terms. If you do not agree with these terms, +please do not use, install, modify or redistribute this Apple software. + +In consideration of your agreement to abide by the following terms, and subject +to these terms, Apple grants you a personal, non-exclusive license, under +Apple's copyrights in this original Apple software (the "Apple Software"), to +use, reproduce, modify and redistribute the Apple Software, with or without +modifications, in source and/or binary forms; provided that if you redistribute +the Apple Software in its entirety and without modifications, you must retain +this notice and the following text and disclaimers in all such redistributions +of the Apple Software. +Neither the name, trademarks, service marks or logos of Apple Inc. may be used +to endorse or promote products derived from the Apple Software without specific +prior written permission from Apple. Except as expressly stated in this notice, +no other rights or licenses, express or implied, are granted by Apple herein, +including but not limited to any patent rights that may be infringed by your +derivative works or by other works in which the Apple Software may be +incorporated. + +The Apple Software is provided by Apple on an "AS IS" basis. APPLE MAKES NO +WARRANTIES, EXPRESS OR IMPLIED, INCLUDING WITHOUT LIMITATION THE IMPLIED +WARRANTIES OF NON-INFRINGEMENT, MERCHANTABILITY AND FITNESS FOR A PARTICULAR +PURPOSE, REGARDING THE APPLE SOFTWARE OR ITS USE AND OPERATION ALONE OR IN +COMBINATION WITH YOUR PRODUCTS. + +IN NO EVENT SHALL APPLE BE LIABLE FOR ANY SPECIAL, INDIRECT, INCIDENTAL OR +CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE +GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) +ARISING IN ANY WAY OUT OF THE USE, REPRODUCTION, MODIFICATION AND/OR +DISTRIBUTION OF THE APPLE SOFTWARE, HOWEVER CAUSED AND WHETHER UNDER THEORY OF +CONTRACT, TORT (INCLUDING NEGLIGENCE), STRICT LIABILITY OR OTHERWISE, EVEN IF +APPLE HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +Copyright (C) 2008 Apple Inc. All Rights Reserved. + +*/ + +#import // for NSObject + +#import "ccTypes.h" +#import "ccMacros.h" +#import "CCFontDefinition.h" + +#import "Platforms/CCGL.h" // OpenGL stuff +#import "Platforms/CCNS.h" // Next-Step stuff + +//CONSTANTS: + +/** @typedef CCTexture2DPixelFormat + Possible texture pixel formats + */ +typedef enum { + //! 32-bit texture: RGBA8888 + kCCTexture2DPixelFormat_RGBA8888, + //! 32-bit texture without Alpha channel. Don't use it. + kCCTexture2DPixelFormat_RGB888, + //! 16-bit texture without Alpha channel + kCCTexture2DPixelFormat_RGB565, + //! 8-bit textures used as masks + kCCTexture2DPixelFormat_A8, + //! 8-bit intensity texture + kCCTexture2DPixelFormat_I8, + //! 16-bit textures used as masks + kCCTexture2DPixelFormat_AI88, + //! 16-bit textures: RGBA4444 + kCCTexture2DPixelFormat_RGBA4444, + //! 16-bit textures: RGB5A1 + kCCTexture2DPixelFormat_RGB5A1, + //! 4-bit PVRTC-compressed texture: PVRTC4 + kCCTexture2DPixelFormat_PVRTC4, + //! 2-bit PVRTC-compressed texture: PVRTC2 + kCCTexture2DPixelFormat_PVRTC2, + + //! Default texture format: RGBA8888 + kCCTexture2DPixelFormat_Default = kCCTexture2DPixelFormat_RGBA8888, + +} CCTexture2DPixelFormat; + + +@class CCGLProgram; + +/** CCTexture2D class. + * This class allows to easily create OpenGL 2D textures from images, text or raw data. + * The created CCTexture2D object will always have power-of-two dimensions. + * Depending on how you create the CCTexture2D object, the actual image area of the texture might be smaller than the texture dimensions i.e. "contentSize" != (pixelsWide, pixelsHigh) and (maxS, maxT) != (1.0, 1.0). + * Be aware that the content of the generated textures will be upside-down! + */ +@interface CCTexture2D : NSObject +{ + GLuint _name; + CGSize _size; + NSUInteger _width, + _height; + CCTexture2DPixelFormat _format; + GLfloat _maxS, + _maxT; + BOOL _hasPremultipliedAlpha; + BOOL _hasMipmaps; + + ccResolutionType _resolutionType; + + // needed for drawAtRect, drawInPoint + CCGLProgram *_shaderProgram; + +} +/** Initializes with a texture2d with data */ +- (id) initWithData:(const void*)data pixelFormat:(CCTexture2DPixelFormat)pixelFormat pixelsWide:(NSUInteger)width pixelsHigh:(NSUInteger)height contentSize:(CGSize)size; + +/** These functions are needed to create mutable textures */ +- (void) releaseData:(void*)data; +- (void*) keepData:(void*)data length:(NSUInteger)length; + +/** pixel format of the texture */ +@property(nonatomic,readonly) CCTexture2DPixelFormat pixelFormat; +/** width in pixels */ +@property(nonatomic,readonly) NSUInteger pixelsWide; +/** hight in pixels */ +@property(nonatomic,readonly) NSUInteger pixelsHigh; + +/** texture name */ +@property(nonatomic,readonly) GLuint name; + +/** returns content size of the texture in pixels */ +@property(nonatomic,readonly, nonatomic) CGSize contentSizeInPixels; + +/** texture max S */ +@property(nonatomic,readwrite) GLfloat maxS; +/** texture max T */ +@property(nonatomic,readwrite) GLfloat maxT; +/** whether or not the texture has their Alpha premultiplied */ +@property(nonatomic,readonly) BOOL hasPremultipliedAlpha; + +/** shader program used by drawAtPoint and drawInRect */ +@property(nonatomic,readwrite,retain) CCGLProgram *shaderProgram; + +/** Returns the resolution type of the texture. + Is it a RetinaDisplay texture, an iPad texture, a Mac, a Mac RetinaDisplay or an standard texture ? + + Should be a readonly property. It is readwrite as a hack. + + @since v1.1 + */ +@property (nonatomic, readwrite) ccResolutionType resolutionType; + + +/** returns the content size of the texture in points */ +-(CGSize) contentSize; + + +@end + +/** +Drawing extensions to make it easy to draw basic quads using a CCTexture2D object. +These functions require GL_TEXTURE_2D and both GL_VERTEX_ARRAY and GL_TEXTURE_COORD_ARRAY client states to be enabled. +*/ +@interface CCTexture2D (Drawing) +/** draws a texture at a given point */ +- (void) drawAtPoint:(CGPoint)point; +/** draws a texture inside a rect */ +- (void) drawInRect:(CGRect)rect; +@end + +/** +Extensions to make it easy to create a CCTexture2D object from an image file. +Note that RGBA type textures will have their alpha premultiplied - use the blending mode (GL_ONE, GL_ONE_MINUS_SRC_ALPHA). +*/ +@interface CCTexture2D (Image) +/** Initializes a texture from a CGImage object */ +- (id) initWithCGImage:(CGImageRef)cgImage resolutionType:(ccResolutionType)resolution; +@end + +/** +Extensions to make it easy to create a CCTexture2D object from a string of text. +Note that the generated textures are of type A8 - use the blending mode (GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA). +*/ +@interface CCTexture2D (Text) +/** Initializes a texture from a string with dimensions, alignment, line break mode, font name and font size + Supported lineBreakModes: + - iOS: all UILineBreakMode supported modes + - Mac: Only NSLineBreakByWordWrapping is supported. + @since v1.0 + */ +- (id) initWithString:(NSString*)string fontName:(NSString*)name fontSize:(CGFloat)size dimensions:(CGSize)dimensions hAlignment:(CCTextAlignment)alignment vAlignment:(CCVerticalTextAlignment) vertAlignment lineBreakMode:(CCLineBreakMode)lineBreakMode ; +/** Initializes a texture from a string with dimensions, alignment, font name and font size */ +- (id) initWithString:(NSString*)string fontName:(NSString*)name fontSize:(CGFloat)size dimensions:(CGSize)dimensions hAlignment:(CCTextAlignment)alignment vAlignment:(CCVerticalTextAlignment) vertAlignment; +/** Initializes a texture from a string with font name and font size */ +- (id) initWithString:(NSString*)string fontName:(NSString*)name fontSize:(CGFloat)size; +/** Initializes a texture from a string with font definition */ +- (id) initWithString:(NSString*)string fontDef:(CCFontDefinition *)definition; + +@end + + +/** + Extensions to make it easy to create a CCTexture2D object from a PVRTC file + Note that the generated textures don't have their alpha premultiplied - use the blending mode (GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA). + */ +@interface CCTexture2D (PVRSupport) +/** Initializes a texture from a PVR file. + + Supported PVR formats: + - BGRA 8888 + - RGBA 8888 + - RGBA 4444 + - RGBA 5551 + - RBG 565 + - A 8 + - I 8 + - AI 8 + - PVRTC 2BPP + - PVRTC 4BPP + + By default PVR images are treated as if they alpha channel is NOT premultiplied. You can override this behavior with this class method: + - PVRImagesHavePremultipliedAlpha:(BOOL)haveAlphaPremultiplied; + + IMPORTANT: This method is only defined on iOS. It is not supported on the Mac version. + + */ +-(id) initWithPVRFile: (NSString*) file; + +/** treats (or not) PVR files as if they have alpha premultiplied. + Since it is impossible to know at runtime if the PVR images have the alpha channel premultiplied, it is + possible load them as if they have (or not) the alpha channel premultiplied. + + By default it is disabled. + + @since v0.99.5 + */ ++(void) PVRImagesHavePremultipliedAlpha:(BOOL)haveAlphaPremultiplied; +@end + +/** + Extension to set the Min / Mag filter + */ +typedef struct _ccTexParams { + GLuint minFilter; + GLuint magFilter; + GLuint wrapS; + GLuint wrapT; +} ccTexParams; + +@interface CCTexture2D (GLFilter) +/** sets the min filter, mag filter, wrap s and wrap t texture parameters. + If the texture size is NPOT (non power of 2), then in can only use GL_CLAMP_TO_EDGE in GL_TEXTURE_WRAP_{S,T}. + + @warning Calling this method could allocate additional texture memory. + + @since v0.8 + */ +-(void) setTexParameters: (ccTexParams*) texParams; + +/** sets antialias texture parameters: + - GL_TEXTURE_MIN_FILTER = GL_LINEAR + - GL_TEXTURE_MAG_FILTER = GL_LINEAR + + @warning Calling this method could allocate additional texture memory. + + @since v0.8 + */ +- (void) setAntiAliasTexParameters; + +/** sets alias texture parameters: + - GL_TEXTURE_MIN_FILTER = GL_NEAREST + - GL_TEXTURE_MAG_FILTER = GL_NEAREST + + @warning Calling this method could allocate additional texture memory. + + @since v0.8 + */ +- (void) setAliasTexParameters; + + +/** Generates mipmap images for the texture. + It only works if the texture size is POT (power of 2). + @since v0.99.0 + */ +-(void) generateMipmap; + + +@end + +@interface CCTexture2D (PixelFormat) +/** sets the default pixel format for CGImages that contains alpha channel. + If the CGImage contains alpha channel, then the options are: + - generate 32-bit textures: kCCTexture2DPixelFormat_RGBA8888 (default one) + - generate 16-bit textures: kCCTexture2DPixelFormat_RGBA4444 + - generate 16-bit textures: kCCTexture2DPixelFormat_RGB5A1 + - generate 24-bit textures: kCCTexture2DPixelFormat_RGB888 (no alpha) + - generate 16-bit textures: kCCTexture2DPixelFormat_RGB565 (no alpha) + - generate 8-bit textures: kCCTexture2DPixelFormat_A8 (only use it if you use just 1 color) + + How does it work ? + - If the image is an RGBA (with Alpha) then the default pixel format will be used (it can be a 8-bit, 16-bit or 32-bit texture) + - If the image is an RGB (without Alpha) then: If the default pixel format is RGBA8888 then a RGBA8888 (32-bit) will be used. Otherwise a RGB565 (16-bit texture) will be used. + + This parameter is not valid for PVR / PVR.CCZ images. + + @since v0.8 + */ ++(void) setDefaultAlphaPixelFormat:(CCTexture2DPixelFormat)format; + +/** returns the alpha pixel format + @since v0.8 + */ ++(CCTexture2DPixelFormat) defaultAlphaPixelFormat; + +/** returns the bits-per-pixel of the in-memory OpenGL texture + @since v1.0 + */ +-(NSUInteger) bitsPerPixelForFormat; + +/** returns the pixel format in a NSString. + @since v2.0 + */ +-(NSString*) stringForFormat; + + +/** Helper functions that returns bits per pixels for a given format. + @since v2.0 + */ ++(NSUInteger) bitsPerPixelForFormat:(CCTexture2DPixelFormat)format; + +@end + + + + + diff --git "a/21451198\345\215\242\350\266\205/project5/MyPlane/libs/cocos2d/CCTexture2D.m" "b/21451198\345\215\242\350\266\205/project5/MyPlane/libs/cocos2d/CCTexture2D.m" new file mode 100644 index 00000000..e082c351 --- /dev/null +++ "b/21451198\345\215\242\350\266\205/project5/MyPlane/libs/cocos2d/CCTexture2D.m" @@ -0,0 +1,1445 @@ +/* + + ===== IMPORTANT ===== + + This is sample code demonstrating API, technology or techniques in development. + Although this sample code has been reviewed for technical accuracy, it is not + final. Apple is supplying this information to help you plan for the adoption of + the technologies and programming interfaces described herein. This information + is subject to change, and software implemented based on this sample code should + be tested with final operating system software and final documentation. Newer + versions of this sample code may be provided with future seeds of the API or + technology. For information about updates to this and other developer + documentation, view the New & Updated sidebars in subsequent documentationd + seeds. + + ===================== + + File: Texture2D.m + Abstract: Creates OpenGL 2D textures from images or text. + + Version: 1.6 + + Disclaimer: IMPORTANT: This Apple software is supplied to you by Apple Inc. + ("Apple") in consideration of your agreement to the following terms, and your + use, installation, modification or redistribution of this Apple software + constitutes acceptance of these terms. If you do not agree with these terms, + please do not use, install, modify or redistribute this Apple software. + + In consideration of your agreement to abide by the following terms, and subject + to these terms, Apple grants you a personal, non-exclusive license, under + Apple's copyrights in this original Apple software (the "Apple Software"), to + use, reproduce, modify and redistribute the Apple Software, with or without + modifications, in source and/or binary forms; provided that if you redistribute + the Apple Software in its entirety and without modifications, you must retain + this notice and the following text and disclaimers in all such redistributions + of the Apple Software. + Neither the name, trademarks, service marks or logos of Apple Inc. may be used + to endorse or promote products derived from the Apple Software without specific + prior written permission from Apple. Except as expressly stated in this notice, + no other rights or licenses, express or implied, are granted by Apple herein, + including but not limited to any patent rights that may be infringed by your + derivative works or by other works in which the Apple Software may be + incorporated. + + The Apple Software is provided by Apple on an "AS IS" basis. APPLE MAKES NO + WARRANTIES, EXPRESS OR IMPLIED, INCLUDING WITHOUT LIMITATION THE IMPLIED + WARRANTIES OF NON-INFRINGEMENT, MERCHANTABILITY AND FITNESS FOR A PARTICULAR + PURPOSE, REGARDING THE APPLE SOFTWARE OR ITS USE AND OPERATION ALONE OR IN + COMBINATION WITH YOUR PRODUCTS. + + IN NO EVENT SHALL APPLE BE LIABLE FOR ANY SPECIAL, INDIRECT, INCIDENTAL OR + CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE + GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + ARISING IN ANY WAY OUT OF THE USE, REPRODUCTION, MODIFICATION AND/OR + DISTRIBUTION OF THE APPLE SOFTWARE, HOWEVER CAUSED AND WHETHER UNDER THEORY OF + CONTRACT, TORT (INCLUDING NEGLIGENCE), STRICT LIABILITY OR OTHERWISE, EVEN IF + APPLE HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + + Copyright (C) 2008 Apple Inc. All Rights Reserved. + + */ + +/* + * Support for RGBA_4_4_4_4 and RGBA_5_5_5_1 was copied from: + * https://devforums.apple.com/message/37855#37855 by a1studmuffin + */ + +/* + * Added many additions for cocos2d + */ + +#import "Platforms/CCGL.h" +#import "Platforms/CCNS.h" + +#import "CCTexture2D.h" +#import "ccConfig.h" +#import "ccMacros.h" +#import "CCConfiguration.h" +#import "CCTexturePVR.h" +#import "CCGLProgram.h" +#import "ccGLStateCache.h" +#import "CCShaderCache.h" +#import "CCDirector.h" + +#import "Support/ccUtils.h" +#import "Support/CCFileUtils.h" + +#import "ccDeprecated.h" + + + +#if CC_USE_LA88_LABELS +#define LABEL_PIXEL_FORMAT kCCTexture2DPixelFormat_AI88 +#else +#define LABEL_PIXEL_FORMAT kCCTexture2DPixelFormat_A8 +#endif + +//CLASS IMPLEMENTATIONS: + + +// If the image has alpha, you can create RGBA8 (32-bit) or RGBA4 (16-bit) or RGB5A1 (16-bit) +// Default is: RGBA8888 (32-bit textures) +static CCTexture2DPixelFormat defaultAlphaPixel_format = kCCTexture2DPixelFormat_Default; + +#pragma mark - +#pragma mark CCTexture2D - Main + +@implementation CCTexture2D + +@synthesize contentSizeInPixels = _size, pixelFormat = _format, pixelsWide = _width, pixelsHigh = _height, name = _name, maxS = _maxS, maxT = _maxT; +@synthesize hasPremultipliedAlpha = _hasPremultipliedAlpha; +@synthesize shaderProgram = _shaderProgram; +@synthesize resolutionType = _resolutionType; + + +- (id) initWithData:(const void*)data pixelFormat:(CCTexture2DPixelFormat)pixelFormat pixelsWide:(NSUInteger)width pixelsHigh:(NSUInteger)height contentSize:(CGSize)size +{ + if((self = [super init])) { + + + // XXX: 32 bits or POT textures uses UNPACK of 4 (is this correct ??? ) + if( pixelFormat == kCCTexture2DPixelFormat_RGBA8888 || ( ccNextPOT(width)==width && ccNextPOT(height)==height) ) + glPixelStorei(GL_UNPACK_ALIGNMENT,4); + else + glPixelStorei(GL_UNPACK_ALIGNMENT,1); + + glGenTextures(1, &_name); + ccGLBindTexture2D( _name ); + + glTexParameteri( GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR ); + glTexParameteri( GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR ); + glTexParameteri( GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE ); + glTexParameteri( GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE ); + + // Specify OpenGL texture image + + switch(pixelFormat) + { + case kCCTexture2DPixelFormat_RGBA8888: + glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, (GLsizei) width, (GLsizei) height, 0, GL_RGBA, GL_UNSIGNED_BYTE, data); + break; + case kCCTexture2DPixelFormat_RGBA4444: + glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, (GLsizei) width, (GLsizei) height, 0, GL_RGBA, GL_UNSIGNED_SHORT_4_4_4_4, data); + break; + case kCCTexture2DPixelFormat_RGB5A1: + glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, (GLsizei) width, (GLsizei) height, 0, GL_RGBA, GL_UNSIGNED_SHORT_5_5_5_1, data); + break; + case kCCTexture2DPixelFormat_RGB565: + glTexImage2D(GL_TEXTURE_2D, 0, GL_RGB, (GLsizei) width, (GLsizei) height, 0, GL_RGB, GL_UNSIGNED_SHORT_5_6_5, data); + break; + case kCCTexture2DPixelFormat_RGB888: + glTexImage2D(GL_TEXTURE_2D, 0, GL_RGB, (GLsizei) width, (GLsizei) height, 0, GL_RGB, GL_UNSIGNED_BYTE, data); + break; + case kCCTexture2DPixelFormat_AI88: + glTexImage2D(GL_TEXTURE_2D, 0, GL_LUMINANCE_ALPHA, (GLsizei) width, (GLsizei) height, 0, GL_LUMINANCE_ALPHA, GL_UNSIGNED_BYTE, data); + break; + case kCCTexture2DPixelFormat_A8: + glTexImage2D(GL_TEXTURE_2D, 0, GL_ALPHA, (GLsizei) width, (GLsizei) height, 0, GL_ALPHA, GL_UNSIGNED_BYTE, data); + break; + default: + [NSException raise:NSInternalInconsistencyException format:@""]; + + } + + _size = size; + _width = width; + _height = height; + _format = pixelFormat; + _maxS = size.width / (float)width; + _maxT = size.height / (float)height; + + _hasPremultipliedAlpha = NO; + + _hasMipmaps = NO; + + _resolutionType = kCCResolutionUnknown; + self.shaderProgram = [[CCShaderCache sharedShaderCache] programForKey:kCCShader_PositionTexture]; + } + return self; +} + +- (void) releaseData:(void*)data +{ + //Free data + free(data); +} + +- (void*) keepData:(void*)data length:(NSUInteger)length +{ + //The texture data mustn't be saved becuase it isn't a mutable texture. + return data; +} + +- (void) dealloc +{ + CCLOGINFO(@"cocos2d: deallocing %@", self); + + [_shaderProgram release]; + + if( _name ) + ccGLDeleteTexture( _name ); + + [super dealloc]; +} + +- (NSString*) description +{ + return [NSString stringWithFormat:@"<%@ = %p | Name = %i | Dimensions = %lux%lu | Pixel format = %@ | Coordinates = (%.2f, %.2f)>", [self class], self, _name, (unsigned long)_width, (unsigned long)_height, [self stringForFormat], _maxS, _maxT]; +} + +-(CGSize) contentSize +{ + CGSize ret; + ret.width = _size.width / CC_CONTENT_SCALE_FACTOR(); + ret.height = _size.height / CC_CONTENT_SCALE_FACTOR(); + + return ret; +} + +@end + +#pragma mark - +#pragma mark CCTexture2D - Image + +@implementation CCTexture2D (Image) + +- (id) initWithCGImage:(CGImageRef)cgImage resolutionType:(ccResolutionType)resolution +{ + NSUInteger textureWidth, textureHeight; + CGContextRef context = nil; + void* data = nil; + CGColorSpaceRef colorSpace; + void* tempData; + unsigned int* inPixel32; + unsigned short* outPixel16; + BOOL hasAlpha; + CGImageAlphaInfo info; + CGSize imageSize; + CCTexture2DPixelFormat pixelFormat; + + if(cgImage == NULL) { + CCLOG(@"cocos2d: CCTexture2D. Can't create Texture. cgImage is nil"); + [self release]; + return nil; + } + + CCConfiguration *conf = [CCConfiguration sharedConfiguration]; + + info = CGImageGetAlphaInfo(cgImage); + +#ifdef __CC_PLATFORM_IOS + + // Bug #886. It is present on iOS 4 only + unsigned int version = [conf OSVersion]; + if( version >= kCCiOSVersion_4_0 && version < kCCiOSVersion_5_0 ) + hasAlpha = ((info == kCGImageAlphaNoneSkipLast) || (info == kCGImageAlphaPremultipliedLast) || (info == kCGImageAlphaPremultipliedFirst) || (info == kCGImageAlphaLast) || (info == kCGImageAlphaFirst) ? YES : NO); + else +#endif // __CC_PLATFORM_IOS + + hasAlpha = ((info == kCGImageAlphaPremultipliedLast) || (info == kCGImageAlphaPremultipliedFirst) || (info == kCGImageAlphaLast) || (info == kCGImageAlphaFirst) ? YES : NO); + + colorSpace = CGImageGetColorSpace(cgImage); + + if(colorSpace) { + if( hasAlpha ) { + pixelFormat = defaultAlphaPixel_format; + info = kCGImageAlphaPremultipliedLast; + } + else + { + info = kCGImageAlphaNoneSkipLast; + + // Use RGBA8888 if default is RGBA8888, otherwise use RGB565. + // DO NOT USE RGB888 since it is the same as RGBA8888, but it is more expensive to create it + if( defaultAlphaPixel_format == kCCTexture2DPixelFormat_RGBA8888 ) + pixelFormat = kCCTexture2DPixelFormat_RGBA8888; + else + { + pixelFormat = kCCTexture2DPixelFormat_RGB565; + CCLOG(@"cocos2d: CCTexture2D: Using RGB565 texture since image has no alpha"); + } + } + } else { + // NOTE: No colorspace means a mask image + CCLOG(@"cocos2d: CCTexture2D: Using A8 texture since image is a mask"); + pixelFormat = kCCTexture2DPixelFormat_A8; + } + + if( ! [conf supportsNPOT] ) + { + textureWidth = ccNextPOT(CGImageGetWidth(cgImage)); + textureHeight = ccNextPOT(CGImageGetHeight(cgImage)); + } + else + { + textureWidth = CGImageGetWidth(cgImage); + textureHeight = CGImageGetHeight(cgImage); + } + +#ifdef __CC_PLATFORM_IOS + + // iOS 5 BUG: + // If width is not word aligned, convert it to word aligned. + // http://www.cocos2d-iphone.org/forum/topic/31092 + if( [conf OSVersion] >= kCCiOSVersion_5_0 ) + { + + NSUInteger bpp = [[self class] bitsPerPixelForFormat:pixelFormat]; + NSUInteger bytes = textureWidth * bpp / 8; + + // XXX: Should it be 4 or sizeof(int) ?? + NSUInteger mod = bytes % 4; + + // Not word aligned ? + if( mod != 0 ) { + + NSUInteger neededBytes = (4 - mod ) / (bpp/8); + + CCLOGWARN(@"cocos2d: WARNING converting size=(%d,%d) to size=(%d,%d) due to iOS 5.x memory BUG. See: http://www.cocos2d-iphone.org/forum/topic/31092", textureWidth, textureHeight, textureWidth + neededBytes, textureHeight ); + textureWidth = textureWidth + neededBytes; + } + } +#endif // IOS + + NSUInteger maxTextureSize = [conf maxTextureSize]; + if( textureHeight > maxTextureSize || textureWidth > maxTextureSize ) { + CCLOGWARN(@"cocos2d: WARNING: Image (%lu x %lu) is bigger than the supported %ld x %ld", + (long)textureWidth, (long)textureHeight, + (long)maxTextureSize, (long)maxTextureSize); + [self release]; + return nil; + } + + imageSize = CGSizeMake(CGImageGetWidth(cgImage), CGImageGetHeight(cgImage)); + + // Create the bitmap graphics context + + switch(pixelFormat) { + case kCCTexture2DPixelFormat_RGBA8888: + case kCCTexture2DPixelFormat_RGBA4444: + case kCCTexture2DPixelFormat_RGB5A1: + case kCCTexture2DPixelFormat_RGB565: + case kCCTexture2DPixelFormat_RGB888: + colorSpace = CGColorSpaceCreateDeviceRGB(); + data = malloc(textureHeight * textureWidth * 4); +// info = hasAlpha ? kCGImageAlphaPremultipliedLast : kCGImageAlphaNoneSkipLast; +// info = kCGImageAlphaPremultipliedLast; // issue #886. This patch breaks BMP images. + context = CGBitmapContextCreate(data, textureWidth, textureHeight, 8, 4 * textureWidth, colorSpace, info | kCGBitmapByteOrder32Big); + CGColorSpaceRelease(colorSpace); + break; + case kCCTexture2DPixelFormat_A8: + data = malloc(textureHeight * textureWidth); + info = kCGImageAlphaOnly; + context = CGBitmapContextCreate(data, textureWidth, textureHeight, 8, textureWidth, NULL, (CGBitmapInfo)info); + break; + default: + [NSException raise:NSInternalInconsistencyException format:@"Invalid pixel format"]; + } + + + CGContextClearRect(context, CGRectMake(0, 0, textureWidth, textureHeight)); + CGContextTranslateCTM(context, 0, textureHeight - imageSize.height); + CGContextDrawImage(context, CGRectMake(0, 0, CGImageGetWidth(cgImage), CGImageGetHeight(cgImage)), cgImage); + + // Repack the pixel data into the right format + + if(pixelFormat == kCCTexture2DPixelFormat_RGB565) { + //Convert "RRRRRRRRRGGGGGGGGBBBBBBBBAAAAAAAA" to "RRRRRGGGGGGBBBBB" + tempData = malloc(textureHeight * textureWidth * 2); + inPixel32 = (unsigned int*)data; + outPixel16 = (unsigned short*)tempData; + for(unsigned int i = 0; i < textureWidth * textureHeight; ++i, ++inPixel32) + *outPixel16++ = ((((*inPixel32 >> 0) & 0xFF) >> 3) << 11) | ((((*inPixel32 >> 8) & 0xFF) >> 2) << 5) | ((((*inPixel32 >> 16) & 0xFF) >> 3) << 0); + free(data); + data = tempData; + + } + + else if(pixelFormat == kCCTexture2DPixelFormat_RGB888) { + //Convert "RRRRRRRRRGGGGGGGGBBBBBBBBAAAAAAAA" to "RRRRRRRRGGGGGGGGBBBBBBB" + tempData = malloc(textureHeight * textureWidth * 3); + char *inData = (char*)data; + char *outData = (char*)tempData; + int j=0; + for(unsigned int i = 0; i < textureWidth * textureHeight *4; i++) { + outData[j++] = inData[i++]; + outData[j++] = inData[i++]; + outData[j++] = inData[i++]; + } + free(data); + data = tempData; + + } + + else if (pixelFormat == kCCTexture2DPixelFormat_RGBA4444) { + //Convert "RRRRRRRRRGGGGGGGGBBBBBBBBAAAAAAAA" to "RRRRGGGGBBBBAAAA" + tempData = malloc(textureHeight * textureWidth * 2); + inPixel32 = (unsigned int*)data; + outPixel16 = (unsigned short*)tempData; + for(unsigned int i = 0; i < textureWidth * textureHeight; ++i, ++inPixel32) + *outPixel16++ = + ((((*inPixel32 >> 0) & 0xFF) >> 4) << 12) | // R + ((((*inPixel32 >> 8) & 0xFF) >> 4) << 8) | // G + ((((*inPixel32 >> 16) & 0xFF) >> 4) << 4) | // B + ((((*inPixel32 >> 24) & 0xFF) >> 4) << 0); // A + + + free(data); + data = tempData; + + } + else if (pixelFormat == kCCTexture2DPixelFormat_RGB5A1) { + //Convert "RRRRRRRRRGGGGGGGGBBBBBBBBAAAAAAAA" to "RRRRRGGGGGBBBBBA" + /* + Here was a bug. + When you convert RGBA8888 texture to RGB5A1 texture and then render it on black background, you'll see a "ghost" image as if the texture is still RGBA8888. + On background lighter than the pixel color this effect disappers. + This happens because the old convertion function doesn't premultiply old RGB with new A. + As Result = sourceRGB + destination*(1-source A), then + if Destination = 0000, then Result = source. Here comes the ghost! + We need to check new alpha value first (it may be 1 or 0) and depending on it whether convert RGB values or just set pixel to 0 + */ + tempData = malloc(textureHeight * textureWidth * 2); + inPixel32 = (unsigned int*)data; + outPixel16 = (unsigned short*)tempData; + for(unsigned int i = 0; i < textureWidth * textureHeight; ++i, ++inPixel32) { + if ((*inPixel32 >> 31))// A can be 1 or 0 + *outPixel16++ = + ((((*inPixel32 >> 0) & 0xFF) >> 3) << 11) | // R + ((((*inPixel32 >> 8) & 0xFF) >> 3) << 6) | // G + ((((*inPixel32 >> 16) & 0xFF) >> 3) << 1) | // B + 1; // A + else + *outPixel16++ = 0; + } + + free(data); + data = tempData; + } + self = [self initWithData:data pixelFormat:pixelFormat pixelsWide:textureWidth pixelsHigh:textureHeight contentSize:imageSize]; + + // should be after calling super init + _hasPremultipliedAlpha = (info == kCGImageAlphaPremultipliedLast || info == kCGImageAlphaPremultipliedFirst); + + CGContextRelease(context); + [self releaseData:data]; + + _resolutionType = resolution; + + return self; +} +@end + +#pragma mark - +#pragma mark CCTexture2D - Text + +@implementation CCTexture2D (Text) + +#ifdef __CC_PLATFORM_IOS + +- (id) initWithString:(NSString*)string fontDef:(CCFontDefinition *)definition +{ + // MUST have the same order declared on ccTypes + NSInteger linebreaks[] = {NSLineBreakByWordWrapping, NSLineBreakByCharWrapping, NSLineBreakByClipping, NSLineBreakByTruncatingHead, NSLineBreakByTruncatingTail, NSLineBreakByTruncatingMiddle}; + + + + UIFont *uifont = [UIFont fontWithName:definition.fontName size:definition.fontSize]; + if( ! uifont ) + { + CCLOG(@"cocos2d: Texture2d: Invalid Font: %@. Verify the .ttf name", definition.fontName); + [self release]; + return nil; + } + + // width and height + NSUInteger textureWidth = 0; + NSUInteger textureHeight = 0; + + + // the final dimension + CGSize computedDimension; + + if (definition.dimensions.width == 0 || definition.dimensions.height == 0) + { + CGSize boundingSize = CGSizeMake(CGFLOAT_MAX, CGFLOAT_MAX); + CGSize dim = [string sizeWithFont:uifont + constrainedToSize:boundingSize + lineBreakMode:NSLineBreakByWordWrapping]; + + if(dim.width == 0) + dim.width = 1; + if(dim.height == 0) + dim.height = 1; + + textureWidth = dim.width; + textureHeight = dim.height; + + computedDimension = dim; + } + else + { + textureWidth = ccNextPOT(definition.dimensions.width); + textureHeight = ccNextPOT(definition.dimensions.height); + computedDimension = definition.dimensions; + } + + unsigned char* data; + CGContextRef context; + CGColorSpaceRef colorSpace; + + // check if stroke or shadows are enabled + bool effectsEnabled = (([definition shadowEnabled]) || ([definition strokeEnabled])); + + // compute the padding needed by shadow and stroke + float shadowStrokePaddingX = 0.0f; + float shadowStrokePaddingY = 0.0f; + + + if ( [definition strokeEnabled] ) + { + shadowStrokePaddingY = shadowStrokePaddingX = ceilf([definition strokeSize]); + } + + if ( [definition shadowEnabled] ) + { + shadowStrokePaddingX = max(shadowStrokePaddingX, (float)abs([definition shadowOffset].width)); + shadowStrokePaddingY = max(shadowStrokePaddingY, (float)abs([definition shadowOffset].height)); + } + + // add the padding (this could be 0 if no shadow and no stroke) + textureWidth += shadowStrokePaddingX; + textureHeight += shadowStrokePaddingY; + + + +#if CC_USE_LA88_LABELS + + if (effectsEnabled) + { + data = calloc(textureHeight, textureWidth * 4); + } + else + { + data = calloc(textureHeight, textureWidth * 2); + } + +#else + + data = calloc(textureHeight, textureWidth); + +#endif + + if (effectsEnabled) + { + colorSpace = CGColorSpaceCreateDeviceRGB(); + context = CGBitmapContextCreate(data, textureWidth, textureHeight, 8, textureWidth * 4, colorSpace, kCGImageAlphaPremultipliedLast | kCGBitmapByteOrder32Big); + CGContextSetRGBFillColor(context, ((float)definition.fontFillColor.r) /255.0, ((float)definition.fontFillColor.g/255.0), ((float)definition.fontFillColor.b/255.0), 1.0); + } + else + { + colorSpace = CGColorSpaceCreateDeviceGray(); + // XXX ios7 + context = CGBitmapContextCreate(data, textureWidth, textureHeight, 8, textureWidth, colorSpace, (CGBitmapInfo)kCGImageAlphaNone); + CGContextSetGrayFillColor(context, 1.0f, 1.0f); + } + + + CGColorSpaceRelease(colorSpace); + + if( ! context ) { + free(data); + [self release]; + return nil; + } + + + CGContextTranslateCTM(context, 0.0f, textureHeight - shadowStrokePaddingY); + CGContextScaleCTM(context, 1.0f, -1.0f); //NOTE: NSString draws in UIKit referential i.e. renders upside-down compared to CGBitmapContext referential + UIGraphicsPushContext(context); + + // take care of stroke if needed + if ( [definition strokeEnabled] ) + { + CGContextSetTextDrawingMode(context, kCGTextFillStroke); + CGContextSetRGBStrokeColor(context, [definition strokeColor].r, [definition strokeColor].g, [definition strokeColor].b, 1); + CGContextSetLineWidth(context, [definition strokeSize]); + } + + // take care of shadow if needed + if ( [definition shadowEnabled] ) + { + CGSize offset; + offset.height = [definition shadowOffset].height; + offset.width = [definition shadowOffset].width; + CGContextSetShadow(context, offset, [definition shadowBlur]); + } + + float textOriginX = 0.0; + float textOriginY = 0.0; + + if ( [definition shadowOffset].width < 0 ) + { + textOriginX = shadowStrokePaddingX; + } + + if ( [definition shadowOffset].height < 0 ) + { + textOriginY = (-shadowStrokePaddingY); + } + + CGRect drawArea; + + if(definition.vertAlignment == kCCVerticalTextAlignmentTop) + { + drawArea = CGRectMake(textOriginX, textOriginY, computedDimension.width, computedDimension.height); + } + else + { + CGSize drawSize = [string sizeWithFont:uifont constrainedToSize:computedDimension lineBreakMode:linebreaks[definition.lineBreakMode] ]; + + if(definition.vertAlignment == kCCVerticalTextAlignmentBottom) + { + drawArea = CGRectMake(textOriginX, (computedDimension.height - drawSize.height) + textOriginY, computedDimension.width, drawSize.height); + } + else // kCCVerticalTextAlignmentCenter + { + drawArea = CGRectMake(textOriginX, ((computedDimension.height - drawSize.height) / 2) + textOriginY, computedDimension.width, drawSize.height); + } + } + + // must follow the same order of CCTextureAligment + NSUInteger alignments[] = { NSTextAlignmentLeft, NSTextAlignmentCenter, NSTextAlignmentRight }; + + [string drawInRect:drawArea withFont:uifont lineBreakMode:linebreaks[definition.lineBreakMode] alignment:alignments[definition.alignment]]; + + + UIGraphicsPopContext(); + + if (effectsEnabled) + { + CGSize finalSize; + finalSize.width = textureWidth; + finalSize.height = textureHeight; + self = [self initWithData:data pixelFormat:kCCTexture2DPixelFormat_RGBA8888 pixelsWide:textureWidth pixelsHigh:textureHeight contentSize:finalSize]; + } + else + { + #if CC_USE_LA88_LABELS + NSUInteger textureSize = textureWidth*textureHeight; + unsigned short *la88_data = (unsigned short*)data; + for(int i = textureSize-1; i>=0; i--) //Convert A8 to AI88 + la88_data[i] = (data[i] << 8) | 0xff; + #endif + self = [self initWithData:data pixelFormat:LABEL_PIXEL_FORMAT pixelsWide:textureWidth pixelsHigh:textureHeight contentSize:computedDimension]; + } + + CGContextRelease(context); + [self releaseData:data]; + + return self; + +} + +- (id) initWithString:(NSString*)string dimensions:(CGSize)dimensions hAlignment:(CCTextAlignment)hAlignment vAlignment:(CCVerticalTextAlignment) vAlignment lineBreakMode:(CCLineBreakMode)lineBreakMode font:(UIFont*)uifont +{ + NSAssert( uifont, @"Invalid font"); + + // MUST have the same order declared on ccTypes + NSInteger linebreaks[] = {NSLineBreakByWordWrapping, NSLineBreakByCharWrapping, NSLineBreakByClipping, NSLineBreakByTruncatingHead, NSLineBreakByTruncatingTail, NSLineBreakByTruncatingMiddle}; + + NSUInteger textureWidth = ccNextPOT(dimensions.width); + NSUInteger textureHeight = ccNextPOT(dimensions.height); + unsigned char* data; + + CGContextRef context; + CGColorSpaceRef colorSpace; + +#if CC_USE_LA88_LABELS + data = calloc(textureHeight, textureWidth * 2); +#else + data = calloc(textureHeight, textureWidth); +#endif + + colorSpace = CGColorSpaceCreateDeviceGray(); + context = CGBitmapContextCreate(data, textureWidth, textureHeight, 8, textureWidth, colorSpace, (CGBitmapInfo)kCGImageAlphaNone); + CGColorSpaceRelease(colorSpace); + + if( ! context ) { + free(data); + [self release]; + return nil; + } + + CGContextSetGrayFillColor(context, 1.0f, 1.0f); + CGContextTranslateCTM(context, 0.0f, textureHeight); + CGContextScaleCTM(context, 1.0f, -1.0f); //NOTE: NSString draws in UIKit referential i.e. renders upside-down compared to CGBitmapContext referential + + UIGraphicsPushContext(context); + + CGRect drawArea; + if(vAlignment == kCCVerticalTextAlignmentTop) + { + drawArea = CGRectMake(0, 0, dimensions.width, dimensions.height); + } + else + { + CGSize drawSize = [string sizeWithFont:uifont constrainedToSize:dimensions lineBreakMode:linebreaks[lineBreakMode] ]; + + if(vAlignment == kCCVerticalTextAlignmentBottom) + { + drawArea = CGRectMake(0, dimensions.height - drawSize.height, dimensions.width, drawSize.height); + } + else // kCCVerticalTextAlignmentCenter + { + drawArea = CGRectMake(0, (dimensions.height - drawSize.height) / 2, dimensions.width, drawSize.height); + } + } + + // must follow the same order of CCTextureAligment + NSUInteger alignments[] = { NSTextAlignmentLeft, NSTextAlignmentCenter, NSTextAlignmentRight }; + + [string drawInRect:drawArea withFont:uifont lineBreakMode:linebreaks[lineBreakMode] alignment:alignments[hAlignment]]; + + UIGraphicsPopContext(); + +#if CC_USE_LA88_LABELS + NSUInteger textureSize = textureWidth*textureHeight; + unsigned short *la88_data = (unsigned short*)data; + for(int i = textureSize-1; i>=0; i--) //Convert A8 to AI88 + la88_data[i] = (data[i] << 8) | 0xff; + +#endif + + self = [self initWithData:data pixelFormat:LABEL_PIXEL_FORMAT pixelsWide:textureWidth pixelsHigh:textureHeight contentSize:dimensions]; + + CGContextRelease(context); + [self releaseData:data]; + + return self; +} + + +#elif defined(__CC_PLATFORM_MAC) + +- (id) initWithString:(NSString*)string dimensions:(CGSize)dimensions hAlignment:(CCTextAlignment)hAlignment vAlignment:(CCVerticalTextAlignment)vAlignment attributedString:(NSAttributedString*)stringWithAttributes +{ + NSAssert(stringWithAttributes, @"Invalid stringWithAttributes"); + + // get nearest power of two + NSSize POTSize = NSMakeSize(ccNextPOT(dimensions.width), ccNextPOT(dimensions.height)); + + // Get actual rendered dimensions + NSRect boundingRect = [stringWithAttributes boundingRectWithSize:NSSizeFromCGSize(dimensions) options:NSStringDrawingUsesLineFragmentOrigin]; + + // Mac crashes if the width or height is 0 + if( POTSize.width == 0 ) + POTSize.width = 2; + + if( POTSize.height == 0) + POTSize.height = 2; + + CGSize offset = CGSizeMake(0, POTSize.height - dimensions.height); + + //Alignment + switch (hAlignment) { + case kCCTextAlignmentLeft: break; + case kCCTextAlignmentCenter: offset.width = (dimensions.width-boundingRect.size.width)/2.0f; break; + case kCCTextAlignmentRight: offset.width = dimensions.width-boundingRect.size.width; break; + default: break; + } + switch (vAlignment) { + case kCCVerticalTextAlignmentTop: offset.height += dimensions.height - boundingRect.size.height; break; + case kCCVerticalTextAlignmentCenter: offset.height += (dimensions.height - boundingRect.size.height) / 2; break; + case kCCVerticalTextAlignmentBottom: break; + default: break; + } + + CGRect drawArea = CGRectMake(offset.width, offset.height, boundingRect.size.width, boundingRect.size.height); + + //Disable antialias + [[NSGraphicsContext currentContext] setShouldAntialias:NO]; + + NSImage *image = [[NSImage alloc] initWithSize:POTSize]; + [image lockFocus]; + [[NSAffineTransform transform] set]; + + [stringWithAttributes drawWithRect:NSRectFromCGRect(drawArea) options:NSStringDrawingUsesLineFragmentOrigin]; + + NSBitmapImageRep *bitmap = [[NSBitmapImageRep alloc] initWithFocusedViewRect:NSMakeRect (0.0f, 0.0f, POTSize.width, POTSize.height)]; + [image unlockFocus]; + + unsigned char *data = (unsigned char*) [bitmap bitmapData]; //Use the same buffer to improve the performance. + + NSUInteger textureSize = POTSize.width * POTSize.height; +#if CC_USE_LA88_LABELS + unsigned short *dst = (unsigned short*)data; + for(int i = 0; i 0 ) + translationX = -shadowStrokePaddingX; + break; + default: + break; + } + } + else + { + if ([definition shadowOffset].width < 0 ) + translationX = shadowStrokePaddingX; + } + } + + if ([definition shadowOffset].height != 0 ) + { + if (mustAllign) + { + switch (definition.vertAlignment) + { + case kCCVerticalTextAlignmentTop: + if ([definition shadowOffset].height > 0 ) + translationY = (-shadowStrokePaddingY); + break; + + case kCCVerticalTextAlignmentCenter: + break; + + case kCCVerticalTextAlignmentBottom: + if ([definition shadowOffset].height < 0 ) + translationY = shadowStrokePaddingY; + break; + + default: + break; + } + + } + else + { + if ([definition shadowOffset].height < 0 ) + translationY = shadowStrokePaddingY; + } + } + } + + dim.height +=shadowStrokePaddingY; + dim.width +=shadowStrokePaddingX; + + + NSAssert(stringWithAttributes, @"Invalid stringWithAttributes"); + + // get nearest power of two + NSSize POTSize = NSMakeSize(ccNextPOT(dim.width), ccNextPOT(dim.height)); + + + // Get actual rendered dimensions + NSRect boundingRect = [stringWithAttributes boundingRectWithSize:NSSizeFromCGSize(dim) options:NSStringDrawingUsesLineFragmentOrigin]; + + // Mac crashes if the width or height is 0 + if( POTSize.width == 0 ) + POTSize.width = 2; + + if( POTSize.height == 0) + POTSize.height = 2; + + CGSize offset = CGSizeMake(0, POTSize.height - dim.height); + + //Alignment + if (mustAllign) + { + switch (definition.alignment) { + case kCCTextAlignmentLeft: break; + case kCCTextAlignmentCenter: offset.width = (dim.width-boundingRect.size.width)/2.0f; break; + case kCCTextAlignmentRight: offset.width = dim.width-boundingRect.size.width; break; + default: break; + } + switch (definition.vertAlignment) { + case kCCVerticalTextAlignmentTop: offset.height += dim.height - boundingRect.size.height; break; + case kCCVerticalTextAlignmentCenter: offset.height += (dim.height - boundingRect.size.height) / 2; break; + case kCCVerticalTextAlignmentBottom: break; + default: break; + } + } + + + CGRect drawArea = CGRectMake((offset.width + translationX), (offset.height + translationY), boundingRect.size.width, boundingRect.size.height); + + //Disable antialias + [[NSGraphicsContext currentContext] setShouldAntialias:NO]; + + NSImage *image = [[NSImage alloc] initWithSize:POTSize]; + [image lockFocus]; + [[NSAffineTransform transform] set]; + + [stringWithAttributes drawWithRect:NSRectFromCGRect(drawArea) options:NSStringDrawingUsesLineFragmentOrigin]; + + NSBitmapImageRep *bitmap = [[NSBitmapImageRep alloc] initWithFocusedViewRect:NSMakeRect (0.0f, 0.0f, POTSize.width, POTSize.height)]; + [image unlockFocus]; + + unsigned char *data = (unsigned char*) [bitmap bitmapData]; //Use the same buffer to improve the performance. + + NSUInteger textureSize = POTSize.width * POTSize.height; + + + if (useAdvancedAttributes) + { + self = [self initWithData:data pixelFormat:kCCTexture2DPixelFormat_RGBA8888 pixelsWide:POTSize.width pixelsHigh:POTSize.height contentSize:dim]; + } + else + { +#if CC_USE_LA88_LABELS + unsigned short *dst = (unsigned short*)data; + for(int i = 0; i 1 ); + [pvr release]; + + } else { + + CCLOG(@"cocos2d: Couldn't load PVR image: %@", relPath); + [self release]; + return nil; + } + _resolutionType = resolution; + } + return self; +} + ++(void) PVRImagesHavePremultipliedAlpha:(BOOL)haveAlphaPremultiplied +{ + _PVRHaveAlphaPremultiplied = haveAlphaPremultiplied; +} +@end + +#pragma mark - +#pragma mark CCTexture2D - Drawing + +@implementation CCTexture2D (Drawing) + +- (void) drawAtPoint:(CGPoint)point +{ + GLfloat coordinates[] = { 0.0f, _maxT, + _maxS, _maxT, + 0.0f, 0.0f, + _maxS, 0.0f }; + GLfloat width = (GLfloat)_width * _maxS, + height = (GLfloat)_height * _maxT; + + GLfloat vertices[] = { point.x, point.y, + width + point.x, point.y, + point.x, height + point.y, + width + point.x, height + point.y }; + + ccGLEnableVertexAttribs( kCCVertexAttribFlag_Position | kCCVertexAttribFlag_TexCoords ); + [_shaderProgram use]; + [_shaderProgram setUniformsForBuiltins]; + + ccGLBindTexture2D( _name ); + + + glVertexAttribPointer(kCCVertexAttrib_Position, 2, GL_FLOAT, GL_FALSE, 0, vertices); + glVertexAttribPointer(kCCVertexAttrib_TexCoords, 2, GL_FLOAT, GL_FALSE, 0, coordinates); + + + glDrawArrays(GL_TRIANGLE_STRIP, 0, 4); + + CC_INCREMENT_GL_DRAWS(1); +} + + +- (void) drawInRect:(CGRect)rect +{ + GLfloat coordinates[] = { 0.0f, _maxT, + _maxS, _maxT, + 0.0f, 0.0f, + _maxS, 0.0f }; + GLfloat vertices[] = { rect.origin.x, rect.origin.y, + rect.origin.x + rect.size.width, rect.origin.y, + rect.origin.x, rect.origin.y + rect.size.height, + rect.origin.x + rect.size.width, rect.origin.y + rect.size.height }; + + + [_shaderProgram use]; + [_shaderProgram setUniformsForBuiltins]; + + ccGLEnableVertexAttribs( kCCVertexAttribFlag_Position | kCCVertexAttribFlag_TexCoords ); + + ccGLBindTexture2D( _name ); + + glVertexAttribPointer(kCCVertexAttrib_Position, 2, GL_FLOAT, GL_FALSE, 0, vertices); + glVertexAttribPointer(kCCVertexAttrib_TexCoords, 2, GL_FLOAT, GL_FALSE, 0, coordinates); + + + glDrawArrays(GL_TRIANGLE_STRIP, 0, 4); + + CC_INCREMENT_GL_DRAWS(1); +} + +@end + + +#pragma mark - +#pragma mark CCTexture2D - GLFilter + +// +// Use to apply MIN/MAG filter +// +@implementation CCTexture2D (GLFilter) + +-(void) generateMipmap +{ + NSAssert( _width == ccNextPOT(_width) && _height == ccNextPOT(_height), @"Mimpap texture only works in POT textures"); + ccGLBindTexture2D( _name ); + glGenerateMipmap(GL_TEXTURE_2D); + _hasMipmaps = YES; +} + +-(void) setTexParameters: (ccTexParams*) texParams +{ + NSAssert( (_width == ccNextPOT(_width) && _height == ccNextPOT(_height)) || + (texParams->wrapS == GL_CLAMP_TO_EDGE && texParams->wrapT == GL_CLAMP_TO_EDGE), + @"GL_CLAMP_TO_EDGE should be used in NPOT dimensions"); + + ccGLBindTexture2D( _name ); + glTexParameteri( GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, texParams->minFilter ); + glTexParameteri( GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, texParams->magFilter ); + glTexParameteri( GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, texParams->wrapS ); + glTexParameteri( GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, texParams->wrapT ); +} + +-(void) setAliasTexParameters +{ + ccGLBindTexture2D( _name ); + + if( ! _hasMipmaps ) + glTexParameteri( GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST ); + else + glTexParameteri( GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST_MIPMAP_NEAREST ); + + glTexParameteri( GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST ); +} + +-(void) setAntiAliasTexParameters +{ + ccGLBindTexture2D( _name ); + + if( ! _hasMipmaps ) + glTexParameteri( GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR ); + else + glTexParameteri( GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR_MIPMAP_NEAREST ); + + glTexParameteri( GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR ); +} +@end + + +#pragma mark - +#pragma mark CCTexture2D - Pixel Format + +// +// Texture options for images that contains alpha +// +@implementation CCTexture2D (PixelFormat) ++(void) setDefaultAlphaPixelFormat:(CCTexture2DPixelFormat)format +{ + defaultAlphaPixel_format = format; +} + ++(CCTexture2DPixelFormat) defaultAlphaPixelFormat +{ + return defaultAlphaPixel_format; +} + ++(NSUInteger) bitsPerPixelForFormat:(CCTexture2DPixelFormat)format +{ + NSUInteger ret=0; + + switch (format) { + case kCCTexture2DPixelFormat_RGBA8888: + ret = 32; + break; + case kCCTexture2DPixelFormat_RGB888: + // It is 32 and not 24, since its internal representation uses 32 bits. + ret = 32; + break; + case kCCTexture2DPixelFormat_RGB565: + ret = 16; + break; + case kCCTexture2DPixelFormat_RGBA4444: + ret = 16; + break; + case kCCTexture2DPixelFormat_RGB5A1: + ret = 16; + break; + case kCCTexture2DPixelFormat_AI88: + ret = 16; + break; + case kCCTexture2DPixelFormat_A8: + ret = 8; + break; + case kCCTexture2DPixelFormat_I8: + ret = 8; + break; + case kCCTexture2DPixelFormat_PVRTC4: + ret = 4; + break; + case kCCTexture2DPixelFormat_PVRTC2: + ret = 2; + break; + default: + ret = -1; + NSAssert1(NO , @"bitsPerPixelForFormat: %ld, unrecognised pixel format", (long)format); + CCLOG(@"bitsPerPixelForFormat: %ld, cannot give useful result", (long)format); + break; + } + return ret; +} + +-(NSUInteger) bitsPerPixelForFormat +{ + return [[self class] bitsPerPixelForFormat:_format]; +} + +-(NSString*) stringForFormat +{ + + switch (_format) { + case kCCTexture2DPixelFormat_RGBA8888: + return @"RGBA8888"; + + case kCCTexture2DPixelFormat_RGB888: + return @"RGB888"; + + case kCCTexture2DPixelFormat_RGB565: + return @"RGB565"; + + case kCCTexture2DPixelFormat_RGBA4444: + return @"RGBA4444"; + + case kCCTexture2DPixelFormat_RGB5A1: + return @"RGB5A1"; + + case kCCTexture2DPixelFormat_AI88: + return @"AI88"; + + case kCCTexture2DPixelFormat_A8: + return @"A8"; + + case kCCTexture2DPixelFormat_I8: + return @"I8"; + + case kCCTexture2DPixelFormat_PVRTC4: + return @"PVRTC4"; + + case kCCTexture2DPixelFormat_PVRTC2: + return @"PVRTC2"; + + default: + NSAssert1(NO , @"stringForFormat: %ld, unrecognised pixel format", (long)_format); + CCLOG(@"stringForFormat: %ld, cannot give useful result", (long)_format); + break; + } + + return nil; +} +@end + diff --git "a/21451198\345\215\242\350\266\205/project5/MyPlane/libs/cocos2d/CCTextureAtlas.h" "b/21451198\345\215\242\350\266\205/project5/MyPlane/libs/cocos2d/CCTextureAtlas.h" new file mode 100644 index 00000000..5794ec80 --- /dev/null +++ "b/21451198\345\215\242\350\266\205/project5/MyPlane/libs/cocos2d/CCTextureAtlas.h" @@ -0,0 +1,188 @@ +/* + * cocos2d for iPhone: http://www.cocos2d-iphone.org + * + * Copyright (c) 2008-2010 Ricardo Quesada + * Copyright (c) 2011 Zynga Inc. + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + * THE SOFTWARE. + * + */ + +#import "CCTexture2D.h" +#import "ccTypes.h" +#import "ccConfig.h" + +/** A class that implements a Texture Atlas. + Supported features: + * The atlas file can be a PVRTC, PNG or any other format supported by Texture2D + * Quads can be updated in runtime + * Quads can be added in runtime + * Quads can be removed in runtime + * Quads can be re-ordered in runtime + * The TextureAtlas capacity can be increased or decreased in runtime + * OpenGL component: V3F, C4B, T2F. + The quads are rendered using an OpenGL ES VBO. + To render the quads using an interleaved vertex array list, you should modify the ccConfig.h file + */ +@interface CCTextureAtlas : NSObject +{ + NSUInteger _totalQuads; + NSUInteger _capacity; + ccV3F_C4B_T2F_Quad *_quads; // quads to be rendered + GLushort *_indices; + CCTexture2D *_texture; + + GLuint _buffersVBO[2]; //0: vertex 1: indices + BOOL _dirty; //indicates whether or not the array buffer of the VBO needs to be updated + +#if CC_TEXTURE_ATLAS_USE_VAO + GLuint _VAOname; +#endif +} + +/** quantity of quads that are going to be drawn */ +@property (nonatomic,readonly) NSUInteger totalQuads; +/** quantity of quads that can be stored with the current texture atlas size */ +@property (nonatomic,readonly) NSUInteger capacity; +/** Texture of the texture atlas */ +@property (nonatomic,retain) CCTexture2D *texture; +/** Quads that are going to be rendered */ +@property (nonatomic,readwrite) ccV3F_C4B_T2F_Quad *quads; + +/** creates a TextureAtlas with an filename and with an initial capacity for Quads. + * The TextureAtlas capacity can be increased in runtime. + */ ++(id) textureAtlasWithFile:(NSString*)file capacity:(NSUInteger)capacity; + +/** initializes a TextureAtlas with a filename and with a certain capacity for Quads. + * The TextureAtlas capacity can be increased in runtime. + * + * WARNING: Do not reinitialize the TextureAtlas because it will leak memory (issue #706) + */ +-(id) initWithFile: (NSString*) file capacity:(NSUInteger)capacity; + +/** creates a TextureAtlas with a previously initialized Texture2D object, and + * with an initial capacity for n Quads. + * The TextureAtlas capacity can be increased in runtime. + */ ++(id) textureAtlasWithTexture:(CCTexture2D *)tex capacity:(NSUInteger)capacity; + +/** initializes a TextureAtlas with a previously initialized Texture2D object, and + * with an initial capacity for Quads. + * The TextureAtlas capacity can be increased in runtime. + * + * WARNING: Do not reinitialize the TextureAtlas because it will leak memory (issue #706) + */ +-(id) initWithTexture:(CCTexture2D *)tex capacity:(NSUInteger)capacity; + +/** updates a Quad (texture, vertex and color) at a certain index + * index must be between 0 and the atlas capacity - 1 + @since v0.8 + */ +-(void) updateQuad:(ccV3F_C4B_T2F_Quad*)quad atIndex:(NSUInteger)index; + +/** Inserts a Quad (texture, vertex and color) at a certain index + index must be between 0 and the atlas capacity - 1 + @since v0.8 + */ +-(void) insertQuad:(ccV3F_C4B_T2F_Quad*)quad atIndex:(NSUInteger)index; + +/** Inserts a c array of quads at a given index + index must be between 0 and the atlas capacity - 1 + this method doesn't enlarge the array when amount + index > totalQuads + @since v1.1 +*/ +-(void) insertQuads:(ccV3F_C4B_T2F_Quad*)quads atIndex:(NSUInteger)index amount:(NSUInteger)amount; + +/** Removes the quad that is located at a certain index and inserts it at a new index + This operation is faster than removing and inserting in a quad in 2 different steps + @since v0.7.2 +*/ +-(void) insertQuadFromIndex:(NSUInteger)fromIndex atIndex:(NSUInteger)newIndex; + +/** removes a quad at a given index number. + The capacity remains the same, but the total number of quads to be drawn is reduced in 1 + @since v0.7.2 + */ +-(void) removeQuadAtIndex:(NSUInteger) index; + +/** removes a amount of quads starting from index + @since 1.1 + */ +- (void) removeQuadsAtIndex:(NSUInteger) index amount:(NSUInteger) amount; + +/** removes all Quads. + The TextureAtlas capacity remains untouched. No memory is freed. + The total number of quads to be drawn will be 0 + @since v0.7.2 + */ +-(void) removeAllQuads; + +/** resize the capacity of the CCTextureAtlas. + * The new capacity can be lower or higher than the current one + * It returns YES if the resize was successful. + * If it fails to resize the capacity it will return NO with a new capacity of 0. + */ +-(BOOL) resizeCapacity: (NSUInteger) n; + +/** + Used internally by CCParticleBatchNode + don't use this unless you know what you're doing + @since 1.1 +*/ +- (void) increaseTotalQuadsWith:(NSUInteger) amount; + +/** Moves an amount of quads from oldIndex at newIndex + @since v1.1 + */ +-(void) moveQuadsFromIndex:(NSUInteger)oldIndex amount:(NSUInteger) amount atIndex:(NSUInteger)newIndex; + +/** + Moves quads from index till totalQuads to the newIndex + Used internally by CCParticleBatchNode + This method doesn't enlarge the array if newIndex + quads to be moved > capacity + @since 1.1 +*/ +- (void) moveQuadsFromIndex:(NSUInteger) index to:(NSUInteger) newIndex; + +/** + Ensures that after a realloc quads are still empty + Used internally by CCParticleBatchNode + @since 1.1 +*/ +- (void) fillWithEmptyQuadsFromIndex:(NSUInteger) index amount:(NSUInteger) amount; + +/** draws n quads + * n can't be greater than the capacity of the Atlas + */ + +-(void) drawNumberOfQuads: (NSUInteger) n; + +/** draws n quads from an index (offset). + n + start can't be greater than the capacity of the atlas + + @since v1.0 + */ +-(void) drawNumberOfQuads: (NSUInteger) n fromIndex: (NSUInteger) start; + +/** draws all the Atlas's Quads + */ +-(void) drawQuads; + +@end diff --git "a/21451198\345\215\242\350\266\205/project5/MyPlane/libs/cocos2d/CCTextureAtlas.m" "b/21451198\345\215\242\350\266\205/project5/MyPlane/libs/cocos2d/CCTextureAtlas.m" new file mode 100644 index 00000000..ccf6f1ca --- /dev/null +++ "b/21451198\345\215\242\350\266\205/project5/MyPlane/libs/cocos2d/CCTextureAtlas.m" @@ -0,0 +1,575 @@ +/* + * cocos2d for iPhone: http://www.cocos2d-iphone.org + * + * Copyright (c) 2008-2010 Ricardo Quesada + * Copyright (c) 2011 Zynga Inc. + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + * THE SOFTWARE. + * + */ + +// cocos2d +#import "CCTextureAtlas.h" +#import "ccMacros.h" +#import "CCTexture2D.h" +#import "CCTextureCache.h" +#import "CCGLProgram.h" +#import "ccGLStateCache.h" +#import "CCDirector.h" +#import "CCConfiguration.h" + +#import "Support/NSThread+performBlock.h" +#import "Support/OpenGL_Internal.h" + +@interface CCTextureAtlas () +-(void) setupIndices; +-(void) mapBuffers; + +#if CC_TEXTURE_ATLAS_USE_VAO +-(void) setupVBOandVAO; +#else +-(void) setupVBO; +#endif +@end + +//According to some tests GL_TRIANGLE_STRIP is slower, MUCH slower. Probably I'm doing something very wrong + +@implementation CCTextureAtlas + +@synthesize totalQuads = _totalQuads, capacity = _capacity; +@synthesize texture = _texture; +@synthesize quads = _quads; + +#pragma mark TextureAtlas - alloc & init + ++(id) textureAtlasWithFile:(NSString*) file capacity: (NSUInteger) n +{ + return [[[self alloc] initWithFile:file capacity:n] autorelease]; +} + ++(id) textureAtlasWithTexture:(CCTexture2D *)tex capacity:(NSUInteger)n +{ + return [[[self alloc] initWithTexture:tex capacity:n] autorelease]; +} + +-(id) initWithFile:(NSString*)file capacity:(NSUInteger)n +{ + // retained in property + CCTexture2D *tex = [[CCTextureCache sharedTextureCache] addImage:file]; + if( tex ) + return [self initWithTexture:tex capacity:n]; + + // else + { + CCLOG(@"cocos2d: Could not open file: %@", file); + [self release]; + return nil; + } +} + +-(id) initWithTexture:(CCTexture2D*)tex capacity:(NSUInteger)n +{ + if( (self=[super init]) ) { + + _capacity = n; + _totalQuads = 0; + + // retained in property + self.texture = tex; + + // Re-initialization is not allowed + NSAssert(_quads==nil && _indices==nil, @"CCTextureAtlas re-initialization is not allowed"); + + _quads = calloc( sizeof(_quads[0]) * _capacity, 1 ); + _indices = calloc( sizeof(_indices[0]) * _capacity * 6, 1 ); + + if( ! ( _quads && _indices) ) { + CCLOG(@"cocos2d: CCTextureAtlas: not enough memory"); + if( _quads ) + free(_quads); + if( _indices ) + free(_indices); + + [self release]; + return nil; + } + + [self setupIndices]; + +#if CC_TEXTURE_ATLAS_USE_VAO + [self setupVBOandVAO]; +#else + [self setupVBO]; +#endif + + _dirty = YES; + } + + return self; +} + +-(NSString*) description +{ + return [NSString stringWithFormat:@"<%@ = %p | totalQuads = %lu>", [self class], self, (unsigned long)_totalQuads]; +} + +-(void) dealloc +{ + CCLOGINFO(@"cocos2d: deallocing %@",self); + + free(_quads); + free(_indices); + + glDeleteBuffers(2, _buffersVBO); + +#if CC_TEXTURE_ATLAS_USE_VAO + glDeleteVertexArrays(1, &_VAOname); +#endif + + [_texture release]; + + [super dealloc]; +} + +-(void) setupIndices +{ + for( NSUInteger i = 0; i < _capacity;i++) + { +#if CC_TEXTURE_ATLAS_USE_TRIANGLE_STRIP + _indices[i*6+0] = i*4+0; + _indices[i*6+1] = i*4+0; + _indices[i*6+2] = i*4+2; + _indices[i*6+3] = i*4+1; + _indices[i*6+4] = i*4+3; + _indices[i*6+5] = i*4+3; +#else + _indices[i*6+0] = i*4+0; + _indices[i*6+1] = i*4+1; + _indices[i*6+2] = i*4+2; + + // inverted index. issue #179 + _indices[i*6+3] = i*4+3; + _indices[i*6+4] = i*4+2; + _indices[i*6+5] = i*4+1; +#endif + } +} + +#pragma mark TextureAtlas - VAO / VBO specific + +#if CC_TEXTURE_ATLAS_USE_VAO +-(void) setupVBOandVAO +{ + // VAO requires GL_APPLE_vertex_array_object in order to be created on a different thread + // https://devforums.apple.com/thread/145566?tstart=0 + + void (^createVAO)(void) = ^{ + glGenVertexArrays(1, &_VAOname); + ccGLBindVAO(_VAOname); + + #define kQuadSize sizeof(_quads[0].bl) + + glGenBuffers(2, &_buffersVBO[0]); + + glBindBuffer(GL_ARRAY_BUFFER, _buffersVBO[0]); + glBufferData(GL_ARRAY_BUFFER, sizeof(_quads[0]) * _capacity, _quads, GL_DYNAMIC_DRAW); + + // vertices + glEnableVertexAttribArray(kCCVertexAttrib_Position); + glVertexAttribPointer(kCCVertexAttrib_Position, 3, GL_FLOAT, GL_FALSE, kQuadSize, (GLvoid*) offsetof( ccV3F_C4B_T2F, vertices)); + + // colors + glEnableVertexAttribArray(kCCVertexAttrib_Color); + glVertexAttribPointer(kCCVertexAttrib_Color, 4, GL_UNSIGNED_BYTE, GL_TRUE, kQuadSize, (GLvoid*) offsetof( ccV3F_C4B_T2F, colors)); + + // tex coords + glEnableVertexAttribArray(kCCVertexAttrib_TexCoords); + glVertexAttribPointer(kCCVertexAttrib_TexCoords, 2, GL_FLOAT, GL_FALSE, kQuadSize, (GLvoid*) offsetof( ccV3F_C4B_T2F, texCoords)); + + glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, _buffersVBO[1]); + glBufferData(GL_ELEMENT_ARRAY_BUFFER, sizeof(_indices[0]) * _capacity * 6, _indices, GL_STATIC_DRAW); + + // Must unbind the VAO before changing the element buffer. + ccGLBindVAO(0); + glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, 0); + glBindBuffer(GL_ARRAY_BUFFER, 0); + + CHECK_GL_ERROR_DEBUG(); + }; + + NSThread *cocos2dThread = [[CCDirector sharedDirector] runningThread]; + if( cocos2dThread == [NSThread currentThread] || [[CCConfiguration sharedConfiguration] supportsShareableVAO] ) + createVAO(); + else + [cocos2dThread performBlock:createVAO waitUntilDone:YES]; +} +#else // CC_TEXTURE_ATLAS_USE_VAO +-(void) setupVBO +{ + glGenBuffers(2, &_buffersVBO[0]); + + [self mapBuffers]; +} +#endif // ! // CC_TEXTURE_ATLAS_USE_VAO + + +-(void) mapBuffers +{ + // Avoid changing the element buffer for whatever VAO might be bound. + ccGLBindVAO(0); + + glBindBuffer(GL_ARRAY_BUFFER, _buffersVBO[0]); + glBufferData(GL_ARRAY_BUFFER, sizeof(_quads[0]) * _capacity, _quads, GL_DYNAMIC_DRAW); + glBindBuffer(GL_ARRAY_BUFFER, 0); + + glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, _buffersVBO[1]); + glBufferData(GL_ELEMENT_ARRAY_BUFFER, sizeof(_indices[0]) * _capacity * 6, _indices, GL_STATIC_DRAW); + glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, 0); + + CHECK_GL_ERROR_DEBUG(); +} + +#pragma mark TextureAtlas - Update, Insert, Move & Remove + +-(ccV3F_C4B_T2F_Quad *) quads +{ + //if someone accesses the quads directly, presume that changes will be made + _dirty = YES; + return _quads; +} + +-(void) updateQuad:(ccV3F_C4B_T2F_Quad*)quad atIndex:(NSUInteger) n +{ + NSAssert(n < _capacity, @"updateQuadWithTexture: Invalid index"); + + _totalQuads = MAX( n+1, _totalQuads); + + _quads[n] = *quad; + + _dirty = YES; +} + +-(void) insertQuad:(ccV3F_C4B_T2F_Quad*)quad atIndex:(NSUInteger)index +{ + NSAssert(index < _capacity, @"insertQuadWithTexture: Invalid index"); + + _totalQuads++; + NSAssert( _totalQuads <= _capacity, @"invalid totalQuads"); + + // issue #575. index can be > totalQuads + NSInteger remaining = (_totalQuads-1) - index; + + // last object doesn't need to be moved + if( remaining > 0) + // tex coordinates + memmove( &_quads[index+1],&_quads[index], sizeof(_quads[0]) * remaining ); + + _quads[index] = *quad; + + _dirty = YES; +} + +-(void) insertQuads:(ccV3F_C4B_T2F_Quad*)quads atIndex:(NSUInteger)index amount:(NSUInteger) amount +{ + NSAssert(index + amount <= _capacity, @"insertQuadWithTexture: Invalid index + amount"); + + _totalQuads+= amount; + + NSAssert( _totalQuads <= _capacity, @"invalid totalQuads"); + + // issue #575. index can be > totalQuads + NSInteger remaining = (_totalQuads-1) - index - amount; + + // last object doesn't need to be moved + if( remaining > 0) + // tex coordinates + memmove( &_quads[index+amount],&_quads[index], sizeof(_quads[0]) * remaining ); + + + + NSUInteger max = index + amount; + NSUInteger j = 0; + for (NSUInteger i = index; i < max ; i++) + { + _quads[index] = quads[j]; + index++; + j++; + } + + _dirty = YES; +} + +-(void) insertQuadFromIndex:(NSUInteger)oldIndex atIndex:(NSUInteger)newIndex +{ + NSAssert(newIndex < _totalQuads, @"insertQuadFromIndex:atIndex: Invalid index"); + NSAssert(oldIndex < _totalQuads, @"insertQuadFromIndex:atIndex: Invalid index"); + + if( oldIndex == newIndex ) + return; + + NSUInteger howMany = labs( oldIndex - newIndex); + NSUInteger dst = oldIndex; + NSUInteger src = oldIndex + 1; + if( oldIndex > newIndex) { + dst = newIndex+1; + src = newIndex; + } + + // tex coordinates + ccV3F_C4B_T2F_Quad quadsBackup = _quads[oldIndex]; + memmove( &_quads[dst],&_quads[src], sizeof(_quads[0]) * howMany ); + _quads[newIndex] = quadsBackup; + + _dirty = YES; +} + +-(void) moveQuadsFromIndex:(NSUInteger)oldIndex amount:(NSUInteger) amount atIndex:(NSUInteger)newIndex +{ + NSAssert(newIndex + amount <= _totalQuads, @"insertQuadFromIndex:atIndex: Invalid index"); + NSAssert(oldIndex < _totalQuads, @"insertQuadFromIndex:atIndex: Invalid index"); + + if( oldIndex == newIndex ) + return; + + //create buffer + size_t quadSize = sizeof(ccV3F_C4B_T2F_Quad); + ccV3F_C4B_T2F_Quad *tempQuads = malloc( quadSize * amount); + memcpy( tempQuads, &_quads[oldIndex], quadSize * amount ); + + if (newIndex < oldIndex) + { + // move quads from newIndex to newIndex + amount to make room for buffer + memmove( &_quads[newIndex], &_quads[newIndex+amount], (oldIndex-newIndex)*quadSize); + } + else + { + // move quads above back + memmove( &_quads[oldIndex], &_quads[oldIndex+amount], (newIndex-oldIndex)*quadSize); + } + memcpy( &_quads[newIndex], tempQuads, amount*quadSize); + + free(tempQuads); + + _dirty = YES; +} + +-(void) removeQuadAtIndex:(NSUInteger) index +{ + NSAssert(index < _totalQuads, @"removeQuadAtIndex: Invalid index"); + + NSUInteger remaining = (_totalQuads-1) - index; + + // last object doesn't need to be moved + if( remaining ) + memmove( &_quads[index],&_quads[index+1], sizeof(_quads[0]) * remaining ); + + _totalQuads--; + + _dirty = YES; +} + +-(void) removeQuadsAtIndex:(NSUInteger) index amount:(NSUInteger) amount +{ + NSAssert(index + amount <= _totalQuads, @"removeQuadAtIndex: index + amount out of bounds"); + + NSUInteger remaining = (_totalQuads) - (index + amount); + + _totalQuads -= amount; + + if ( remaining ) + memmove( &_quads[index], &_quads[index+amount], sizeof(_quads[0]) * remaining ); + + _dirty = YES; +} + +-(void) removeAllQuads +{ + _totalQuads = 0; +} + +#pragma mark TextureAtlas - Resize + +-(BOOL) resizeCapacity: (NSUInteger) newCapacity +{ + if( newCapacity == _capacity ) + return YES; + + // update capacity and totolQuads + _totalQuads = MIN(_totalQuads,newCapacity); + _capacity = newCapacity; + + void * tmpQuads = realloc( _quads, sizeof(_quads[0]) * _capacity ); + void * tmpIndices = realloc( _indices, sizeof(_indices[0]) * _capacity * 6 ); + + if( ! ( tmpQuads && tmpIndices) ) { + CCLOG(@"cocos2d: CCTextureAtlas: not enough memory"); + if( tmpQuads ) + free(tmpQuads); + else + free(_quads); + + if( tmpIndices ) + free(tmpIndices); + else + free(_indices); + + _indices = nil; + _quads = nil; + _capacity = _totalQuads = 0; + return NO; + } + + _quads = tmpQuads; + _indices = tmpIndices; + + // Update Indices + [self setupIndices]; + [self mapBuffers]; + + _dirty = YES; + + return YES; +} + +#pragma mark TextureAtlas - CCParticleBatchNode Specific + +-(void) fillWithEmptyQuadsFromIndex:(NSUInteger) index amount:(NSUInteger) amount +{ + ccV3F_C4B_T2F_Quad quad; + bzero( &quad, sizeof(quad) ); + + NSUInteger to = index + amount; + for (NSInteger i = index ; i < to ; i++) + { + _quads[i] = quad; + } + +} +-(void) increaseTotalQuadsWith:(NSUInteger) amount +{ + _totalQuads += amount; +} + +-(void) moveQuadsFromIndex:(NSUInteger) index to:(NSUInteger) newIndex +{ + NSAssert(newIndex + (_totalQuads - index) <= _capacity, @"moveQuadsFromIndex move is out of bounds"); + + memmove(_quads + newIndex,_quads + index, (_totalQuads - index) * sizeof(_quads[0])); +} + +#pragma mark TextureAtlas - Drawing + +-(void) drawQuads +{ + [self drawNumberOfQuads: _totalQuads fromIndex:0]; +} + +-(void) drawNumberOfQuads: (NSUInteger) n +{ + [self drawNumberOfQuads:n fromIndex:0]; +} + +-(void) drawNumberOfQuads: (NSUInteger) n fromIndex: (NSUInteger) start +{ + ccGLBindTexture2D( [_texture name] ); + +#if CC_TEXTURE_ATLAS_USE_VAO + + // + // Using VBO and VAO + // + // XXX: update is done in draw... perhaps it should be done in a timer + if (_dirty) { + glBindBuffer(GL_ARRAY_BUFFER, _buffersVBO[0]); + // option 1: subdata +// glBufferSubData(GL_ARRAY_BUFFER, sizeof(_quads[0])*start, sizeof(_quads[0]) * n , &_quads[start] ); + + // option 2: data +// glBufferData(GL_ARRAY_BUFFER, sizeof(_quads[0]) * (n-start), &_quads[start], GL_DYNAMIC_DRAW); + + // option 3: orphaning + glMapBuffer + glBufferData(GL_ARRAY_BUFFER, sizeof(_quads[0]) * (n-start), nil, GL_DYNAMIC_DRAW); + void *buf = glMapBuffer(GL_ARRAY_BUFFER, GL_WRITE_ONLY); + memcpy(buf, _quads, sizeof(_quads[0])* (n-start)); + glUnmapBuffer(GL_ARRAY_BUFFER); + + glBindBuffer(GL_ARRAY_BUFFER, 0); + + _dirty = NO; + } + + ccGLBindVAO( _VAOname ); + +#if CC_TEXTURE_ATLAS_USE_TRIANGLE_STRIP + glDrawElements(GL_TRIANGLE_STRIP, (GLsizei) n*6, GL_UNSIGNED_SHORT, (GLvoid*) (start*6*sizeof(_indices[0])) ); +#else + glDrawElements(GL_TRIANGLES, (GLsizei) n*6, GL_UNSIGNED_SHORT, (GLvoid*) (start*6*sizeof(_indices[0])) ); +#endif // CC_TEXTURE_ATLAS_USE_TRIANGLE_STRIP + +// glBindVertexArray(0); + + +#else // ! CC_TEXTURE_ATLAS_USE_VAO + + // + // Using VBO without VAO + // + +#define kQuadSize sizeof(_quads[0].bl) + glBindBuffer(GL_ARRAY_BUFFER, _buffersVBO[0]); + + // XXX: update is done in draw... perhaps it should be done in a timer + if (_dirty) { +// glBufferSubData(GL_ARRAY_BUFFER, sizeof(_quads[0])*start, sizeof(_quads[0]) * n , &_quads[start] ); + + // Apparently this is faster... need to do performance tests + glBufferData(GL_ARRAY_BUFFER, sizeof(_quads[0]) * n, _quads, GL_DYNAMIC_DRAW); + _dirty = NO; + } + + ccGLEnableVertexAttribs( kCCVertexAttribFlag_PosColorTex ); + + // vertices + glVertexAttribPointer(kCCVertexAttrib_Position, 3, GL_FLOAT, GL_FALSE, kQuadSize, (GLvoid*) offsetof( ccV3F_C4B_T2F, vertices)); + + // colors + glVertexAttribPointer(kCCVertexAttrib_Color, 4, GL_UNSIGNED_BYTE, GL_TRUE, kQuadSize, (GLvoid*) offsetof( ccV3F_C4B_T2F, colors)); + + // tex coords + glVertexAttribPointer(kCCVertexAttrib_TexCoords, 2, GL_FLOAT, GL_FALSE, kQuadSize, (GLvoid*) offsetof( ccV3F_C4B_T2F, texCoords)); + + glBindBuffer(GL_ARRAY_BUFFER, 0); + + glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, _buffersVBO[1]); + +#if CC_TEXTURE_ATLAS_USE_TRIANGLE_STRIP + glDrawElements(GL_TRIANGLE_STRIP, (GLsizei) n*6, GL_UNSIGNED_SHORT, (GLvoid*) (start*6*sizeof(_indices[0])) ); +#else + glDrawElements(GL_TRIANGLES, (GLsizei) n*6, GL_UNSIGNED_SHORT, (GLvoid*) (start*6*sizeof(_indices[0])) ); +#endif // CC_TEXTURE_ATLAS_USE_TRIANGLE_STRIP + + glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, 0); + +#endif // CC_TEXTURE_ATLAS_USE_VAO + + CC_INCREMENT_GL_DRAWS(1); + + CHECK_GL_ERROR_DEBUG(); +} +@end diff --git "a/21451198\345\215\242\350\266\205/project5/MyPlane/libs/cocos2d/CCTextureCache.h" "b/21451198\345\215\242\350\266\205/project5/MyPlane/libs/cocos2d/CCTextureCache.h" new file mode 100644 index 00000000..5c7568d9 --- /dev/null +++ "b/21451198\345\215\242\350\266\205/project5/MyPlane/libs/cocos2d/CCTextureCache.h" @@ -0,0 +1,146 @@ +/* + * cocos2d for iPhone: http://www.cocos2d-iphone.org + * + * Copyright (c) 2008-2010 Ricardo Quesada + * Copyright (c) 2011 Zynga Inc. + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + * THE SOFTWARE. + * + */ + +#import "ccMacros.h" + +#ifdef __CC_PLATFORM_IOS +#import +#endif + +#import + +@class CCTexture2D; + +/** Singleton that handles the loading of textures + * Once the texture is loaded, the next time it will return + * a reference of the previously loaded texture reducing GPU & CPU memory + */ +@interface CCTextureCache : NSObject +{ + NSMutableDictionary *_textures; + + dispatch_queue_t _loadingQueue; + dispatch_queue_t _dictQueue; +} + +/** Retruns ths shared instance of the cache */ ++ (CCTextureCache *) sharedTextureCache; + +/** purges the cache. It releases the retained instance. + @since v0.99.0 + */ ++(void)purgeSharedTextureCache; + + +/** Returns a Texture2D object given an file image + * If the file image was not previously loaded, it will create a new CCTexture2D + * object and it will return it. It will use the filename as a key. + * Otherwise it will return a reference of a previously loaded image. + * Supported image extensions: .png, .bmp, .tiff, .jpeg, .pvr, .gif + */ +-(CCTexture2D*) addImage: (NSString*) fileimage; + +/** Asynchronously, load a texture2d from a file. + * If the file image was previously loaded, it will use it. + * Otherwise it will load a texture in a new thread, and when the image is loaded, the callback will be called with the Texture2D as a parameter. + * The callback will be called in the cocos2d thread, so it is safe to create any cocos2d object from the callback. + * Supported image extensions: .png, .bmp, .tiff, .jpeg, .pvr, .gif + * @since v0.8 + */ +-(void) addImageAsync:(NSString*) filename target:(id)target selector:(SEL)selector; + +/** Asynchronously, load a texture2d from a file. + * If the file image was previously loaded, it will use it. + * Otherwise it will load a texture in a new thread, and when the image is loaded, the block will be called. + * The callback will be called in the cocos2d thread, so it is safe to create any cocos2d object from the callback. + * Supported image extensions: .png, .bmp, .tiff, .jpeg, .pvr, .gif + * @since v2.0 + */ +-(void) addImageAsync:(NSString*) filename withBlock:(void(^)(CCTexture2D *tex))block; + + +/** Returns a Texture2D object given an CGImageRef image + * If the image was not previously loaded, it will create a new CCTexture2D object and it will return it. + * Otherwise it will return a reference of a previously loaded image + * The "key" parameter will be used as the "key" for the cache. + * If "key" is nil, then a new texture will be created each time. + * @since v0.8 + */ +-(CCTexture2D*) addCGImage: (CGImageRef) image forKey: (NSString *)key; + +/** Returns an already created texture. Returns nil if the texture doesn't exist. + @since v0.99.5 + */ +-(CCTexture2D *) textureForKey:(NSString *)key; + +/** Purges the dictionary of loaded textures. + * Call this method if you receive the "Memory Warning" + * In the short term: it will free some resources preventing your app from being killed + * In the medium term: it will allocate more resources + * In the long term: it will be the same + */ +-(void) removeAllTextures; + +/** Removes unused textures + * Textures that have a retain count of 1 will be deleted + * It is convenient to call this method after when starting a new Scene + * @since v0.8 + */ +-(void) removeUnusedTextures; + +/** Deletes a texture from the cache given a texture + */ +-(void) removeTexture: (CCTexture2D*) tex; + +/** Deletes a texture from the cache given a its key name + @since v0.99.4 + */ +-(void) removeTextureForKey: (NSString*) textureKeyName; + +@end + + +@interface CCTextureCache (PVRSupport) + +/** Returns a Texture2D object given an PVR filename. + * If the file image was not previously loaded, it will create a new CCTexture2D + * object and it will return it. Otherwise it will return a reference of a previously loaded image + * + */ +-(CCTexture2D*) addPVRImage:(NSString*) filename; + +@end + + +@interface CCTextureCache (Debug) +/** Output to CCLOG the current contents of this CCTextureCache + * This will attempt to calculate the size of each texture, and the total texture memory in use + * + * @since v1.0 + */ +-(void) dumpCachedTextureInfo; + +@end diff --git "a/21451198\345\215\242\350\266\205/project5/MyPlane/libs/cocos2d/CCTextureCache.m" "b/21451198\345\215\242\350\266\205/project5/MyPlane/libs/cocos2d/CCTextureCache.m" new file mode 100644 index 00000000..1972a2af --- /dev/null +++ "b/21451198\345\215\242\350\266\205/project5/MyPlane/libs/cocos2d/CCTextureCache.m" @@ -0,0 +1,500 @@ +/* + * cocos2d for iPhone: http://www.cocos2d-iphone.org + * + * Copyright (c) 2008-2010 Ricardo Quesada + * Copyright (c) 2011 Zynga Inc. + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + * THE SOFTWARE. + * + */ + +#import "ccMacros.h" +#import "Platforms/CCGL.h" +#import "CCTextureCache.h" +#import "CCTexture2D.h" +#import "CCTexturePVR.h" +#import "CCConfiguration.h" +#import "CCDirector.h" +#import "ccConfig.h" +#import "ccTypes.h" + +#import "Support/CCFileUtils.h" +#import "Support/NSThread+performBlock.h" + + +#ifdef __CC_PLATFORM_MAC +#import "Platforms/Mac/CCDirectorMac.h" +#endif + +// needed for CCCallFuncO in Mac-display_link version +//#import "CCActionManager.h" +//#import "CCActionInstant.h" + +#ifdef __CC_PLATFORM_IOS +static EAGLContext *_auxGLcontext = nil; +#elif defined(__CC_PLATFORM_MAC) +static NSOpenGLContext *_auxGLcontext = nil; +#endif + +@implementation CCTextureCache + +#pragma mark TextureCache - Alloc, Init & Dealloc +static CCTextureCache *sharedTextureCache; + ++ (CCTextureCache *)sharedTextureCache +{ + if (!sharedTextureCache) + sharedTextureCache = [[self alloc] init]; + + return sharedTextureCache; +} + ++(id)alloc +{ + NSAssert(sharedTextureCache == nil, @"Attempted to allocate a second instance of a singleton."); + return [super alloc]; +} + ++(void)purgeSharedTextureCache +{ + [sharedTextureCache release]; + sharedTextureCache = nil; +} + +-(id) init +{ + if( (self=[super init]) ) { + _textures = [[NSMutableDictionary dictionaryWithCapacity: 10] retain]; + + // init "global" stuff + _loadingQueue = dispatch_queue_create("org.cocos2d.texturecacheloading", NULL); + _dictQueue = dispatch_queue_create("org.cocos2d.texturecachedict", NULL); + + CCGLView *view = (CCGLView*)[[CCDirector sharedDirector] view]; + NSAssert(view, @"Do not initialize the TextureCache before the Director"); + +#ifdef __CC_PLATFORM_IOS + _auxGLcontext = [[EAGLContext alloc] + initWithAPI:kEAGLRenderingAPIOpenGLES2 + sharegroup:[[view context] sharegroup]]; + +#elif defined(__CC_PLATFORM_MAC) + NSOpenGLPixelFormat *pf = [view pixelFormat]; + NSOpenGLContext *share = [view openGLContext]; + + _auxGLcontext = [[NSOpenGLContext alloc] initWithFormat:pf shareContext:share]; + +#endif // __CC_PLATFORM_MAC + + NSAssert( _auxGLcontext, @"TextureCache: Could not create EAGL context"); + + } + + return self; +} + +- (NSString*) description +{ + __block NSString *desc = nil; + dispatch_sync(_dictQueue, ^{ + desc = [NSString stringWithFormat:@"<%@ = %p | num of textures = %lu | keys: %@>", + [self class], + self, + (unsigned long)[_textures count], + [_textures allKeys] + ]; + }); + return desc; +} + +-(void) dealloc +{ + CCLOGINFO(@"cocos2d: deallocing %@", self); + + dispatch_sync(_dictQueue, ^{ + [_textures release]; + }); + [_auxGLcontext release]; + _auxGLcontext = nil; + sharedTextureCache = nil; + dispatch_release(_loadingQueue); + dispatch_release(_dictQueue); + + [super dealloc]; +} + +#pragma mark TextureCache - Add Images + +-(void) addImageAsync: (NSString*)path target:(id)target selector:(SEL)selector +{ + NSAssert(path != nil, @"TextureCache: fileimage MUST not be nill"); + NSAssert(target != nil, @"TextureCache: target can't be nil"); + NSAssert(selector != NULL, @"TextureCache: selector can't be NULL"); + + // remove possible -HD suffix to prevent caching the same image twice (issue #1040) + CCFileUtils *fileUtils = [CCFileUtils sharedFileUtils]; + path = [fileUtils standarizePath:path]; + + // optimization + __block CCTexture2D * tex; + + dispatch_sync(_dictQueue, ^{ + tex = [_textures objectForKey:path]; + }); + + if(tex) { + [target performSelector:selector withObject:tex]; + return; + } + + // dispatch it serially + dispatch_async(_loadingQueue, ^{ + + CCTexture2D *texture; + +#ifdef __CC_PLATFORM_IOS + if( [EAGLContext setCurrentContext:_auxGLcontext] ) { + + // load / create the texture + texture = [self addImage:path]; + + glFlush(); + + // callback should be executed in cocos2d thread + [target performSelector:selector onThread:[[CCDirector sharedDirector] runningThread] withObject:texture waitUntilDone:NO]; + + [EAGLContext setCurrentContext:nil]; + } else { + CCLOG(@"cocos2d: ERROR: TetureCache: Could not set EAGLContext"); + } + +#elif defined(__CC_PLATFORM_MAC) + + [_auxGLcontext makeCurrentContext]; + + // load / create the texture + texture = [self addImage:path]; + + glFlush(); + + // callback should be executed in cocos2d thread + [target performSelector:selector onThread:[[CCDirector sharedDirector] runningThread] withObject:texture waitUntilDone:NO]; + + [NSOpenGLContext clearCurrentContext]; + +#endif // __CC_PLATFORM_MAC + + }); +} + +-(void) addImageAsync:(NSString*)path withBlock:(void(^)(CCTexture2D *tex))block +{ + NSAssert(path != nil, @"TextureCache: fileimage MUST not be nil"); + + // remove possible -HD suffix to prevent caching the same image twice (issue #1040) + CCFileUtils *fileUtils = [CCFileUtils sharedFileUtils]; + path = [fileUtils standarizePath:path]; + + // optimization + __block CCTexture2D * tex; + + dispatch_sync(_dictQueue, ^{ + tex = [_textures objectForKey:path]; + }); + + if(tex) { + block(tex); + return; + } + + // dispatch it serially + dispatch_async( _loadingQueue, ^{ + + CCTexture2D *texture; + +#ifdef __CC_PLATFORM_IOS + if( [EAGLContext setCurrentContext:_auxGLcontext] ) { + + // load / create the texture + texture = [self addImage:path]; + + glFlush(); + + // callback should be executed in cocos2d thread + NSThread *thread = [[CCDirector sharedDirector] runningThread]; + [thread performBlock:block withObject:texture waitUntilDone:NO]; + + [EAGLContext setCurrentContext:nil]; + } else { + CCLOG(@"cocos2d: ERROR: TetureCache: Could not set EAGLContext"); + } + +#elif defined(__CC_PLATFORM_MAC) + + [_auxGLcontext makeCurrentContext]; + + // load / create the texture + texture = [self addImage:path]; + + glFlush(); + + // callback should be executed in cocos2d thread + NSThread *thread = [[CCDirector sharedDirector] runningThread]; + [thread performBlock:block withObject:texture waitUntilDone:NO]; + + [NSOpenGLContext clearCurrentContext]; + +#endif // __CC_PLATFORM_MAC + + }); +} + +-(CCTexture2D*) addImage: (NSString*) path +{ + NSAssert(path != nil, @"TextureCache: fileimage MUST not be nil"); + + // remove possible -HD suffix to prevent caching the same image twice (issue #1040) + CCFileUtils *fileUtils = [CCFileUtils sharedFileUtils]; + path = [fileUtils standarizePath:path]; + + __block CCTexture2D * tex = nil; + + dispatch_sync(_dictQueue, ^{ + tex = [_textures objectForKey: path]; + }); + + if( ! tex ) { + + ccResolutionType resolution; + NSString *fullpath = [fileUtils fullPathForFilename:path resolutionType:&resolution]; + if( ! fullpath ) { + CCLOG(@"cocos2d: Couldn't find file:%@", path); + return nil; + } + + NSString *lowerCase = [fullpath lowercaseString]; + + // all images are handled by UIKit/AppKit except PVR extension that is handled by cocos2d's handler + + if ( [lowerCase hasSuffix:@".pvr"] || [lowerCase hasSuffix:@".pvr.gz"] || [lowerCase hasSuffix:@".pvr.ccz"] ) + tex = [self addPVRImage:path]; + +#ifdef __CC_PLATFORM_IOS + + else { + + UIImage *image = [[UIImage alloc] initWithContentsOfFile:fullpath]; + tex = [[CCTexture2D alloc] initWithCGImage:image.CGImage resolutionType:resolution]; + [image release]; + + if( tex ){ + dispatch_sync(_dictQueue, ^{ + [_textures setObject: tex forKey:path]; + }); + }else{ + CCLOG(@"cocos2d: Couldn't create texture for file:%@ in CCTextureCache", path); + } + + // autorelease prevents possible crash in multithreaded environments + [tex autorelease]; + } + + +#elif defined(__CC_PLATFORM_MAC) + else { + + NSData *data = [[NSData alloc] initWithContentsOfFile:fullpath]; + NSBitmapImageRep *image = [[NSBitmapImageRep alloc] initWithData:data]; + tex = [ [CCTexture2D alloc] initWithCGImage:[image CGImage] resolutionType:resolution]; + + [data release]; + [image release]; + + if( tex ){ + dispatch_sync(_dictQueue, ^{ + [_textures setObject: tex forKey:path]; + }); + }else{ + CCLOG(@"cocos2d: Couldn't create texture for file:%@ in CCTextureCache", path); + } + + // autorelease prevents possible crash in multithreaded environments + [tex autorelease]; + } +#endif // __CC_PLATFORM_MAC + + } + + return tex; +} + + +-(CCTexture2D*) addCGImage: (CGImageRef) imageref forKey: (NSString *)key +{ + NSAssert(imageref != nil, @"TextureCache: image MUST not be nill"); + + __block CCTexture2D * tex = nil; + + // If key is nil, then create a new texture each time + if( key ) { + dispatch_sync(_dictQueue, ^{ + tex = [_textures objectForKey:key]; + }); + if(tex) + return tex; + } + + tex = [[CCTexture2D alloc] initWithCGImage:imageref resolutionType:kCCResolutionUnknown]; + + if(tex && key){ + dispatch_sync(_dictQueue, ^{ + [_textures setObject: tex forKey:key]; + }); + }else{ + CCLOG(@"cocos2d: Couldn't add CGImage in CCTextureCache"); + } + + return [tex autorelease]; +} + +#pragma mark TextureCache - Remove + +-(void) removeAllTextures +{ + dispatch_sync(_dictQueue, ^{ + [_textures removeAllObjects]; + }); +} + +-(void) removeUnusedTextures +{ + dispatch_sync(_dictQueue, ^{ + NSArray *keys = [_textures allKeys]; + for( id key in keys ) { + id value = [_textures objectForKey:key]; + if( [value retainCount] == 1 ) { + CCLOG(@"cocos2d: CCTextureCache: removing unused texture: %@", key); + [_textures removeObjectForKey:key]; + } + } + }); +} + +-(void) removeTexture: (CCTexture2D*) tex +{ + if( ! tex ) + return; + + dispatch_sync(_dictQueue, ^{ + NSArray *keys = [_textures allKeysForObject:tex]; + + for( NSUInteger i = 0; i < [keys count]; i++ ) + [_textures removeObjectForKey:[keys objectAtIndex:i]]; + }); +} + +-(void) removeTextureForKey:(NSString*)name +{ + if( ! name ) + return; + + dispatch_sync(_dictQueue, ^{ + [_textures removeObjectForKey:name]; + }); +} + +#pragma mark TextureCache - Get +- (CCTexture2D *)textureForKey:(NSString *)key +{ + __block CCTexture2D *tex = nil; + + dispatch_sync(_dictQueue, ^{ + tex = [_textures objectForKey:key]; + }); + + return tex; +} + +@end + + +@implementation CCTextureCache (PVRSupport) + +-(CCTexture2D*) addPVRImage:(NSString*)path +{ + NSAssert(path != nil, @"TextureCache: fileimage MUST not be nill"); + + // remove possible -HD suffix to prevent caching the same image twice (issue #1040) + CCFileUtils *fileUtils = [CCFileUtils sharedFileUtils]; + path = [fileUtils standarizePath:path]; + + __block CCTexture2D * tex; + + dispatch_sync(_dictQueue, ^{ + tex = [_textures objectForKey:path]; + }); + + if(tex) { + return tex; + } + + tex = [[CCTexture2D alloc] initWithPVRFile: path]; + if( tex ){ + dispatch_sync(_dictQueue, ^{ + [_textures setObject: tex forKey:path]; + }); + }else{ + CCLOG(@"cocos2d: Couldn't add PVRImage:%@ in CCTextureCache",path); + } + + return [tex autorelease]; +} + +@end + + +@implementation CCTextureCache (Debug) + +-(void) dumpCachedTextureInfo +{ + __block NSUInteger count = 0; + __block NSUInteger totalBytes = 0; + + dispatch_sync(_dictQueue, ^{ + for (NSString* texKey in _textures) { + CCTexture2D* tex = [_textures objectForKey:texKey]; + NSUInteger bpp = [tex bitsPerPixelForFormat]; + // Each texture takes up width * height * bytesPerPixel bytes. + NSUInteger bytes = tex.pixelsWide * tex.pixelsHigh * bpp / 8; + totalBytes += bytes; + count++; + NSLog( @"cocos2d: \"%@\"\trc=%lu\tid=%lu\t%lu x %lu\t@ %ld bpp =>\t%lu KB", + texKey, + (long)[tex retainCount], + (long)tex.name, + (long)tex.pixelsWide, + (long)tex.pixelsHigh, + (long)bpp, + (long)bytes / 1024 ); + } + }); + NSLog( @"cocos2d: CCTextureCache dumpDebugInfo:\t%ld textures,\tfor %lu KB (%.2f MB)", (long)count, (long)totalBytes / 1024, totalBytes / (1024.0f*1024.0f)); +} + +@end diff --git "a/21451198\345\215\242\350\266\205/project5/MyPlane/libs/cocos2d/CCTexturePVR.h" "b/21451198\345\215\242\350\266\205/project5/MyPlane/libs/cocos2d/CCTexturePVR.h" new file mode 100644 index 00000000..61d1dc4b --- /dev/null +++ "b/21451198\345\215\242\350\266\205/project5/MyPlane/libs/cocos2d/CCTexturePVR.h" @@ -0,0 +1,146 @@ +/* + +File: PVRTexture.h +Abstract: The PVRTexture class is responsible for loading .pvr files. + +Version: 1.0 + +Disclaimer: IMPORTANT: This Apple software is supplied to you by Apple Inc. +("Apple") in consideration of your agreement to the following terms, and your +use, installation, modification or redistribution of this Apple software +constitutes acceptance of these terms. If you do not agree with these terms, +please do not use, install, modify or redistribute this Apple software. + +In consideration of your agreement to abide by the following terms, and subject +to these terms, Apple grants you a personal, non-exclusive license, under +Apple's copyrights in this original Apple software (the "Apple Software"), to +use, reproduce, modify and redistribute the Apple Software, with or without +modifications, in source and/or binary forms; provided that if you redistribute +the Apple Software in its entirety and without modifications, you must retain +this notice and the following text and disclaimers in all such redistributions +of the Apple Software. +Neither the name, trademarks, service marks or logos of Apple Inc. may be used +to endorse or promote products derived from the Apple Software without specific +prior written permission from Apple. Except as expressly stated in this notice, +no other rights or licenses, express or implied, are granted by Apple herein, +including but not limited to any patent rights that may be infringed by your +derivative works or by other works in which the Apple Software may be +incorporated. + +The Apple Software is provided by Apple on an "AS IS" basis. APPLE MAKES NO +WARRANTIES, EXPRESS OR IMPLIED, INCLUDING WITHOUT LIMITATION THE IMPLIED +WARRANTIES OF NON-INFRINGEMENT, MERCHANTABILITY AND FITNESS FOR A PARTICULAR +PURPOSE, REGARDING THE APPLE SOFTWARE OR ITS USE AND OPERATION ALONE OR IN +COMBINATION WITH YOUR PRODUCTS. + +IN NO EVENT SHALL APPLE BE LIABLE FOR ANY SPECIAL, INDIRECT, INCIDENTAL OR +CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE +GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) +ARISING IN ANY WAY OUT OF THE USE, REPRODUCTION, MODIFICATION AND/OR +DISTRIBUTION OF THE APPLE SOFTWARE, HOWEVER CAUSED AND WHETHER UNDER THEORY OF +CONTRACT, TORT (INCLUDING NEGLIGENCE), STRICT LIABILITY OR OTHERWISE, EVEN IF +APPLE HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +Copyright (C) 2008 Apple Inc. All Rights Reserved. + +*/ + +#import + +#import "Platforms/CCGL.h" +#import "CCTexture2D.h" + + +#pragma mark - +#pragma mark CCTexturePVR + +struct CCPVRMipmap { + unsigned char *address; + unsigned int len; +}; + +typedef struct _ccPVRTexturePixelFormatInfo { + GLenum internalFormat; + GLenum format; + GLenum type; + uint32_t bpp; + BOOL compressed; + BOOL alpha; + CCTexture2DPixelFormat ccPixelFormat; +} ccPVRTexturePixelFormatInfo; + +enum { + CC_PVRMIPMAP_MAX = 16, +}; + +/** CCTexturePVR + + Object that loads PVR images. + + Supported PVR formats: + - RGBA8888 + - BGRA8888 + - RGBA4444 + - RGBA5551 + - RGB565 + - A8 + - I8 + - AI88 + - PVRTC 4BPP + - PVRTC 2BPP + + Limitations: + Pre-generated mipmaps, such as PVR textures with mipmap levels embedded in file, + are only supported if all individual sprites are of _square_ size. + To use mipmaps with non-square textures, instead call CCTexture2D#generateMipmap on the sheet texture itself + (and to save space, save the PVR sprite sheet without mip maps included). + */ +@interface CCTexturePVR : NSObject +{ + struct CCPVRMipmap _mipmaps[CC_PVRMIPMAP_MAX]; // pointer to mipmap images + NSUInteger _numberOfMipmaps; // number of mipmap used + + uint32_t _width, _height; + GLuint _name; + BOOL _hasAlpha; + BOOL _hasPremultipliedAlpha; + BOOL _forcePremultipliedAlpha; + + // cocos2d integration + BOOL _retainName; + CCTexture2DPixelFormat _format; + + const ccPVRTexturePixelFormatInfo *_pixelFormatInfo; +} + +/** initializes a CCTexturePVR with a path */ +- (id)initWithContentsOfFile:(NSString *)path; +/** initializes a CCTexturePVR with an URL */ +- (id)initWithContentsOfURL:(NSURL *)url; +/** creates and initializes a CCTexturePVR with a path */ ++ (id)pvrTextureWithContentsOfFile:(NSString *)path; +/** creates and initializes a CCTexturePVR with an URL */ ++ (id)pvrTextureWithContentsOfURL:(NSURL *)url; + +/** texture id name */ +@property (nonatomic,readonly) GLuint name; +/** texture width */ +@property (nonatomic,readonly) uint32_t width; +/** texture height */ +@property (nonatomic,readonly) uint32_t height; +/** whether or not the texture has alpha */ +@property (nonatomic,readonly) BOOL hasAlpha; +/** whether or not the texture has premultiplied alpha */ +@property (nonatomic,readonly) BOOL hasPremultipliedAlpha; +/** whether or not the texture should use hasPremultipliedAlpha instead of global default */ +@property (nonatomic,readonly) BOOL forcePremultipliedAlpha; +/** how many mipmaps the texture has. 1 means one level (level 0 */ +@property (nonatomic, readonly) NSUInteger numberOfMipmaps; + +// cocos2d integration +@property (nonatomic,readwrite) BOOL retainName; +@property (nonatomic,readonly) CCTexture2DPixelFormat format; + +@end + + diff --git "a/21451198\345\215\242\350\266\205/project5/MyPlane/libs/cocos2d/CCTexturePVR.m" "b/21451198\345\215\242\350\266\205/project5/MyPlane/libs/cocos2d/CCTexturePVR.m" new file mode 100644 index 00000000..8cc359d5 --- /dev/null +++ "b/21451198\345\215\242\350\266\205/project5/MyPlane/libs/cocos2d/CCTexturePVR.m" @@ -0,0 +1,708 @@ +/* + +File: PVRTexture.m +Abstract: The PVRTexture class is responsible for loading .pvr files. + +Version: 1.0 + +Disclaimer: IMPORTANT: This Apple software is supplied to you by Apple Inc. +("Apple") in consideration of your agreement to the following terms, and your +use, installation, modification or redistribution of this Apple software +constitutes acceptance of these terms. If you do not agree with these terms, +please do not use, install, modify or redistribute this Apple software. + +In consideration of your agreement to abide by the following terms, and subject +to these terms, Apple grants you a personal, non-exclusive license, under +Apple's copyrights in this original Apple software (the "Apple Software"), to +use, reproduce, modify and redistribute the Apple Software, with or without +modifications, in source and/or binary forms; provided that if you redistribute +the Apple Software in its entirety and without modifications, you must retain +this notice and the following text and disclaimers in all such redistributions +of the Apple Software. +Neither the name, trademarks, service marks or logos of Apple Inc. may be used +to endorse or promote products derived from the Apple Software without specific +prior written permission from Apple. Except as expressly stated in this notice, +no other rights or licenses, express or implied, are granted by Apple herein, +including but not limited to any patent rights that may be infringed by your +derivative works or by other works in which the Apple Software may be +incorporated. + +The Apple Software is provided by Apple on an "AS IS" basis. APPLE MAKES NO +WARRANTIES, EXPRESS OR IMPLIED, INCLUDING WITHOUT LIMITATION THE IMPLIED +WARRANTIES OF NON-INFRINGEMENT, MERCHANTABILITY AND FITNESS FOR A PARTICULAR +PURPOSE, REGARDING THE APPLE SOFTWARE OR ITS USE AND OPERATION ALONE OR IN +COMBINATION WITH YOUR PRODUCTS. + +IN NO EVENT SHALL APPLE BE LIABLE FOR ANY SPECIAL, INDIRECT, INCIDENTAL OR +CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE +GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) +ARISING IN ANY WAY OUT OF THE USE, REPRODUCTION, MODIFICATION AND/OR +DISTRIBUTION OF THE APPLE SOFTWARE, HOWEVER CAUSED AND WHETHER UNDER THEORY OF +CONTRACT, TORT (INCLUDING NEGLIGENCE), STRICT LIABILITY OR OTHERWISE, EVEN IF +APPLE HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +Copyright (C) 2008 Apple Inc. All Rights Reserved. + +*/ + +/* + * Extended PVR formats for cocos2d project ( http://www.cocos2d-iphone.org ) + * - RGBA8888 + * - BGRA8888 + * - RGB888 + * - RGBA4444 + * - RGBA5551 + * - RGB565 + * - A8 + * - I8 + * - AI88 + * + * Added support for PVR v3 file format + */ + +#import + +#import "CCTexturePVR.h" +#import "ccMacros.h" +#import "CCConfiguration.h" +#import "ccGLStateCache.h" +#import "Support/ccUtils.h" +#import "Support/CCFileUtils.h" +#import "Support/ZipUtils.h" +#import "Support/OpenGL_Internal.h" + +#pragma mark - +#pragma mark CCTexturePVR + +#define PVR_TEXTURE_FLAG_TYPE_MASK 0xff + +#pragma mark PVR File format - common + +// +// XXX DO NO ALTER THE ORDER IN THIS LIST XXX +// +static const ccPVRTexturePixelFormatInfo PVRTableFormats[] = { + + // 0: BGRA_8888 + {GL_RGBA, GL_BGRA, GL_UNSIGNED_BYTE, 32, NO, YES, kCCTexture2DPixelFormat_RGBA8888}, + // 1: RGBA_8888 + {GL_RGBA, GL_RGBA, GL_UNSIGNED_BYTE, 32, NO, YES, kCCTexture2DPixelFormat_RGBA8888}, + // 2: RGBA_4444 + {GL_RGBA, GL_RGBA, GL_UNSIGNED_SHORT_4_4_4_4, 16, NO, YES, kCCTexture2DPixelFormat_RGBA4444}, + // 3: RGBA_5551 + {GL_RGBA, GL_RGBA, GL_UNSIGNED_SHORT_5_5_5_1, 16, NO, YES, kCCTexture2DPixelFormat_RGB5A1}, + // 4: RGB_565 + {GL_RGB, GL_RGB, GL_UNSIGNED_SHORT_5_6_5, 16, NO, NO, kCCTexture2DPixelFormat_RGB565}, + // 5: RGB_888 + {GL_RGB, GL_RGB, GL_UNSIGNED_BYTE, 24, NO, NO, kCCTexture2DPixelFormat_RGB888}, + // 6: A_8 + {GL_ALPHA, GL_ALPHA, GL_UNSIGNED_BYTE, 8, NO, NO, kCCTexture2DPixelFormat_A8}, + // 7: L_8 + {GL_LUMINANCE, GL_LUMINANCE, GL_UNSIGNED_BYTE, 8, NO, NO, kCCTexture2DPixelFormat_I8}, + // 8: LA_88 + {GL_LUMINANCE_ALPHA, GL_LUMINANCE_ALPHA, GL_UNSIGNED_BYTE, 16, NO, YES, kCCTexture2DPixelFormat_AI88}, + +#ifdef __CC_PLATFORM_IOS + // 9: PVRTC 2BPP RGB + {GL_COMPRESSED_RGB_PVRTC_2BPPV1_IMG, -1, -1, 2, YES, NO, kCCTexture2DPixelFormat_PVRTC2}, + // 10: PVRTC 2BPP RGBA + {GL_COMPRESSED_RGBA_PVRTC_2BPPV1_IMG, -1, -1, 2, YES, YES, kCCTexture2DPixelFormat_PVRTC2}, + // 11: PVRTC 4BPP RGB + {GL_COMPRESSED_RGB_PVRTC_4BPPV1_IMG, -1, -1, 4, YES, NO, kCCTexture2DPixelFormat_PVRTC4}, + // 12: PVRTC 4BPP RGBA + {GL_COMPRESSED_RGBA_PVRTC_4BPPV1_IMG, -1, -1, 4, YES, YES, kCCTexture2DPixelFormat_PVRTC4}, +#endif // #__CC_PLATFORM_IOS +}; + +struct _pixel_formathash { + uint64_t pixelFormat; + const ccPVRTexturePixelFormatInfo * pixelFormatInfo; +}; + + +#pragma mark PVR File formats for v2 and v3 + +// Values taken from PVRTexture.h from http://www.imgtec.com +enum { + kPVR2TextureFlagMipmap = (1<<8), // has mip map levels + kPVR2TextureFlagTwiddle = (1<<9), // is twiddled + kPVR2TextureFlagBumpmap = (1<<10), // has normals encoded for a bump map + kPVR2TextureFlagTiling = (1<<11), // is bordered for tiled pvr + kPVR2TextureFlagCubemap = (1<<12), // is a cubemap/skybox + kPVR2TextureFlagFalseMipCol = (1<<13), // are there false coloured MIP levels + kPVR2TextureFlagVolume = (1<<14), // is this a volume texture + kPVR2TextureFlagAlpha = (1<<15), // v2.1 is there transparency info in the texture + kPVR2TextureFlagVerticalFlip = (1<<16), // v2.1 is the texture vertically flipped +}; + +enum { + kPVR3TextureFlagPremultipliedAlpha = (1<<1) // has premultiplied alpha +}; + + +static char gPVRTexIdentifier[4] = "PVR!"; + +// v2 +typedef enum +{ + kPVR2TexturePixelFormat_RGBA_4444= 0x10, + kPVR2TexturePixelFormat_RGBA_5551, + kPVR2TexturePixelFormat_RGBA_8888, + kPVR2TexturePixelFormat_RGB_565, + kPVR2TexturePixelFormat_RGB_555, // unsupported + kPVR2TexturePixelFormat_RGB_888, + kPVR2TexturePixelFormat_I_8, + kPVR2TexturePixelFormat_AI_88, + kPVR2TexturePixelFormat_PVRTC_2BPP_RGBA, + kPVR2TexturePixelFormat_PVRTC_4BPP_RGBA, + kPVR2TexturePixelFormat_BGRA_8888, + kPVR2TexturePixelFormat_A_8, +} ccPVR2TexturePixelFormat; + +// v3 +typedef enum { + /* supported predefined formats */ + kPVR3TexturePixelFormat_PVRTC_2BPP_RGB = 0, + kPVR3TexturePixelFormat_PVRTC_2BPP_RGBA = 1, + kPVR3TexturePixelFormat_PVRTC_4BPP_RGB = 2, + kPVR3TexturePixelFormat_PVRTC_4BPP_RGBA = 3, + + /* supported channel type formats */ + kPVR3TexturePixelFormat_BGRA_8888 = 0x0808080861726762, + kPVR3TexturePixelFormat_RGBA_8888 = 0x0808080861626772, + kPVR3TexturePixelFormat_RGBA_4444 = 0x0404040461626772, + kPVR3TexturePixelFormat_RGBA_5551 = 0x0105050561626772, + kPVR3TexturePixelFormat_RGB_565 = 0x0005060500626772, + kPVR3TexturePixelFormat_RGB_888 = 0x0008080800626772, + kPVR3TexturePixelFormat_A_8 = 0x0000000800000061, + kPVR3TexturePixelFormat_L_8 = 0x000000080000006c, + kPVR3TexturePixelFormat_LA_88 = 0x000008080000616c, +} ccPVR3TexturePixelFormat; + +// v2 +static struct _pixel_formathash v2_pixel_formathash[] = { + + { kPVR2TexturePixelFormat_BGRA_8888, &PVRTableFormats[0] }, + { kPVR2TexturePixelFormat_RGBA_8888, &PVRTableFormats[1] }, + { kPVR2TexturePixelFormat_RGBA_4444, &PVRTableFormats[2] }, + { kPVR2TexturePixelFormat_RGBA_5551, &PVRTableFormats[3] }, + { kPVR2TexturePixelFormat_RGB_565, &PVRTableFormats[4] }, + { kPVR2TexturePixelFormat_RGB_888, &PVRTableFormats[5] }, + { kPVR2TexturePixelFormat_A_8, &PVRTableFormats[6] }, + { kPVR2TexturePixelFormat_I_8, &PVRTableFormats[7] }, + { kPVR2TexturePixelFormat_AI_88, &PVRTableFormats[8] }, + +#ifdef __CC_PLATFORM_IOS + { kPVR2TexturePixelFormat_PVRTC_2BPP_RGBA, &PVRTableFormats[10] }, + { kPVR2TexturePixelFormat_PVRTC_4BPP_RGBA, &PVRTableFormats[12] }, +#endif // iphone only +}; + +#define PVR2_MAX_TABLE_ELEMENTS (sizeof(v2_pixel_formathash) / sizeof(v2_pixel_formathash[0])) + +// v3 +struct _pixel_formathash v3_pixel_formathash[] = { + + {kPVR3TexturePixelFormat_BGRA_8888, &PVRTableFormats[0] }, + {kPVR3TexturePixelFormat_RGBA_8888, &PVRTableFormats[1] }, + {kPVR3TexturePixelFormat_RGBA_4444, &PVRTableFormats[2] }, + {kPVR3TexturePixelFormat_RGBA_5551, &PVRTableFormats[3] }, + {kPVR3TexturePixelFormat_RGB_565, &PVRTableFormats[4] }, + {kPVR3TexturePixelFormat_RGB_888, &PVRTableFormats[5] }, + {kPVR3TexturePixelFormat_A_8, &PVRTableFormats[6] }, + {kPVR3TexturePixelFormat_L_8, &PVRTableFormats[7] }, + {kPVR3TexturePixelFormat_LA_88, &PVRTableFormats[8] }, + +#ifdef __CC_PLATFORM_IOS + {kPVR3TexturePixelFormat_PVRTC_2BPP_RGB, &PVRTableFormats[9] }, + {kPVR3TexturePixelFormat_PVRTC_2BPP_RGBA, &PVRTableFormats[10] }, + {kPVR3TexturePixelFormat_PVRTC_4BPP_RGB, &PVRTableFormats[11] }, + {kPVR3TexturePixelFormat_PVRTC_4BPP_RGBA, &PVRTableFormats[12] }, +#endif // #__CC_PLATFORM_IOS +}; + +#define PVR3_MAX_TABLE_ELEMENTS (sizeof(v3_pixel_formathash) / sizeof(v3_pixel_formathash[0])) + +typedef struct _PVRTexHeader +{ + uint32_t headerLength; + uint32_t height; + uint32_t width; + uint32_t numMipmaps; + uint32_t flags; + uint32_t dataLength; + uint32_t bpp; + uint32_t bitmaskRed; + uint32_t bitmaskGreen; + uint32_t bitmaskBlue; + uint32_t bitmaskAlpha; + uint32_t pvrTag; + uint32_t numSurfs; +} ccPVRv2TexHeader; + +typedef struct { + uint32_t version; + uint32_t flags; + uint64_t pixelFormat; + uint32_t colorSpace; + uint32_t channelType; + uint32_t height; + uint32_t width; + uint32_t depth; + uint32_t numberOfSurfaces; + uint32_t numberOfFaces; + uint32_t numberOfMipmaps; + uint32_t metadataLength; +} __attribute__((packed)) ccPVRv3TexHeader ; + +@implementation CCTexturePVR +@synthesize name = _name; +@synthesize width = _width; +@synthesize height = _height; +@synthesize hasAlpha = _hasAlpha; +@synthesize hasPremultipliedAlpha = _hasPremultipliedAlpha; +@synthesize forcePremultipliedAlpha = _forcePremultipliedAlpha; +@synthesize numberOfMipmaps = _numberOfMipmaps; + +// cocos2d integration +@synthesize retainName = _retainName; +@synthesize format = _format; + + +- (BOOL)unpackPVRv2Data:(unsigned char*)data PVRLen:(NSUInteger)len +{ + BOOL success = NO; + ccPVRv2TexHeader *header = NULL; + uint32_t flags, pvrTag; + uint32_t dataLength = 0, dataOffset = 0, dataSize = 0; + uint32_t blockSize = 0, widthBlocks = 0, heightBlocks = 0; + uint32_t width = 0, height = 0, bpp = 4; + uint8_t *bytes = NULL; + uint32_t formatFlags; + + header = (ccPVRv2TexHeader *)data; + + pvrTag = CFSwapInt32LittleToHost(header->pvrTag); + + if ((uint32_t)gPVRTexIdentifier[0] != ((pvrTag >> 0) & 0xff) || + (uint32_t)gPVRTexIdentifier[1] != ((pvrTag >> 8) & 0xff) || + (uint32_t)gPVRTexIdentifier[2] != ((pvrTag >> 16) & 0xff) || + (uint32_t)gPVRTexIdentifier[3] != ((pvrTag >> 24) & 0xff)) + { + return NO; + } + + CCConfiguration *configuration = [CCConfiguration sharedConfiguration]; + + flags = CFSwapInt32LittleToHost(header->flags); + formatFlags = flags & PVR_TEXTURE_FLAG_TYPE_MASK; + BOOL flipped = flags & kPVR2TextureFlagVerticalFlip; + if( flipped ) + CCLOGWARN(@"cocos2d: WARNING: Image is flipped. Regenerate it using PVRTexTool"); + + if( ! [configuration supportsNPOT] && + ( header->width != ccNextPOT(header->width) || header->height != ccNextPOT(header->height ) ) ) { + CCLOGWARN(@"cocos2d: ERROR: Loding an NPOT texture (%dx%d) but is not supported on this device", header->width, header->height); + return NO; + } + + for( NSUInteger i=0; i < (unsigned int)PVR2_MAX_TABLE_ELEMENTS ; i++) { + if( v2_pixel_formathash[i].pixelFormat == formatFlags ) { + + _pixelFormatInfo = v2_pixel_formathash[i].pixelFormatInfo; + _numberOfMipmaps = 0; + + _width = width = CFSwapInt32LittleToHost(header->width); + _height = height = CFSwapInt32LittleToHost(header->height); + + if (CFSwapInt32LittleToHost(header->bitmaskAlpha)) + _hasAlpha = YES; + else + _hasAlpha = NO; + + dataLength = CFSwapInt32LittleToHost(header->dataLength); + bytes = ((uint8_t *)data) + sizeof(ccPVRv2TexHeader); + _format = _pixelFormatInfo->ccPixelFormat; + bpp = _pixelFormatInfo->bpp; + + // Calculate the data size for each texture level and respect the minimum number of blocks + while (dataOffset < dataLength) + { + switch (formatFlags) { + case kPVR2TexturePixelFormat_PVRTC_2BPP_RGBA: + blockSize = 8 * 4; // Pixel by pixel block size for 2bpp + widthBlocks = width / 8; + heightBlocks = height / 4; + break; + case kPVR2TexturePixelFormat_PVRTC_4BPP_RGBA: + blockSize = 4 * 4; // Pixel by pixel block size for 4bpp + widthBlocks = width / 4; + heightBlocks = height / 4; + break; + case kPVR2TexturePixelFormat_BGRA_8888: + if( ! [[CCConfiguration sharedConfiguration] supportsBGRA8888] ) { + CCLOG(@"cocos2d: TexturePVR. BGRA8888 not supported on this device"); + return NO; + } + default: + blockSize = 1; + widthBlocks = width; + heightBlocks = height; + break; + } + + // Clamp to minimum number of blocks + if (widthBlocks < 2) + widthBlocks = 2; + if (heightBlocks < 2) + heightBlocks = 2; + + dataSize = widthBlocks * heightBlocks * ((blockSize * bpp) / 8); + unsigned int packetLength = (dataLength-dataOffset); + packetLength = packetLength > dataSize ? dataSize : packetLength; + + _mipmaps[_numberOfMipmaps].address = bytes+dataOffset; + _mipmaps[_numberOfMipmaps].len = packetLength; + _numberOfMipmaps++; + + NSAssert( _numberOfMipmaps < CC_PVRMIPMAP_MAX, @"TexturePVR: Maximum number of mimpaps reached. Increate the CC_PVRMIPMAP_MAX value"); + + dataOffset += packetLength; + + width = MAX(width >> 1, 1); + height = MAX(height >> 1, 1); + } + + success = YES; + break; + } + } + + if( ! success ) + CCLOGWARN(@"cocos2d: WARNING: Unsupported PVR Pixel Format: 0x%2x. Re-encode it with a OpenGL pixel format variant", formatFlags); + + return success; +} + +- (BOOL)unpackPVRv3Data:(unsigned char*)dataPointer PVRLen:(NSUInteger)dataLength +{ + if(dataLength < sizeof(ccPVRv3TexHeader)) { + return NO; + } + + ccPVRv3TexHeader *header = (ccPVRv3TexHeader *)dataPointer; + + // validate version + if(CFSwapInt32BigToHost(header->version) != 0x50565203) { + CCLOG(@"cocos2d: WARNING: pvr file version mismatch"); + return NO; + } + + // parse pixel format + uint64_t pixelFormat = header->pixelFormat; + + + BOOL infoValid = NO; + + for(int i = 0; i < PVR3_MAX_TABLE_ELEMENTS; i++) { + if( v3_pixel_formathash[i].pixelFormat == pixelFormat ) { + _pixelFormatInfo = v3_pixel_formathash[i].pixelFormatInfo; + _hasAlpha = _pixelFormatInfo->alpha; + infoValid = YES; + break; + } + } + + // unsupported / bad pixel format + if(!infoValid) { + CCLOG(@"cocos2d: WARNING: unsupported pvr pixelformat: %llx", pixelFormat ); + return NO; + } + + // flags + uint32_t flags = CFSwapInt32LittleToHost(header->flags); + + // PVRv3 specifies premultiply alpha in a flag -- should always respect this in PVRv3 files + _forcePremultipliedAlpha = YES; + if(flags & kPVR3TextureFlagPremultipliedAlpha) { + _hasPremultipliedAlpha = YES; + } + + // sizing + uint32_t width = CFSwapInt32LittleToHost(header->width); + uint32_t height = CFSwapInt32LittleToHost(header->height); + _width = width; + _height = height; + uint32_t dataOffset = 0, dataSize = 0; + uint32_t blockSize = 0, widthBlocks = 0, heightBlocks = 0; + uint8_t *bytes = NULL; + + dataOffset = (sizeof(ccPVRv3TexHeader) + header->metadataLength); + bytes = dataPointer; + + _numberOfMipmaps = header->numberOfMipmaps; + NSAssert( _numberOfMipmaps < CC_PVRMIPMAP_MAX, @"TexturePVR: Maximum number of mimpaps reached. Increate the CC_PVRMIPMAP_MAX value"); + + for(int i = 0; i < _numberOfMipmaps; i++) { + + switch(pixelFormat) { + case kPVR3TexturePixelFormat_PVRTC_2BPP_RGB : + case kPVR3TexturePixelFormat_PVRTC_2BPP_RGBA : + blockSize = 8 * 4; // Pixel by pixel block size for 2bpp + widthBlocks = width / 8; + heightBlocks = height / 4; + break; + case kPVR3TexturePixelFormat_PVRTC_4BPP_RGB : + case kPVR3TexturePixelFormat_PVRTC_4BPP_RGBA : + blockSize = 4 * 4; // Pixel by pixel block size for 4bpp + widthBlocks = width / 4; + heightBlocks = height / 4; + break; + case kPVR3TexturePixelFormat_BGRA_8888: + if( ! [[CCConfiguration sharedConfiguration] supportsBGRA8888] ) { + CCLOG(@"cocos2d: TexturePVR. BGRA8888 not supported on this device"); + return NO; + } + default: + blockSize = 1; + widthBlocks = width; + heightBlocks = height; + break; + } + + // Clamp to minimum number of blocks + if (widthBlocks < 2) + widthBlocks = 2; + if (heightBlocks < 2) + heightBlocks = 2; + + dataSize = widthBlocks * heightBlocks * ((blockSize * _pixelFormatInfo->bpp) / 8); + unsigned int packetLength = ((unsigned int)dataLength-dataOffset); + packetLength = packetLength > dataSize ? dataSize : packetLength; + + _mipmaps[i].address = bytes+dataOffset; + _mipmaps[i].len = packetLength; + + dataOffset += packetLength; + NSAssert( dataOffset <= dataLength, @"CCTexurePVR: Invalid length"); + + + width = MAX(width >> 1, 1); + height = MAX(height >> 1, 1); + } + + return YES; +} + + +- (BOOL)createGLTexture +{ + GLsizei width = _width; + GLsizei height = _height; + GLenum err; + + if (_numberOfMipmaps > 0) + { + if (_name != 0) + ccGLDeleteTexture( _name ); + + // From PVR sources: "PVR files are never row aligned." + glPixelStorei(GL_UNPACK_ALIGNMENT,1); + + glGenTextures(1, &_name); + ccGLBindTexture2D( _name ); + + // Default: Anti alias. + if( _numberOfMipmaps == 1 ) + glTexParameteri( GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR ); + else + glTexParameteri( GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR_MIPMAP_NEAREST ); + glTexParameteri( GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR ); + + glTexParameteri( GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE ); + glTexParameteri( GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE ); + } + + CHECK_GL_ERROR(); // clean possible GL error + + GLenum internalFormat = _pixelFormatInfo->internalFormat; + GLenum format = _pixelFormatInfo->format; + GLenum type = _pixelFormatInfo->type; + BOOL compressed = _pixelFormatInfo->compressed; + + // Generate textures with mipmaps + for (GLint i=0; i < _numberOfMipmaps; i++) + { + if( compressed && ! [[CCConfiguration sharedConfiguration] supportsPVRTC] ) { + CCLOGWARN(@"cocos2d: WARNING: PVRTC images are not supported"); + return NO; + } + + unsigned char *data = _mipmaps[i].address; + GLsizei datalen = _mipmaps[i].len; + + if( compressed) + glCompressedTexImage2D(GL_TEXTURE_2D, i, internalFormat, width, height, 0, datalen, data); + else + glTexImage2D(GL_TEXTURE_2D, i, internalFormat, width, height, 0, format, type, data); + + if( i > 0 && (width != height || ccNextPOT(width) != width ) ) + CCLOGWARN(@"cocos2d: TexturePVR. WARNING. Mipmap level %u is not squared. Texture won't render correctly. width=%u != height=%u", i, width, height); + + err = glGetError(); + if (err != GL_NO_ERROR) + { + CCLOGWARN(@"cocos2d: TexturePVR: Error uploading compressed texture level: %u . glError: 0x%04X", i, err); + return NO; + } + + width = MAX(width >> 1, 1); + height = MAX(height >> 1, 1); + } + + return YES; +} + + +- (id)initWithContentsOfFile:(NSString *)path +{ + if((self = [super init])) + { + unsigned char *pvrdata = NULL; + NSInteger pvrlen = 0; + NSString *lowerCase = [path lowercaseString]; + + if ( [lowerCase hasSuffix:@".ccz"]) + pvrlen = ccInflateCCZFile( [path UTF8String], &pvrdata ); + + else if( [lowerCase hasSuffix:@".gz"] ) + pvrlen = ccInflateGZipFile( [path UTF8String], &pvrdata ); + + else + pvrlen = ccLoadFileIntoMemory( [path UTF8String], &pvrdata ); + + if( pvrlen < 0 ) { + [self release]; + return nil; + } + + + _numberOfMipmaps = 0; + + _name = 0; + _width = _height = 0; + _hasAlpha = NO; + _hasPremultipliedAlpha = NO; + _forcePremultipliedAlpha = NO; + _pixelFormatInfo = NULL; + + _retainName = NO; // cocos2d integration + + + if( ! (([self unpackPVRv2Data:pvrdata PVRLen:pvrlen] || [self unpackPVRv3Data:pvrdata PVRLen:pvrlen]) && + [self createGLTexture] ) ) + { + free(pvrdata); + [self release]; + return nil; + } + +#if defined(__CC_PLATFORM_IOS) && defined(DEBUG) + + GLenum pixelFormat = _pixelFormatInfo->ccPixelFormat; + CCConfiguration *conf = [CCConfiguration sharedConfiguration]; + + if( [conf OSVersion] >= kCCiOSVersion_5_0 ) + { + + // iOS 5 BUG: + // RGB888 textures allocate much more memory than needed on iOS 5 + // http://www.cocos2d-iphone.org/forum/topic/31092 + + if( pixelFormat == kCCTexture2DPixelFormat_RGB888 ) { + printf("\n"); + NSLog(@"cocos2d: WARNING. Using RGB888 texture. Convert it to RGB565 or RGBA8888 in order to reduce memory"); + NSLog(@"cocos2d: WARNING: File: %@", [path lastPathComponent] ); + NSLog(@"cocos2d: WARNING: For further info visit: http://www.cocos2d-iphone.org/forum/topic/31092"); + printf("\n"); + } + + + else if( _width != ccNextPOT(_width) ) { + + // XXX: Is this applicable for compressed textures ? + // Since they are squared and POT (PVRv2) it is not an issue now. Not sure in the future. + + // iOS 5 BUG: + // If width is not word aligned, then log warning. + // http://www.cocos2d-iphone.org/forum/topic/31092 + + + NSUInteger bpp = [CCTexture2D bitsPerPixelForFormat:pixelFormat]; + NSUInteger bytes = _width * bpp / 8; + + // XXX: Should it be 4 or sizeof(int) ?? + NSUInteger mod = bytes % 4; + + // Not word aligned ? + if( mod != 0 ) { + + NSUInteger neededBytes = (4 - mod ) / (bpp/8); + printf("\n"); + NSLog(@"cocos2d: WARNING. Current texture size=(%d,%d). Convert it to size=(%d,%d) in order to save memory", _width, _height, _width + neededBytes, _height ); + NSLog(@"cocos2d: WARNING: File: %@", [path lastPathComponent] ); + NSLog(@"cocos2d: WARNING: For further info visit: http://www.cocos2d-iphone.org/forum/topic/31092"); + printf("\n"); + } + } + } +#endif // iOS + + + + free(pvrdata); + } + + return self; +} + +- (id)initWithContentsOfURL:(NSURL *)url +{ + if (![url isFileURL]) + { + CCLOG(@"cocos2d: CCPVRTexture: Only files are supported"); + [self release]; + return nil; + } + + return [self initWithContentsOfFile:[url path]]; +} + + ++ (id)pvrTextureWithContentsOfFile:(NSString *)path +{ + return [[[self alloc] initWithContentsOfFile:path] autorelease]; +} + + ++ (id)pvrTextureWithContentsOfURL:(NSURL *)url +{ + if (![url isFileURL]) + return nil; + + return [CCTexturePVR pvrTextureWithContentsOfFile:[url path]]; +} + + +- (void)dealloc +{ + CCLOGINFO( @"cocos2d: deallocing %@", self); + + if (_name != 0 && ! _retainName ) + ccGLDeleteTexture( _name ); + + [super dealloc]; +} + +@end + diff --git "a/21451198\345\215\242\350\266\205/project5/MyPlane/libs/cocos2d/CCTileMapAtlas.h" "b/21451198\345\215\242\350\266\205/project5/MyPlane/libs/cocos2d/CCTileMapAtlas.h" new file mode 100644 index 00000000..8033cf33 --- /dev/null +++ "b/21451198\345\215\242\350\266\205/project5/MyPlane/libs/cocos2d/CCTileMapAtlas.h" @@ -0,0 +1,83 @@ +/* + * cocos2d for iPhone: http://www.cocos2d-iphone.org + * + * Copyright (c) 2008-2010 Ricardo Quesada + * Copyright (c) 2011 Zynga Inc. + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + * THE SOFTWARE. + * + */ + +#import "CCTextureAtlas.h" +#import "CCAtlasNode.h" +#import "Support/TGAlib.h" + +/** CCTileMapAtlas is a subclass of CCAtlasNode. + + It knows how to render a map based of tiles. + The tiles must be in a .PNG format while the map must be a .TGA file. + + For more information regarding the format, please see this post: + http://www.cocos2d-iphone.org/archives/27 + + All features from CCAtlasNode are valid in CCTileMapAtlas + + IMPORTANT: + This class is deprecated. It is maintained for compatibility reasons only. + You SHOULD not use this class. + Instead, use the newer TMX file format: CCTMXTiledMap + */ +@interface CCTileMapAtlas : CCAtlasNode +{ + + /// info about the map file + tImageTGA *_tgaInfo; + + /// x,y to altas dictionary + NSMutableDictionary *_posToAtlasIndex; + + /// numbers of tiles to render + int _itemsToRender; +} + +/** TileMap info */ +@property (nonatomic,readonly) tImageTGA *tgaInfo; + +/** creates a CCTileMap with a tile file (atlas) with a map file and the width and height of each tile in points. + The tile file will be loaded using the TextureMgr. + */ ++(id) tileMapAtlasWithTileFile:(NSString*)tile mapFile:(NSString*)map tileWidth:(int)w tileHeight:(int)h; + +/** initializes a CCTileMap with a tile file (atlas) with a map file and the width and height of each tile in points. + The file will be loaded using the TextureMgr. + */ +-(id) initWithTileFile:(NSString*)tile mapFile:(NSString*)map tileWidth:(int)w tileHeight:(int)h; + +/** returns a tile from position x,y. + For the moment only channel R is used + */ +-(ccColor3B) tileAt: (CGPoint) position; + +/** sets a tile at position x,y. + For the moment only channel R is used + */ +-(void) setTile:(ccColor3B)tile at:(CGPoint)position; +/** dealloc the map from memory */ +-(void) releaseMap; +@end diff --git "a/21451198\345\215\242\350\266\205/project5/MyPlane/libs/cocos2d/CCTileMapAtlas.m" "b/21451198\345\215\242\350\266\205/project5/MyPlane/libs/cocos2d/CCTileMapAtlas.m" new file mode 100644 index 00000000..dd8d0c73 --- /dev/null +++ "b/21451198\345\215\242\350\266\205/project5/MyPlane/libs/cocos2d/CCTileMapAtlas.m" @@ -0,0 +1,244 @@ +/* + * cocos2d for iPhone: http://www.cocos2d-iphone.org + * + * Copyright (c) 2008-2010 Ricardo Quesada + * Copyright (c) 2011 Zynga Inc. + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + * THE SOFTWARE. + * + */ + +#import "ccConfig.h" +#import "CCTileMapAtlas.h" +#import "ccMacros.h" +#import "Support/CCFileUtils.h" +#import "Support/CGPointExtension.h" + +@interface CCTileMapAtlas (Private) +-(void) loadTGAfile:(NSString*)file; +-(void) calculateItemsToRender; +-(void) updateAtlasValueAt:(CGPoint)pos withValue:(ccColor3B)value withIndex:(NSUInteger)idx; +@end + + +@implementation CCTileMapAtlas + +@synthesize tgaInfo=_tgaInfo; + +#pragma mark CCTileMapAtlas - Creation & Init ++(id) tileMapAtlasWithTileFile:(NSString*)tile mapFile:(NSString*)map tileWidth:(int)w tileHeight:(int)h +{ + return [[[self alloc] initWithTileFile:tile mapFile:map tileWidth:w tileHeight:h] autorelease]; +} + + +-(id) initWithTileFile:(NSString*)tile mapFile:(NSString*)map tileWidth:(int)w tileHeight:(int)h +{ + [self loadTGAfile: map]; + [self calculateItemsToRender]; + + if( (self=[super initWithTileFile:tile tileWidth:w tileHeight:h itemsToRender: _itemsToRender]) ) { + + _posToAtlasIndex = [[NSMutableDictionary dictionaryWithCapacity:_itemsToRender] retain]; + + [self updateAtlasValues]; + + [self setContentSize: CGSizeMake(_tgaInfo->width*_itemWidth, _tgaInfo->height*_itemHeight)]; + } + + return self; +} + +-(void) dealloc +{ + if( _tgaInfo ) + tgaDestroy(_tgaInfo); + + [_posToAtlasIndex release]; + + [super dealloc]; +} + +-(void) releaseMap +{ + if( _tgaInfo ) + tgaDestroy(_tgaInfo); + + _tgaInfo = nil; + + [_posToAtlasIndex release]; + _posToAtlasIndex = nil; +} + +-(void) calculateItemsToRender +{ + NSAssert( _tgaInfo != nil, @"tgaInfo must be non-nil"); + + _itemsToRender = 0; + for(int x = 0;x < _tgaInfo->width; x++ ) { + for(int y = 0; y < _tgaInfo->height; y++ ) { + ccColor3B *ptr = (ccColor3B*) _tgaInfo->imageData; + ccColor3B value = ptr[x + y * _tgaInfo->width]; + if( value.r ) + _itemsToRender++; + } + } +} + +-(void) loadTGAfile:(NSString*)file +{ + NSAssert( file != nil, @"file must be non-nil"); + + NSString *path = [[CCFileUtils sharedFileUtils] fullPathForFilename:file ]; + +// //Find the path of the file +// NSBundle *mainBndl = [CCDirector sharedDirector].loadingBundle; +// NSString *resourcePath = [mainBndl resourcePath]; +// NSString * path = [resourcePath stringByAppendingPathComponent:file]; + + _tgaInfo = tgaLoad( [path UTF8String] ); +#if 1 + if( _tgaInfo->status != TGA_OK ) + [NSException raise:@"TileMapAtlasLoadTGA" format:@"TileMapAtas cannot load TGA file"]; + +#endif +} + +#pragma mark CCTileMapAtlas - Atlas generation / updates + +-(void) setTile:(ccColor3B) tile at:(CGPoint) pos +{ + NSAssert( _tgaInfo != nil, @"_tgaInfo must not be nil"); + NSAssert( _posToAtlasIndex != nil, @"_posToAtlasIndex must not be nil"); + NSAssert( pos.x < _tgaInfo->width, @"Invalid position.x"); + NSAssert( pos.y < _tgaInfo->height, @"Invalid position.x"); + NSAssert( tile.r != 0, @"R component must be non 0"); + + ccColor3B *ptr = (ccColor3B*) _tgaInfo->imageData; + ccColor3B value = ptr[(NSUInteger)(pos.x + pos.y * _tgaInfo->width)]; + if( value.r == 0 ) + CCLOG(@"cocos2d: Value.r must be non 0."); + else { + ptr[(NSUInteger)(pos.x + pos.y * _tgaInfo->width)] = tile; + + // XXX: this method consumes a lot of memory + // XXX: a tree of something like that shall be impolemented + NSNumber *num = [_posToAtlasIndex objectForKey: [NSString stringWithFormat:@"%ld,%ld", (long)pos.x, (long)pos.y]]; + [self updateAtlasValueAt:pos withValue:tile withIndex: [num integerValue]]; + } +} + +-(ccColor3B) tileAt:(CGPoint) pos +{ + NSAssert( _tgaInfo != nil, @"_tgaInfo must not be nil"); + NSAssert( pos.x < _tgaInfo->width, @"Invalid position.x"); + NSAssert( pos.y < _tgaInfo->height, @"Invalid position.y"); + + ccColor3B *ptr = (ccColor3B*) _tgaInfo->imageData; + ccColor3B value = ptr[(NSUInteger)(pos.x + pos.y * _tgaInfo->width)]; + + return value; +} + +-(void) updateAtlasValueAt:(CGPoint)pos withValue:(ccColor3B)value withIndex:(NSUInteger)idx +{ + ccV3F_C4B_T2F_Quad quad; + + NSInteger x = pos.x; + NSInteger y = pos.y; + float row = (value.r % _itemsPerRow); + float col = (value.r / _itemsPerRow); + + float textureWide = [[_textureAtlas texture] pixelsWide]; + float textureHigh = [[_textureAtlas texture] pixelsHigh]; + + float itemWidthInPixels = _itemWidth * CC_CONTENT_SCALE_FACTOR(); + float itemHeightInPixels = _itemHeight * CC_CONTENT_SCALE_FACTOR(); + + +#if CC_FIX_ARTIFACTS_BY_STRECHING_TEXEL + float left = (2*row*itemWidthInPixels+1)/(2*textureWide); + float right = left+(itemWidthInPixels*2-2)/(2*textureWide); + float top = (2*col*itemHeightInPixels+1)/(2*textureHigh); + float bottom = top+(itemHeightInPixels*2-2)/(2*textureHigh); +#else + float left = (row*itemWidthInPixels)/textureWide; + float right = left+itemWidthInPixels/textureWide; + float top = (col*itemHeightInPixels)/textureHigh; + float bottom = top+itemHeightInPixels/textureHigh; +#endif + + + quad.tl.texCoords.u = left; + quad.tl.texCoords.v = top; + quad.tr.texCoords.u = right; + quad.tr.texCoords.v = top; + quad.bl.texCoords.u = left; + quad.bl.texCoords.v = bottom; + quad.br.texCoords.u = right; + quad.br.texCoords.v = bottom; + + quad.bl.vertices.x = (int) (x * _itemWidth); + quad.bl.vertices.y = (int) (y * _itemHeight); + quad.bl.vertices.z = 0.0f; + quad.br.vertices.x = (int)(x * _itemWidth + _itemWidth); + quad.br.vertices.y = (int)(y * _itemHeight); + quad.br.vertices.z = 0.0f; + quad.tl.vertices.x = (int)(x * _itemWidth); + quad.tl.vertices.y = (int)(y * _itemHeight + _itemHeight); + quad.tl.vertices.z = 0.0f; + quad.tr.vertices.x = (int)(x * _itemWidth + _itemWidth); + quad.tr.vertices.y = (int)(y * _itemHeight + _itemHeight); + quad.tr.vertices.z = 0.0f; + + ccColor4B color = { _displayedColor.r, _displayedColor.g, _displayedColor.b, _displayedOpacity }; + quad.tr.colors = color; + quad.tl.colors = color; + quad.br.colors = color; + quad.bl.colors = color; + [_textureAtlas updateQuad:&quad atIndex:idx]; +} + +-(void) updateAtlasValues +{ + NSAssert( _tgaInfo != nil, @"_tgaInfo must be non-nil"); + + + int total = 0; + + for(int x = 0;x < _tgaInfo->width; x++ ) { + for(int y = 0; y < _tgaInfo->height; y++ ) { + if( total < _itemsToRender ) { + ccColor3B *ptr = (ccColor3B*) _tgaInfo->imageData; + ccColor3B value = ptr[x + y * _tgaInfo->width]; + + if( value.r != 0 ) { + [self updateAtlasValueAt:ccp(x,y) withValue:value withIndex:total]; + + NSString *key = [NSString stringWithFormat:@"%d,%d", x,y]; + NSNumber *num = [NSNumber numberWithInt:total]; + [_posToAtlasIndex setObject:num forKey:key]; + + total++; + } + } + } + } +} +@end diff --git "a/21451198\345\215\242\350\266\205/project5/MyPlane/libs/cocos2d/CCTransition.h" "b/21451198\345\215\242\350\266\205/project5/MyPlane/libs/cocos2d/CCTransition.h" new file mode 100644 index 00000000..6ff57780 --- /dev/null +++ "b/21451198\345\215\242\350\266\205/project5/MyPlane/libs/cocos2d/CCTransition.h" @@ -0,0 +1,341 @@ +/* + * cocos2d for iPhone: http://www.cocos2d-iphone.org + * + * Copyright (c) 2008-2010 Ricardo Quesada + * Copyright (c) 2011 Zynga Inc. + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + * THE SOFTWARE. + * + */ + + +#import "CCScene.h" +@class CCActionInterval; +@class CCNode; + +/** CCTransitionEaseScene can ease the actions of the scene protocol. + @since v0.8.2 + */ +@protocol CCTransitionEaseScene +/** returns the Ease action that will be performed on a linear action. + @since v0.8.2 + */ +-(CCActionInterval*) easeActionWithAction:(CCActionInterval*)action; +@end + +/** Orientation Type used by some transitions + */ +typedef enum { + /// An horizontal orientation where the Left is nearer + kCCTransitionOrientationLeftOver = 0, + /// An horizontal orientation where the Right is nearer + kCCTransitionOrientationRightOver = 1, + /// A vertical orientation where the Up is nearer + kCCTransitionOrientationUpOver = 0, + /// A vertical orientation where the Bottom is nearer + kCCTransitionOrientationDownOver = 1, + + // Deprecated +// kOrientationLeftOver = kCCTransitionOrientationLeftOver, +// kOrientationRightOver = kCCTransitionOrientationRightOver, +// kOrientationUpOver = kCCTransitionOrientationUpOver, +// kOrientationDownOver = kCCTransitionOrientationDownOver, +} tOrientation; + +/** Base class for CCTransition scenes + */ +@interface CCTransitionScene : CCScene +{ + CCScene *_inScene; + CCScene *_outScene; + ccTime _duration; + BOOL _inSceneOnTop; + BOOL _sendCleanupToScene; +} +/** creates a base transition with duration and incoming scene */ ++(id) transitionWithDuration:(ccTime) t scene:(CCScene*)s; +/** initializes a transition with duration and incoming scene */ +-(id) initWithDuration:(ccTime) t scene:(CCScene*)s; +/** called after the transition finishes */ +-(void) finish; +/** used by some transitions to hide the outer scene */ +-(void) hideOutShowIn; +@end + +/** A CCTransition that supports orientation like. + * Possible orientation: LeftOver, RightOver, UpOver, DownOver + */ +@interface CCTransitionSceneOriented : CCTransitionScene +{ + tOrientation orientation; +} +/** creates a base transition with duration and incoming scene */ ++(id) transitionWithDuration:(ccTime) t scene:(CCScene*)s orientation:(tOrientation)o; +/** initializes a transition with duration and incoming scene */ +-(id) initWithDuration:(ccTime) t scene:(CCScene*)s orientation:(tOrientation)o; +@end + + +/** CCTransitionRotoZoom: + Rotate and zoom out the outgoing scene, and then rotate and zoom in the incoming + */ +@interface CCTransitionRotoZoom : CCTransitionScene +{} +// needed for BrdigeSupport +-(id) init; +@end + +/** CCTransitionJumpZoom: + Zoom out and jump the outgoing scene, and then jump and zoom in the incoming +*/ +@interface CCTransitionJumpZoom : CCTransitionScene +{} +// needed for BrdigeSupport +-(id) init; +@end + +/** CCTransitionMoveInL: + Move in from to the left the incoming scene. +*/ +@interface CCTransitionMoveInL : CCTransitionScene +{} +/** initializes the scenes */ +-(void) initScenes; +/** returns the action that will be performed */ +-(CCActionInterval*) action; +@end + +/** CCTransitionMoveInR: + Move in from to the right the incoming scene. + */ +@interface CCTransitionMoveInR : CCTransitionMoveInL +{} +// Needed for BridgeSupport +-(void) initScenes; +@end + +/** CCTransitionMoveInT: + Move in from to the top the incoming scene. + */ +@interface CCTransitionMoveInT : CCTransitionMoveInL +{} +// Needed for BridgeSupport +-(void) initScenes; +@end + +/** CCTransitionMoveInB: + Move in from to the bottom the incoming scene. + */ +@interface CCTransitionMoveInB : CCTransitionMoveInL +{} +// Needed for BridgeSupport +-(void) initScenes; +@end + +/** CCTransitionSlideInL: + Slide in the incoming scene from the left border. + */ +@interface CCTransitionSlideInL : CCTransitionScene +{} +/** initializes the scenes */ +-(void) initScenes; +/** returns the action that will be performed by the incoming and outgoing scene */ +-(CCActionInterval*) action; +@end + +/** CCTransitionSlideInR: + Slide in the incoming scene from the right border. + */ +@interface CCTransitionSlideInR : CCTransitionSlideInL +{} +// Needed for BridgeSupport +-(void) initScenes; +@end + +/** CCTransitionSlideInB: + Slide in the incoming scene from the bottom border. + */ +@interface CCTransitionSlideInB : CCTransitionSlideInL +{} +// Needed for BridgeSupport +-(void) initScenes; +@end + +/** CCTransitionSlideInT: + Slide in the incoming scene from the top border. + */ +@interface CCTransitionSlideInT : CCTransitionSlideInL +{} +// Needed for BridgeSupport +-(void) initScenes; +@end + +/** + Shrink the outgoing scene while grow the incoming scene + */ +@interface CCTransitionShrinkGrow : CCTransitionScene +{} +// needed for BrdigeSupport +-(id) init; +@end + +/** CCTransitionFlipX: + Flips the screen horizontally. + The front face is the outgoing scene and the back face is the incoming scene. + */ +@interface CCTransitionFlipX : CCTransitionSceneOriented +{} +// needed for BrdigeSupport +-(id) init; +@end + +/** CCTransitionFlipY: + Flips the screen vertically. + The front face is the outgoing scene and the back face is the incoming scene. + */ +@interface CCTransitionFlipY : CCTransitionSceneOriented +{} +// needed for BrdigeSupport +-(id) init; +@end + +/** CCTransitionFlipAngular: + Flips the screen half horizontally and half vertically. + The front face is the outgoing scene and the back face is the incoming scene. + */ +@interface CCTransitionFlipAngular : CCTransitionSceneOriented +{} +// needed for BrdigeSupport +-(id) init; +@end + +/** CCTransitionZoomFlipX: + Flips the screen horizontally doing a zoom out/in + The front face is the outgoing scene and the back face is the incoming scene. + */ +@interface CCTransitionZoomFlipX : CCTransitionSceneOriented +{} +// needed for BrdigeSupport +-(id) init; +@end + +/** CCTransitionZoomFlipY: + Flips the screen vertically doing a little zooming out/in + The front face is the outgoing scene and the back face is the incoming scene. + */ +@interface CCTransitionZoomFlipY : CCTransitionSceneOriented +{} +// needed for BrdigeSupport +-(id) init; +@end + +/** CCTransitionZoomFlipAngular: + Flips the screen half horizontally and half vertically doing a little zooming out/in. + The front face is the outgoing scene and the back face is the incoming scene. + */ +@interface CCTransitionZoomFlipAngular : CCTransitionSceneOriented +{} +// needed for BrdigeSupport +-(id) init; +@end + +/** CCTransitionFade: + Fade out the outgoing scene and then fade in the incoming scene.''' + */ +@interface CCTransitionFade : CCTransitionScene +{ + ccColor4B color; +} +/** creates the transition with a duration and with an RGB color + * Example: [FadeTransition transitionWithDuration:2 scene:s withColor:ccc3(255,0,0)]; // red color + */ ++(id) transitionWithDuration:(ccTime)duration scene:(CCScene*)scene withColor:(ccColor3B)color; +/** initializes the transition with a duration and with an RGB color */ +-(id) initWithDuration:(ccTime)duration scene:(CCScene*)scene withColor:(ccColor3B)color; +@end + + +/** + CCTransitionCrossFade: + Cross fades two scenes using the CCRenderTexture object. + */ +@class CCRenderTexture; +@interface CCTransitionCrossFade : CCTransitionScene +{} +// needed for BrdigeSupport +-(id) init; +@end + +/** CCTransitionTurnOffTiles: + Turn off the tiles of the outgoing scene in random order + */ +@interface CCTransitionTurnOffTiles : CCTransitionScene +{} +// needed for BrdigeSupport +-(id) init; +@end + +/** CCTransitionSplitCols: + The odd columns goes upwards while the even columns goes downwards. + */ +@interface CCTransitionSplitCols : CCTransitionScene +{} +-(CCActionInterval*) action; +@end + +/** CCTransitionSplitRows: + The odd rows goes to the left while the even rows goes to the right. + */ +@interface CCTransitionSplitRows : CCTransitionSplitCols +{} +// Needed for BridgeSupport +-(CCActionInterval*) action; +@end + +/** CCTransitionFadeTR: + Fade the tiles of the outgoing scene from the left-bottom corner the to top-right corner. + */ +@interface CCTransitionFadeTR : CCTransitionScene +{} +-(CCActionInterval*) actionWithSize:(CGSize) vector; +@end + +/** CCTransitionFadeBL: + Fade the tiles of the outgoing scene from the top-right corner to the bottom-left corner. + */ +@interface CCTransitionFadeBL : CCTransitionFadeTR +{} +-(CCActionInterval*) actionWithSize:(CGSize) vector; +@end + +/** CCTransitionFadeUp: + * Fade the tiles of the outgoing scene from the bottom to the top. + */ +@interface CCTransitionFadeUp : CCTransitionFadeTR +{} +-(CCActionInterval*) actionWithSize: (CGSize) v; +@end + +/** CCTransitionFadeDown: + * Fade the tiles of the outgoing scene from the top to the bottom. + */ +@interface CCTransitionFadeDown : CCTransitionFadeTR +{} +-(CCActionInterval*) actionWithSize: (CGSize) v; +@end diff --git "a/21451198\345\215\242\350\266\205/project5/MyPlane/libs/cocos2d/CCTransition.m" "b/21451198\345\215\242\350\266\205/project5/MyPlane/libs/cocos2d/CCTransition.m" new file mode 100644 index 00000000..bea0e279 --- /dev/null +++ "b/21451198\345\215\242\350\266\205/project5/MyPlane/libs/cocos2d/CCTransition.m" @@ -0,0 +1,1103 @@ +/* + * cocos2d for iPhone: http://www.cocos2d-iphone.org + * + * Copyright (c) 2008-2010 Ricardo Quesada + * Copyright (c) 2011 Zynga Inc. + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + * THE SOFTWARE. + * + */ + + + +#import "CCTransition.h" +#import "CCNode.h" +#import "CCSprite.h" +#import "CCDirector.h" +#import "CCActionInterval.h" +#import "CCActionInstant.h" +#import "CCActionCamera.h" +#import "CCLayer.h" +#import "CCCamera.h" +#import "CCActionTiledGrid.h" +#import "CCActionEase.h" +#import "CCRenderTexture.h" +#import "ccMacros.h" +#import "Support/CGPointExtension.h" + +#ifdef __CC_PLATFORM_IOS +#import "Platforms/iOS/CCTouchDispatcher.h" +#import "Platforms/iOS/CCDirectorIOS.h" +#elif defined(__CC_PLATFORM_MAC) +#import "Platforms/Mac/CCDirectorMac.h" +#import "Platforms/Mac/CCEventDispatcher.h" +#endif + +const NSInteger kSceneFade = 0xFADEFADE; + + +@interface CCTransitionScene (Private) +-(void) sceneOrder; +- (void)setNewScene:(ccTime)dt; +@end + +@implementation CCTransitionScene ++(id) transitionWithDuration:(ccTime) t scene:(CCScene*)s +{ + return [[[self alloc] initWithDuration:t scene:s] autorelease]; +} + +-(id) initWithDuration:(ccTime) t scene:(CCScene*)s +{ + NSAssert( s != nil, @"Argument scene must be non-nil"); + + if( (self=[super init]) ) { + + _duration = t; + + // retain + _inScene = [s retain]; + _outScene = [[CCDirector sharedDirector] runningScene]; + [_outScene retain]; + + NSAssert( _inScene != _outScene, @"Incoming scene must be different from the outgoing scene" ); + + [self sceneOrder]; + } + return self; +} +-(void) sceneOrder +{ + _inSceneOnTop = YES; +} + +-(void) draw +{ + [super draw]; + + if( _inSceneOnTop ) { + [_outScene visit]; + [_inScene visit]; + } else { + [_inScene visit]; + [_outScene visit]; + } +} + +-(void) finish +{ + /* clean up */ + [_inScene setVisible:YES]; + [_inScene setPosition:ccp(0,0)]; + [_inScene setScale:1.0f]; + [_inScene setRotation:0.0f]; + [_inScene.camera restore]; + + [_outScene setVisible:NO]; + [_outScene setPosition:ccp(0,0)]; + [_outScene setScale:1.0f]; + [_outScene setRotation:0.0f]; + [_outScene.camera restore]; + + [self schedule:@selector(setNewScene:) interval:0]; +} + +-(void) setNewScene: (ccTime) dt +{ + [self unschedule:_cmd]; + + CCDirector *director = [CCDirector sharedDirector]; + + // Before replacing, save the "send cleanup to scene" + _sendCleanupToScene = [director sendCleanupToScene]; + + [director replaceScene: _inScene]; + + // issue #267 + [_outScene setVisible:YES]; +} + +-(void) hideOutShowIn +{ + [_inScene setVisible:YES]; + [_outScene setVisible:NO]; +} + +// custom onEnter +-(void) onEnter +{ + [super onEnter]; + + // disable events while transitions + CCDirector *director = [CCDirector sharedDirector]; +#ifdef __CC_PLATFORM_IOS + [[director touchDispatcher] setDispatchEvents: NO]; +#elif defined(__CC_PLATFORM_MAC) + [[director eventDispatcher] setDispatchEvents: NO]; +#endif + + + // _outScene should not receive the onExit callback + // only the onExitTransitionDidStart + [_outScene onExitTransitionDidStart]; + + [_inScene onEnter]; +} + +// custom onExit +-(void) onExit +{ + [super onExit]; + + // enable events while transitions + CCDirector *director = [CCDirector sharedDirector]; +#ifdef __CC_PLATFORM_IOS + [[director touchDispatcher] setDispatchEvents: YES]; +#elif defined(__CC_PLATFORM_MAC) + [[director eventDispatcher] setDispatchEvents: YES]; +#endif + + + [_outScene onExit]; + + // _inScene should not receive the onEnter callback + // only the onEnterTransitionDidFinish + [_inScene onEnterTransitionDidFinish]; +} + +// custom cleanup +-(void) cleanup +{ + [super cleanup]; + + if( _sendCleanupToScene ) + [_outScene cleanup]; +} + +-(void) dealloc +{ + [_inScene release]; + [_outScene release]; + [super dealloc]; +} +@end + +// +// Oriented Transition +// +@implementation CCTransitionSceneOriented ++(id) transitionWithDuration:(ccTime) t scene:(CCScene*)s orientation:(tOrientation)o +{ + return [[[self alloc] initWithDuration:t scene:s orientation:o] autorelease]; +} + +-(id) initWithDuration:(ccTime) t scene:(CCScene*)s orientation:(tOrientation)o +{ + if( (self=[super initWithDuration:t scene:s]) ) + orientation = o; + return self; +} +@end + + +// +// RotoZoom +// +@implementation CCTransitionRotoZoom +-(id) init { + return [super init]; +} + +-(void) onEnter +{ + [super onEnter]; + + [_inScene setScale:0.001f]; + [_outScene setScale:1.0f]; + + [_inScene setAnchorPoint:ccp(0.5f, 0.5f)]; + [_outScene setAnchorPoint:ccp(0.5f, 0.5f)]; + + CCActionInterval *rotozoom = [CCSequence actions: [CCSpawn actions: + [CCScaleBy actionWithDuration:_duration/2 scale:0.001f], + [CCRotateBy actionWithDuration:_duration/2 angle:360 *2], + nil], + [CCDelayTime actionWithDuration:_duration/2], + nil]; + + + [_outScene runAction: rotozoom]; + [_inScene runAction: [CCSequence actions: + [rotozoom reverse], + [CCCallFunc actionWithTarget:self selector:@selector(finish)], + nil]]; +} +@end + +// +// JumpZoom +// +@implementation CCTransitionJumpZoom +-(id) init { + return [super init]; +} +-(void) onEnter +{ + [super onEnter]; + CGSize s = [[CCDirector sharedDirector] winSize]; + + [_inScene setScale:0.5f]; + [_inScene setPosition:ccp( s.width,0 )]; + + [_inScene setAnchorPoint:ccp(0.5f, 0.5f)]; + [_outScene setAnchorPoint:ccp(0.5f, 0.5f)]; + + CCActionInterval *jump = [CCJumpBy actionWithDuration:_duration/4 position:ccp(-s.width,0) height:s.width/4 jumps:2]; + CCActionInterval *scaleIn = [CCScaleTo actionWithDuration:_duration/4 scale:1.0f]; + CCActionInterval *scaleOut = [CCScaleTo actionWithDuration:_duration/4 scale:0.5f]; + + CCActionInterval *jumpZoomOut = [CCSequence actions: scaleOut, jump, nil]; + CCActionInterval *jumpZoomIn = [CCSequence actions: jump, scaleIn, nil]; + + CCActionInterval *delay = [CCDelayTime actionWithDuration:_duration/2]; + + [_outScene runAction: jumpZoomOut]; + [_inScene runAction: [CCSequence actions: delay, + jumpZoomIn, + [CCCallFunc actionWithTarget:self selector:@selector(finish)], + nil] ]; +} +@end + +// +// MoveInL +// +@implementation CCTransitionMoveInL +-(void) onEnter +{ + [super onEnter]; + + [self initScenes]; + + CCActionInterval *a = [self action]; + + [_inScene runAction: [CCSequence actions: + [self easeActionWithAction:a], + [CCCallFunc actionWithTarget:self selector:@selector(finish)], + nil] + ]; + +} +-(CCActionInterval*) action +{ + return [CCMoveTo actionWithDuration:_duration position:ccp(0,0)]; +} + +-(CCActionInterval*) easeActionWithAction:(CCActionInterval*)action +{ + return [CCEaseOut actionWithAction:action rate:2.0f]; +// return [EaseElasticOut actionWithAction:action period:0.4f]; +} + +-(void) initScenes +{ + CGSize s = [[CCDirector sharedDirector] winSize]; + [_inScene setPosition: ccp( -s.width,0) ]; +} +@end + +// +// MoveInR +// +@implementation CCTransitionMoveInR +-(void) initScenes +{ + CGSize s = [[CCDirector sharedDirector] winSize]; + [_inScene setPosition: ccp( s.width,0) ]; +} +@end + +// +// MoveInT +// +@implementation CCTransitionMoveInT +-(void) initScenes +{ + CGSize s = [[CCDirector sharedDirector] winSize]; + [_inScene setPosition: ccp( 0, s.height) ]; +} +@end + +// +// MoveInB +// +@implementation CCTransitionMoveInB +-(void) initScenes +{ + CGSize s = [[CCDirector sharedDirector] winSize]; + [_inScene setPosition: ccp( 0, -s.height) ]; +} +@end + +// +// SlideInL +// + +// The adjust factor is needed to prevent issue #442 +// One solution is to use DONT_RENDER_IN_SUBPIXELS images, but NO +// The other issue is that in some transitions (and I don't know why) +// the order should be reversed (In in top of Out or vice-versa). +#define ADJUST_FACTOR 0.5f +@implementation CCTransitionSlideInL +-(void) onEnter +{ + [super onEnter]; + + [self initScenes]; + + CCActionInterval *in = [self action]; + CCActionInterval *out = [self action]; + + id inAction = [self easeActionWithAction:in]; + id outAction = [CCSequence actions: + [self easeActionWithAction:out], + [CCCallFunc actionWithTarget:self selector:@selector(finish)], + nil]; + + [_inScene runAction: inAction]; + [_outScene runAction: outAction]; +} +-(void) sceneOrder +{ + _inSceneOnTop = NO; +} +-(void) initScenes +{ + CGSize s = [[CCDirector sharedDirector] winSize]; + [_inScene setPosition: ccp( -(s.width-ADJUST_FACTOR),0) ]; +} +-(CCActionInterval*) action +{ + CGSize s = [[CCDirector sharedDirector] winSize]; + return [CCMoveBy actionWithDuration:_duration position:ccp(s.width-ADJUST_FACTOR,0)]; +} + +-(CCActionInterval*) easeActionWithAction:(CCActionInterval*)action +{ + return [CCEaseOut actionWithAction:action rate:2.0f]; +// return [EaseElasticOut actionWithAction:action period:0.4f]; +} + +@end + +// +// SlideInR +// +@implementation CCTransitionSlideInR +-(void) sceneOrder +{ + _inSceneOnTop = YES; +} +-(void) initScenes +{ + CGSize s = [[CCDirector sharedDirector] winSize]; + [_inScene setPosition: ccp( s.width-ADJUST_FACTOR,0) ]; +} + +-(CCActionInterval*) action +{ + CGSize s = [[CCDirector sharedDirector] winSize]; + return [CCMoveBy actionWithDuration:_duration position:ccp(-(s.width-ADJUST_FACTOR),0)]; +} + +@end + +// +// SlideInT +// +@implementation CCTransitionSlideInT +-(void) sceneOrder +{ + _inSceneOnTop = NO; +} +-(void) initScenes +{ + CGSize s = [[CCDirector sharedDirector] winSize]; + [_inScene setPosition: ccp(0,s.height-ADJUST_FACTOR) ]; +} + +-(CCActionInterval*) action +{ + CGSize s = [[CCDirector sharedDirector] winSize]; + return [CCMoveBy actionWithDuration:_duration position:ccp(0,-(s.height-ADJUST_FACTOR))]; +} + +@end + +// +// SlideInB +// +@implementation CCTransitionSlideInB +-(void) sceneOrder +{ + _inSceneOnTop = YES; +} + +-(void) initScenes +{ + CGSize s = [[CCDirector sharedDirector] winSize]; + [_inScene setPosition: ccp(0,-(s.height-ADJUST_FACTOR)) ]; +} + +-(CCActionInterval*) action +{ + CGSize s = [[CCDirector sharedDirector] winSize]; + return [CCMoveBy actionWithDuration:_duration position:ccp(0,s.height-ADJUST_FACTOR)]; +} +@end + +// +// ShrinkGrow Transition +// +@implementation CCTransitionShrinkGrow +-(id) init { + return [super init]; +} +-(void) onEnter +{ + [super onEnter]; + + [_inScene setScale:0.001f]; + [_outScene setScale:1.0f]; + + [_inScene setAnchorPoint:ccp(2/3.0f,0.5f)]; + [_outScene setAnchorPoint:ccp(1/3.0f,0.5f)]; + + CCActionInterval *scaleOut = [CCScaleTo actionWithDuration:_duration scale:0.01f]; + CCActionInterval *scaleIn = [CCScaleTo actionWithDuration:_duration scale:1.0f]; + + [_inScene runAction: [self easeActionWithAction:scaleIn]]; + [_outScene runAction: [CCSequence actions: + [self easeActionWithAction:scaleOut], + [CCCallFunc actionWithTarget:self selector:@selector(finish)], + nil] ]; +} +-(CCActionInterval*) easeActionWithAction:(CCActionInterval*)action +{ + return [CCEaseOut actionWithAction:action rate:2.0f]; +// return [EaseElasticOut actionWithAction:action period:0.3f]; +} +@end + +// +// FlipX Transition +// +@implementation CCTransitionFlipX +-(id) init { + return [super init]; +} +-(void) onEnter +{ + [super onEnter]; + + CCActionInterval *inA, *outA; + [_inScene setVisible: NO]; + + float inDeltaZ, inAngleZ; + float outDeltaZ, outAngleZ; + + if( orientation == kCCTransitionOrientationRightOver ) { + inDeltaZ = 90; + inAngleZ = 270; + outDeltaZ = 90; + outAngleZ = 0; + } else { + inDeltaZ = -90; + inAngleZ = 90; + outDeltaZ = -90; + outAngleZ = 0; + } + + inA = [CCSequence actions: + [CCDelayTime actionWithDuration:_duration/2], + [CCShow action], + [CCOrbitCamera actionWithDuration: _duration/2 radius: 1 deltaRadius:0 angleZ:inAngleZ deltaAngleZ:inDeltaZ angleX:0 deltaAngleX:0], + [CCCallFunc actionWithTarget:self selector:@selector(finish)], + nil ]; + outA = [CCSequence actions: + [CCOrbitCamera actionWithDuration: _duration/2 radius: 1 deltaRadius:0 angleZ:outAngleZ deltaAngleZ:outDeltaZ angleX:0 deltaAngleX:0], + [CCHide action], + [CCDelayTime actionWithDuration:_duration/2], + nil ]; + + [_inScene runAction: inA]; + [_outScene runAction: outA]; + +} +@end + +// +// FlipY Transition +// +@implementation CCTransitionFlipY +-(id) init { + return [super init]; +} +-(void) onEnter +{ + [super onEnter]; + + CCActionInterval *inA, *outA; + [_inScene setVisible: NO]; + + float inDeltaZ, inAngleZ; + float outDeltaZ, outAngleZ; + + if( orientation == kCCTransitionOrientationUpOver ) { + inDeltaZ = 90; + inAngleZ = 270; + outDeltaZ = 90; + outAngleZ = 0; + } else { + inDeltaZ = -90; + inAngleZ = 90; + outDeltaZ = -90; + outAngleZ = 0; + } + inA = [CCSequence actions: + [CCDelayTime actionWithDuration:_duration/2], + [CCShow action], + [CCOrbitCamera actionWithDuration: _duration/2 radius: 1 deltaRadius:0 angleZ:inAngleZ deltaAngleZ:inDeltaZ angleX:90 deltaAngleX:0], + [CCCallFunc actionWithTarget:self selector:@selector(finish)], + nil ]; + outA = [CCSequence actions: + [CCOrbitCamera actionWithDuration: _duration/2 radius: 1 deltaRadius:0 angleZ:outAngleZ deltaAngleZ:outDeltaZ angleX:90 deltaAngleX:0], + [CCHide action], + [CCDelayTime actionWithDuration:_duration/2], + nil ]; + + [_inScene runAction: inA]; + [_outScene runAction: outA]; + +} +@end + +// +// FlipAngular Transition +// +@implementation CCTransitionFlipAngular +-(id) init { + return [super init]; +} +-(void) onEnter +{ + [super onEnter]; + + CCActionInterval *inA, *outA; + [_inScene setVisible: NO]; + + float inDeltaZ, inAngleZ; + float outDeltaZ, outAngleZ; + + if( orientation == kCCTransitionOrientationRightOver ) { + inDeltaZ = 90; + inAngleZ = 270; + outDeltaZ = 90; + outAngleZ = 0; + } else { + inDeltaZ = -90; + inAngleZ = 90; + outDeltaZ = -90; + outAngleZ = 0; + } + inA = [CCSequence actions: + [CCDelayTime actionWithDuration:_duration/2], + [CCShow action], + [CCOrbitCamera actionWithDuration: _duration/2 radius: 1 deltaRadius:0 angleZ:inAngleZ deltaAngleZ:inDeltaZ angleX:-45 deltaAngleX:0], + [CCCallFunc actionWithTarget:self selector:@selector(finish)], + nil ]; + outA = [CCSequence actions: + [CCOrbitCamera actionWithDuration: _duration/2 radius: 1 deltaRadius:0 angleZ:outAngleZ deltaAngleZ:outDeltaZ angleX:45 deltaAngleX:0], + [CCHide action], + [CCDelayTime actionWithDuration:_duration/2], + nil ]; + + [_inScene runAction: inA]; + [_outScene runAction: outA]; +} +@end + +// +// ZoomFlipX Transition +// +@implementation CCTransitionZoomFlipX +-(id) init { + return [super init]; +} +-(void) onEnter +{ + [super onEnter]; + + CCActionInterval *inA, *outA; + [_inScene setVisible: NO]; + + float inDeltaZ, inAngleZ; + float outDeltaZ, outAngleZ; + + if( orientation == kCCTransitionOrientationRightOver ) { + inDeltaZ = 90; + inAngleZ = 270; + outDeltaZ = 90; + outAngleZ = 0; + } else { + inDeltaZ = -90; + inAngleZ = 90; + outDeltaZ = -90; + outAngleZ = 0; + } + inA = [CCSequence actions: + [CCDelayTime actionWithDuration:_duration/2], + [CCSpawn actions: + [CCOrbitCamera actionWithDuration: _duration/2 radius: 1 deltaRadius:0 angleZ:inAngleZ deltaAngleZ:inDeltaZ angleX:0 deltaAngleX:0], + [CCScaleTo actionWithDuration:_duration/2 scale:1], + [CCShow action], + nil], + [CCCallFunc actionWithTarget:self selector:@selector(finish)], + nil ]; + outA = [CCSequence actions: + [CCSpawn actions: + [CCOrbitCamera actionWithDuration: _duration/2 radius: 1 deltaRadius:0 angleZ:outAngleZ deltaAngleZ:outDeltaZ angleX:0 deltaAngleX:0], + [CCScaleTo actionWithDuration:_duration/2 scale:0.5f], + nil], + [CCHide action], + [CCDelayTime actionWithDuration:_duration/2], + nil ]; + + _inScene.scale = 0.5f; + [_inScene runAction: inA]; + [_outScene runAction: outA]; +} +@end + +// +// ZoomFlipY Transition +// +@implementation CCTransitionZoomFlipY +-(id) init { + return [super init]; +} +-(void) onEnter +{ + [super onEnter]; + + CCActionInterval *inA, *outA; + [_inScene setVisible: NO]; + + float inDeltaZ, inAngleZ; + float outDeltaZ, outAngleZ; + + if( orientation == kCCTransitionOrientationUpOver ) { + inDeltaZ = 90; + inAngleZ = 270; + outDeltaZ = 90; + outAngleZ = 0; + } else { + inDeltaZ = -90; + inAngleZ = 90; + outDeltaZ = -90; + outAngleZ = 0; + } + + inA = [CCSequence actions: + [CCDelayTime actionWithDuration:_duration/2], + [CCSpawn actions: + [CCOrbitCamera actionWithDuration: _duration/2 radius: 1 deltaRadius:0 angleZ:inAngleZ deltaAngleZ:inDeltaZ angleX:90 deltaAngleX:0], + [CCScaleTo actionWithDuration:_duration/2 scale:1], + [CCShow action], + nil], + [CCCallFunc actionWithTarget:self selector:@selector(finish)], + nil ]; + outA = [CCSequence actions: + [CCSpawn actions: + [CCOrbitCamera actionWithDuration: _duration/2 radius: 1 deltaRadius:0 angleZ:outAngleZ deltaAngleZ:outDeltaZ angleX:90 deltaAngleX:0], + [CCScaleTo actionWithDuration:_duration/2 scale:0.5f], + nil], + [CCHide action], + [CCDelayTime actionWithDuration:_duration/2], + nil ]; + + _inScene.scale = 0.5f; + [_inScene runAction: inA]; + [_outScene runAction: outA]; +} +@end + +// +// ZoomFlipAngular Transition +// +@implementation CCTransitionZoomFlipAngular +-(id) init { + return [super init]; +} +-(void) onEnter +{ + [super onEnter]; + + CCActionInterval *inA, *outA; + [_inScene setVisible: NO]; + + float inDeltaZ, inAngleZ; + float outDeltaZ, outAngleZ; + + if( orientation == kCCTransitionOrientationUpOver ) { + inDeltaZ = 90; + inAngleZ = 270; + outDeltaZ = 90; + outAngleZ = 0; + } else { + inDeltaZ = -90; + inAngleZ = 90; + outDeltaZ = -90; + outAngleZ = 0; + } + + inA = [CCSequence actions: + [CCDelayTime actionWithDuration:_duration/2], + [CCSpawn actions: + [CCOrbitCamera actionWithDuration: _duration/2 radius: 1 deltaRadius:0 angleZ:inAngleZ deltaAngleZ:inDeltaZ angleX:-45 deltaAngleX:0], + [CCScaleTo actionWithDuration:_duration/2 scale:1], + [CCShow action], + nil], + [CCShow action], + [CCCallFunc actionWithTarget:self selector:@selector(finish)], + nil ]; + outA = [CCSequence actions: + [CCSpawn actions: + [CCOrbitCamera actionWithDuration: _duration/2 radius: 1 deltaRadius:0 angleZ:outAngleZ deltaAngleZ:outDeltaZ angleX:45 deltaAngleX:0], + [CCScaleTo actionWithDuration:_duration/2 scale:0.5f], + nil], + [CCHide action], + [CCDelayTime actionWithDuration:_duration/2], + nil ]; + + _inScene.scale = 0.5f; + [_inScene runAction: inA]; + [_outScene runAction: outA]; +} +@end + + +// +// Fade Transition +// +@implementation CCTransitionFade ++(id) transitionWithDuration:(ccTime)d scene:(CCScene*)s withColor:(ccColor3B)color +{ + return [[[self alloc] initWithDuration:d scene:s withColor:color] autorelease]; +} + +-(id) initWithDuration:(ccTime)d scene:(CCScene*)s withColor:(ccColor3B)aColor +{ + if( (self=[super initWithDuration:d scene:s]) ) { + color.r = aColor.r; + color.g = aColor.g; + color.b = aColor.b; + } + + return self; +} + +-(id) initWithDuration:(ccTime)d scene:(CCScene*)s +{ + return [self initWithDuration:d scene:s withColor:ccBLACK]; +} + +-(void) onEnter +{ + [super onEnter]; + + CCLayerColor *l = [CCLayerColor layerWithColor:color]; + [_inScene setVisible: NO]; + + [self addChild: l z:2 tag:kSceneFade]; + + + CCNode *f = [self getChildByTag:kSceneFade]; + + CCActionInterval *a = [CCSequence actions: + [CCFadeIn actionWithDuration:_duration/2], + [CCCallFunc actionWithTarget:self selector:@selector(hideOutShowIn)], + [CCFadeOut actionWithDuration:_duration/2], + [CCCallFunc actionWithTarget:self selector:@selector(finish)], + nil ]; + [f runAction: a]; +} + +-(void) onExit +{ + [super onExit]; + [self removeChildByTag:kSceneFade cleanup:YES]; +} +@end + + +// +// Cross Fade Transition +// +@implementation CCTransitionCrossFade +-(id) init { + return [super init]; +} +-(void) draw +{ + // override draw since both scenes (textures) are rendered in 1 scene +} + +-(void) onEnter +{ + [super onEnter]; + + // create a transparent color layer + // in which we are going to add our rendertextures + ccColor4B color = {0,0,0,0}; + CGSize size = [[CCDirector sharedDirector] winSize]; + CCLayerColor * layer = [CCLayerColor layerWithColor:color]; + + // create the first render texture for _inScene + CCRenderTexture *inTexture = [CCRenderTexture renderTextureWithWidth:size.width height:size.height]; + inTexture.sprite.anchorPoint= ccp(0.5f,0.5f); + inTexture.position = ccp(size.width/2, size.height/2); + inTexture.anchorPoint = ccp(0.5f,0.5f); + + // render _inScene to its texturebuffer + [inTexture begin]; + [_inScene visit]; + [inTexture end]; + + // create the second render texture for _outScene + CCRenderTexture *outTexture = [CCRenderTexture renderTextureWithWidth:size.width height:size.height]; + outTexture.sprite.anchorPoint= ccp(0.5f,0.5f); + outTexture.position = ccp(size.width/2, size.height/2); + outTexture.anchorPoint = ccp(0.5f,0.5f); + + // render _outScene to its texturebuffer + [outTexture begin]; + [_outScene visit]; + [outTexture end]; + + // create blend functions + + ccBlendFunc blend1 = {GL_ONE, GL_ONE}; // _inScene will lay on background and will not be used with alpha + ccBlendFunc blend2 = {GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA}; // we are going to blend _outScene via alpha + + // set blendfunctions + [inTexture.sprite setBlendFunc:blend1]; + [outTexture.sprite setBlendFunc:blend2]; + + // add render textures to the layer + [layer addChild:inTexture]; + [layer addChild:outTexture]; + + // initial opacity: + [inTexture.sprite setOpacity:255]; + [outTexture.sprite setOpacity:255]; + + // create the blend action + CCActionInterval * layerAction = [CCSequence actions: + [CCFadeTo actionWithDuration:_duration opacity:0], + [CCCallFunc actionWithTarget:self selector:@selector(hideOutShowIn)], + [CCCallFunc actionWithTarget:self selector:@selector(finish)], + nil ]; + + + // run the blend action + [outTexture.sprite runAction: layerAction]; + + // add the layer (which contains our two rendertextures) to the scene + [self addChild: layer z:2 tag:kSceneFade]; +} + +// clean up on exit +-(void) onExit +{ + // remove our layer and release all containing objects + [self removeChildByTag:kSceneFade cleanup:YES]; + + [super onExit]; +} +@end + +// +// TurnOffTilesTransition +// +@implementation CCTransitionTurnOffTiles +-(id) init { + return [super init]; +} +// override addScenes, and change the order +-(void) sceneOrder +{ + _inSceneOnTop = NO; +} + +-(void) onEnter +{ + [super onEnter]; + CGSize s = [[CCDirector sharedDirector] winSize]; + float aspect = s.width / s.height; + int x = 12 * aspect; + int y = 12; + + id toff = [CCTurnOffTiles actionWithDuration:_duration size:CGSizeMake(x,y)]; + id action = [self easeActionWithAction:toff]; + [_outScene runAction: [CCSequence actions: action, + [CCCallFunc actionWithTarget:self selector:@selector(finish)], + [CCStopGrid action], + nil] + ]; + +} +-(CCActionInterval*) easeActionWithAction:(CCActionInterval*)action +{ + return action; +// return [EaseIn actionWithAction:action rate:2.0f]; +} +@end + +#pragma mark Split Transitions + +// +// SplitCols Transition +// +@implementation CCTransitionSplitCols + +-(void) onEnter +{ + [super onEnter]; + + _inScene.visible = NO; + + id split = [self action]; + id seq = [CCSequence actions: + split, + [CCCallFunc actionWithTarget:self selector:@selector(hideOutShowIn)], + [split reverse], + nil + ]; + [self runAction: [CCSequence actions: + [self easeActionWithAction:seq], + [CCCallFunc actionWithTarget:self selector:@selector(finish)], + [CCStopGrid action], + nil] + ]; +} + +-(CCActionInterval*) action +{ + return [CCSplitCols actionWithDuration:_duration/2.0f cols:3]; +} + +-(CCActionInterval*) easeActionWithAction:(CCActionInterval*)action +{ + return [CCEaseInOut actionWithAction:action rate:3.0f]; +} +@end + +// +// SplitRows Transition +// +@implementation CCTransitionSplitRows +-(CCActionInterval*) action +{ + return [CCSplitRows actionWithDuration:_duration/2.0f rows:3]; +} +@end + + +#pragma mark Fade Grid Transitions + +// +// FadeTR Transition +// +@implementation CCTransitionFadeTR +-(void) sceneOrder +{ + _inSceneOnTop = NO; +} + +-(void) onEnter +{ + [super onEnter]; + + CGSize s = [[CCDirector sharedDirector] winSize]; + float aspect = s.width / s.height; + int x = 12 * aspect; + int y = 12; + + id action = [self actionWithSize:CGSizeMake(x,y)]; + + [_outScene runAction: [CCSequence actions: + [self easeActionWithAction:action], + [CCCallFunc actionWithTarget:self selector:@selector(finish)], + [CCStopGrid action], + nil] + ]; +} + +-(CCActionInterval*) actionWithSize: (CGSize) v +{ + return [CCFadeOutTRTiles actionWithDuration:_duration size:v]; +} + +-(CCActionInterval*) easeActionWithAction:(CCActionInterval*)action +{ + return action; +// return [CCEaseOut actionWithAction:action rate:3.0f]; +} +@end + +// +// FadeBL Transition +// +@implementation CCTransitionFadeBL +-(CCActionInterval*) actionWithSize: (CGSize) v +{ + return [CCFadeOutBLTiles actionWithDuration:_duration size:v]; +} +@end + +// +// FadeUp Transition +// +@implementation CCTransitionFadeUp +-(CCActionInterval*) actionWithSize: (CGSize) v +{ + return [CCFadeOutUpTiles actionWithDuration:_duration size:v]; +} +@end + +// +// FadeDown Transition +// +@implementation CCTransitionFadeDown +-(CCActionInterval*) actionWithSize: (CGSize) v +{ + return [CCFadeOutDownTiles actionWithDuration:_duration size:v]; +} +@end diff --git "a/21451198\345\215\242\350\266\205/project5/MyPlane/libs/cocos2d/CCTransitionPageTurn.h" "b/21451198\345\215\242\350\266\205/project5/MyPlane/libs/cocos2d/CCTransitionPageTurn.h" new file mode 100644 index 00000000..a6e24ed8 --- /dev/null +++ "b/21451198\345\215\242\350\266\205/project5/MyPlane/libs/cocos2d/CCTransitionPageTurn.h" @@ -0,0 +1,60 @@ +/* + * cocos2d for iPhone: http://www.cocos2d-iphone.org + * + * Copyright (c) 2009 Sindesso Pty Ltd http://www.sindesso.com/ + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + * THE SOFTWARE. + * + */ + + +#import "CCTransition.h" + +/** CCTransitionPageTurn transition. + * A transition which peels back the bottom right hand corner of a scene + * to transition to the scene beneath it simulating a page turn + * + * This uses a 3DAction so it is strongly recommended that depth buffering + * is turned on in CCDirector using: + * + * [[CCDirector sharedDirector] setDepthBufferFormat:kCCDepthBuffer16]; + * + * @since v0.8.2 + */ +@interface CCTransitionPageTurn : CCTransitionScene +{ + BOOL _back; +} +/** + * creates a base transition with duration and incoming scene + * if back is TRUE then the effect is reversed to appear as if the incoming + * scene is being turned from left over the outgoing scene + */ ++(id) transitionWithDuration:(ccTime) t scene:(CCScene*)s backwards:(BOOL) back; + +/** + * creates a base transition with duration and incoming scene + * if back is TRUE then the effect is reversed to appear as if the incoming + * scene is being turned from left over the outgoing scene + */ +-(id) initWithDuration:(ccTime) t scene:(CCScene*)s backwards:(BOOL) back; + +-(CCActionInterval*) actionWithSize:(CGSize) vector; + +@end diff --git "a/21451198\345\215\242\350\266\205/project5/MyPlane/libs/cocos2d/CCTransitionPageTurn.m" "b/21451198\345\215\242\350\266\205/project5/MyPlane/libs/cocos2d/CCTransitionPageTurn.m" new file mode 100644 index 00000000..c4f42f40 --- /dev/null +++ "b/21451198\345\215\242\350\266\205/project5/MyPlane/libs/cocos2d/CCTransitionPageTurn.m" @@ -0,0 +1,117 @@ +/* + * cocos2d for iPhone: http://www.cocos2d-iphone.org + * + * Copyright (c) 2009 Sindesso Pty Ltd http://www.sindesso.com/ + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + * THE SOFTWARE. + * + */ + + +#import "CCTransitionPageTurn.h" +#import "CCActionPageTurn3D.h" +#import "CCDirector.h" + +@implementation CCTransitionPageTurn + +/** creates a base transition with duration and incoming scene */ ++(id) transitionWithDuration:(ccTime) t scene:(CCScene*)s backwards:(BOOL) back +{ + return [[[self alloc] initWithDuration:t scene:s backwards:back] autorelease]; +} + +/** initializes a transition with duration and incoming scene */ +-(id) initWithDuration:(ccTime) t scene:(CCScene*)s backwards:(BOOL) back +{ + // XXX: needed before [super init] + _back = back; + + if( ( self = [super initWithDuration:t scene:s] ) ) + { + // do something + } + return self; +} + +-(void) sceneOrder +{ + _inSceneOnTop = _back; +} + +// +-(void) onEnter +{ + [super onEnter]; + + CGSize s = [[CCDirector sharedDirector] winSize]; + int x, y; + if( s.width > s.height) + { + x = 16; + y = 12; + } + else + { + x = 12; + y = 16; + } + + id action = [self actionWithSize:CGSizeMake(x,y)]; + + if(! _back ) + { + [_outScene runAction: [CCSequence actions: + action, + [CCCallFunc actionWithTarget:self selector:@selector(finish)], + [CCStopGrid action], + nil] + ]; + } + else + { + // to prevent initial flicker + _inScene.visible = NO; + [_inScene runAction: [CCSequence actions: + [CCShow action], + action, + [CCCallFunc actionWithTarget:self selector:@selector(finish)], + [CCStopGrid action], + nil] + ]; + } + +} + +-(CCActionInterval*) actionWithSize: (CGSize) v +{ + if( _back ) + { + // Get hold of the PageTurn3DAction + return [CCReverseTime actionWithAction: + [CCPageTurn3D actionWithDuration:_duration size:v]]; + } + else + { + // Get hold of the PageTurn3DAction + return [CCPageTurn3D actionWithDuration:_duration size:v]; + } +} + +@end + diff --git "a/21451198\345\215\242\350\266\205/project5/MyPlane/libs/cocos2d/CCTransitionProgress.h" "b/21451198\345\215\242\350\266\205/project5/MyPlane/libs/cocos2d/CCTransitionProgress.h" new file mode 100644 index 00000000..3597c627 --- /dev/null +++ "b/21451198\345\215\242\350\266\205/project5/MyPlane/libs/cocos2d/CCTransitionProgress.h" @@ -0,0 +1,84 @@ +/* + * cocos2d for iPhone: http://www.cocos2d-iphone.org + * + * Copyright (c) 2009 Lam Pham + * + * Copyright (c) 2012 Ricardo Quesada + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + * THE SOFTWARE. + * + */ + +#import "CCTransition.h" + +@class CCProgressTimer; + +@interface CCTransitionProgress : CCTransitionScene +{ + float _to, _from; + CCScene *_sceneToBeModified; +} +// Needed for BridgeSupport +-(CCProgressTimer*) progressTimerNodeWithRenderTexture:(CCRenderTexture*)texture; +@end + +/** CCTransitionRadialCCW transition. + A counter clock-wise radial transition to the next scene + */ +@interface CCTransitionProgressRadialCCW : CCTransitionProgress +{} +// Needed for BridgeSupport +-(CCProgressTimer*) progressTimerNodeWithRenderTexture:(CCRenderTexture*)texture; +@end + +/** CCTransitionRadialCW transition. + A counter clock-wise radial transition to the next scene +*/ +@interface CCTransitionProgressRadialCW : CCTransitionProgress +{} +// Needed for BridgeSupport +-(CCProgressTimer*) progressTimerNodeWithRenderTexture:(CCRenderTexture*)texture; +@end + +/** CCTransitionProgressHorizontal transition. + A clock-wise radial transition to the next scene + */ +@interface CCTransitionProgressHorizontal : CCTransitionProgress +{} +// Needed for BridgeSupport +-(CCProgressTimer*) progressTimerNodeWithRenderTexture:(CCRenderTexture*)texture; +@end + +@interface CCTransitionProgressVertical : CCTransitionProgress +{} +// Needed for BridgeSupport +-(CCProgressTimer*) progressTimerNodeWithRenderTexture:(CCRenderTexture*)texture; +@end + +@interface CCTransitionProgressInOut : CCTransitionProgress +{} +// Needed for BridgeSupport +-(CCProgressTimer*) progressTimerNodeWithRenderTexture:(CCRenderTexture*)texture; +@end + +@interface CCTransitionProgressOutIn : CCTransitionProgress +{} +// Needed for BridgeSupport +-(CCProgressTimer*) progressTimerNodeWithRenderTexture:(CCRenderTexture*)texture; +@end diff --git "a/21451198\345\215\242\350\266\205/project5/MyPlane/libs/cocos2d/CCTransitionProgress.m" "b/21451198\345\215\242\350\266\205/project5/MyPlane/libs/cocos2d/CCTransitionProgress.m" new file mode 100644 index 00000000..3fd7abad --- /dev/null +++ "b/21451198\345\215\242\350\266\205/project5/MyPlane/libs/cocos2d/CCTransitionProgress.m" @@ -0,0 +1,276 @@ +/* + * cocos2d for iPhone: http://www.cocos2d-iphone.org + * + * Copyright (c) 2009 Lam Pham + * + * Copyright (c) 2012 Ricardo Quesada + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + * THE SOFTWARE. + * + */ + + +#import "CCTransitionProgress.h" +#import "CCDirector.h" +#import "CCRenderTexture.h" +#import "CCLayer.h" +#import "CCActionInstant.h" +#import "CCProgressTimer.h" +#import "CCActionProgressTimer.h" +#import "Support/CGPointExtension.h" + +enum { + kCCSceneRadial = 0xc001, +}; + +#pragma mark - CCTransitionProgress + +@interface CCTransitionProgress() +-(CCProgressTimer*) progressTimerNodeWithRenderTexture:(CCRenderTexture*)texture; +-(void) setupTransition; +@end + +@implementation CCTransitionProgress +-(void) onEnter +{ + [super onEnter]; + + [self setupTransition]; + + // create a transparent color layer + // in which we are going to add our rendertextures + CGSize size = [[CCDirector sharedDirector] winSize]; + + // create the second render texture for outScene + CCRenderTexture *texture = [CCRenderTexture renderTextureWithWidth:size.width height:size.height]; + texture.sprite.anchorPoint= ccp(0.5f,0.5f); + texture.position = ccp(size.width/2, size.height/2); + texture.anchorPoint = ccp(0.5f,0.5f); + + // render outScene to its texturebuffer + [texture clear:0 g:0 b:0 a:1]; + [texture begin]; + [_sceneToBeModified visit]; + [texture end]; + + + // Since we've passed the outScene to the texture we don't need it. + if( _sceneToBeModified == _outScene ) + [self hideOutShowIn]; + + // We need the texture in RenderTexture. + CCProgressTimer *node = [self progressTimerNodeWithRenderTexture:texture]; + + // create the blend action + CCActionInterval * layerAction = [CCSequence actions: + [CCProgressFromTo actionWithDuration:_duration from:_from to:_to], + [CCCallFunc actionWithTarget:self selector:@selector(finish)], + nil ]; + // run the blend action + [node runAction: layerAction]; + + // add the layer (which contains our two rendertextures) to the scene + [self addChild: node z:2 tag:kCCSceneRadial]; +} + +// clean up on exit +-(void) onExit +{ + // remove our layer and release all containing objects + [self removeChildByTag:kCCSceneRadial cleanup:YES]; + [super onExit]; +} + +-(void) sceneOrder +{ + _inSceneOnTop = NO; +} + +-(void) setupTransition +{ + _sceneToBeModified = _outScene; + _from = 100; + _to = 0; +} + +-(CCProgressTimer*) progressTimerNodeWithRenderTexture:(CCRenderTexture*)texture +{ + NSAssert(NO, @"override me - abstract class"); + + return nil; +} +@end + +#pragma mark - CCTransitionProgressRadialCCW + +@implementation CCTransitionProgressRadialCCW +-(CCProgressTimer*) progressTimerNodeWithRenderTexture:(CCRenderTexture*)texture +{ + CGSize size = [[CCDirector sharedDirector] winSize]; + + CCProgressTimer *node = [CCProgressTimer progressWithSprite:texture.sprite]; + + // but it is flipped upside down so we flip the sprite + node.sprite.flipY = YES; + node.type = kCCProgressTimerTypeRadial; + + // Return the radial type that we want to use + node.reverseDirection = NO; + node.percentage = 100; + node.position = ccp(size.width/2, size.height/2); + node.anchorPoint = ccp(0.5f,0.5f); + + return node; +} +@end + +#pragma mark - CCTransitionProgressRadialCW + +@implementation CCTransitionProgressRadialCW +-(CCProgressTimer*) progressTimerNodeWithRenderTexture:(CCRenderTexture*)texture +{ + CGSize size = [[CCDirector sharedDirector] winSize]; + + CCProgressTimer *node = [CCProgressTimer progressWithSprite:texture.sprite]; + + // but it is flipped upside down so we flip the sprite + node.sprite.flipY = YES; + node.type = kCCProgressTimerTypeRadial; + + // Return the radial type that we want to use + node.reverseDirection = YES; + node.percentage = 100; + node.position = ccp(size.width/2, size.height/2); + node.anchorPoint = ccp(0.5f,0.5f); + + return node; +} +@end + +#pragma mark - CCTransitionProgressHorizontal + +@implementation CCTransitionProgressHorizontal +-(CCProgressTimer*) progressTimerNodeWithRenderTexture:(CCRenderTexture*)texture +{ + CGSize size = [[CCDirector sharedDirector] winSize]; + + CCProgressTimer *node = [CCProgressTimer progressWithSprite:texture.sprite]; + + // but it is flipped upside down so we flip the sprite + node.sprite.flipY = YES; + node.type = kCCProgressTimerTypeBar; + + node.midpoint = ccp(1, 0); + node.barChangeRate = ccp(1,0); + + node.percentage = 100; + node.position = ccp(size.width/2, size.height/2); + node.anchorPoint = ccp(0.5f,0.5f); + + return node; +} +@end + +#pragma mark - CCTransitionProgressVertical + +@implementation CCTransitionProgressVertical +-(CCProgressTimer*) progressTimerNodeWithRenderTexture:(CCRenderTexture*)texture +{ + CGSize size = [[CCDirector sharedDirector] winSize]; + + CCProgressTimer *node = [CCProgressTimer progressWithSprite:texture.sprite]; + + // but it is flipped upside down so we flip the sprite + node.sprite.flipY = YES; + node.type = kCCProgressTimerTypeBar; + + node.midpoint = ccp(0, 0); + node.barChangeRate = ccp(0,1); + + node.percentage = 100; + node.position = ccp(size.width/2, size.height/2); + node.anchorPoint = ccp(0.5f,0.5f); + + return node; +} +@end + +#pragma mark - CCTransitionProgressInOut + +@implementation CCTransitionProgressInOut + +-(void) sceneOrder +{ + _inSceneOnTop = NO; +} + +-(void) setupTransition +{ + _sceneToBeModified = _inScene; + _from = 0; + _to = 100; +} + +-(CCProgressTimer*) progressTimerNodeWithRenderTexture:(CCRenderTexture*)texture +{ + CGSize size = [[CCDirector sharedDirector] winSize]; + + CCProgressTimer *node = [CCProgressTimer progressWithSprite:texture.sprite]; + + // but it is flipped upside down so we flip the sprite + node.sprite.flipY = YES; + node.type = kCCProgressTimerTypeBar; + + node.midpoint = ccp(.5f, .5f); + node.barChangeRate = ccp(1, 1); + + node.percentage = 0; + node.position = ccp(size.width/2, size.height/2); + node.anchorPoint = ccp(0.5f,0.5f); + + return node; +} +@end + +#pragma mark - CCTransitionProgressOutIn + +@implementation CCTransitionProgressOutIn +-(CCProgressTimer*) progressTimerNodeWithRenderTexture:(CCRenderTexture*)texture +{ + CGSize size = [[CCDirector sharedDirector] winSize]; + + CCProgressTimer *node = [CCProgressTimer progressWithSprite:texture.sprite]; + + // but it is flipped upside down so we flip the sprite + node.sprite.flipY = YES; + node.type = kCCProgressTimerTypeBar; + + node.midpoint = ccp(.5f, .5f); + node.barChangeRate = ccp(1, 1); + + node.percentage = 100; + node.position = ccp(size.width/2, size.height/2); + node.anchorPoint = ccp(0.5f,0.5f); + + return node; +} +@end + + + diff --git "a/21451198\345\215\242\350\266\205/project5/MyPlane/libs/cocos2d/Platforms/CCGL.h" "b/21451198\345\215\242\350\266\205/project5/MyPlane/libs/cocos2d/Platforms/CCGL.h" new file mode 100644 index 00000000..469c2b09 --- /dev/null +++ "b/21451198\345\215\242\350\266\205/project5/MyPlane/libs/cocos2d/Platforms/CCGL.h" @@ -0,0 +1,74 @@ +/* + * cocos2d for iPhone: http://www.cocos2d-iphone.org + * + * Copyright (c) 2010 Ricardo Quesada + * Copyright (c) 2011 Zynga Inc. + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + * THE SOFTWARE. + */ + +// +// Common layer for OpenGL stuff +// + +#import "../ccMacros.h" + +#if __CC_PLATFORM_IOS +#import +#import +#import +#import "iOS/CCGLView.h" + +#elif __CC_PLATFORM_MAC +#import +#import +#import // needed for NSOpenGLView +#import "Mac/CCGLView.h" +#endif + + +// iOS +#if __CC_PLATFORM_IOS +#define glClearDepth glClearDepthf +#define glDeleteVertexArrays glDeleteVertexArraysOES +#define glGenVertexArrays glGenVertexArraysOES +#define glBindVertexArray glBindVertexArrayOES +#define glMapBuffer glMapBufferOES +#define glUnmapBuffer glUnmapBufferOES + +#define GL_DEPTH24_STENCIL8 GL_DEPTH24_STENCIL8_OES +#define GL_WRITE_ONLY GL_WRITE_ONLY_OES + +// Mac +#elif __CC_PLATFORM_MAC + + +#if 1 +#define glDeleteVertexArrays glDeleteVertexArraysAPPLE +#define glGenVertexArrays glGenVertexArraysAPPLE +#define glBindVertexArray glBindVertexArrayAPPLE + +#else // OpenGL 3.2 Core Profile + +#define glDeleteVertexArrays glDeleteVertexArrays +#define glGenVertexArrays glGenVertexArrays +#define glBindVertexArray glBindVertexArray +#endif + +#endif diff --git "a/21451198\345\215\242\350\266\205/project5/MyPlane/libs/cocos2d/Platforms/CCNS.h" "b/21451198\345\215\242\350\266\205/project5/MyPlane/libs/cocos2d/Platforms/CCNS.h" new file mode 100644 index 00000000..5a396be7 --- /dev/null +++ "b/21451198\345\215\242\350\266\205/project5/MyPlane/libs/cocos2d/Platforms/CCNS.h" @@ -0,0 +1,54 @@ +/* + * cocos2d for iPhone: http://www.cocos2d-iphone.org + * + * Copyright (c) 2010 Ricardo Quesada + * Copyright (c) 2011 Zynga Inc. + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + * THE SOFTWARE. + */ + +// +// Common layer for NS (Next-Step) stuff +// + +#import "../ccMacros.h" + +#import // for NSObject + +#ifdef __CC_PLATFORM_IOS + +#define CCRectFromString(__r__) CGRectFromString(__r__) +#define CCPointFromString(__p__) CGPointFromString(__p__) +#define CCSizeFromString(__s__) CGSizeFromString(__s__) +#define CCNSSizeToCGSize +#define CCNSRectToCGRect +#define CCNSPointToCGPoint + + +#elif defined(__CC_PLATFORM_MAC) + +#define CCRectFromString(__r__) NSRectToCGRect( NSRectFromString(__r__) ) +#define CCPointFromString(__p__) NSPointToCGPoint( NSPointFromString(__p__) ) +#define CCSizeFromString(__s__) NSSizeToCGSize( NSSizeFromString(__s__) ) +#define CCNSSizeToCGSize NSSizeToCGSize +#define CCNSRectToCGRect NSRectToCGRect +#define CCNSPointToCGPoint NSPointToCGPoint +#endif + + diff --git "a/21451198\345\215\242\350\266\205/project5/MyPlane/libs/cocos2d/Platforms/Mac/CCDirectorMac.h" "b/21451198\345\215\242\350\266\205/project5/MyPlane/libs/cocos2d/Platforms/Mac/CCDirectorMac.h" new file mode 100644 index 00000000..68fad06f --- /dev/null +++ "b/21451198\345\215\242\350\266\205/project5/MyPlane/libs/cocos2d/Platforms/Mac/CCDirectorMac.h" @@ -0,0 +1,110 @@ +/* + * cocos2d for iPhone: http://www.cocos2d-iphone.org + * + * Copyright (c) 2010 Ricardo Quesada + * Copyright (c) 2011 Zynga Inc. + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + * THE SOFTWARE. + */ + + +// Only compile this code on Mac. These files should not be included on your iOS project. +// But in case they are included, it won't be compiled. +#import "../../ccMacros.h" +#ifdef __CC_PLATFORM_MAC + +#import +#import "../../CCDirector.h" + +@class CCEventDispatcher; + +enum { + /// If the window is resized, it won't be autoscaled + kCCDirectorResize_NoScale, + /// If the window is resized, it will be autoscaled (default behavior) + kCCDirectorResize_AutoScale, +}; + +@interface CCDirector (MacExtension) +/** sets the CCEventDispatcher (Mac only) */ +@property (nonatomic, readwrite, retain) CCEventDispatcher* eventDispatcher; + +/** converts an NSEvent to GL coordinates (Mac only) */ +-(CGPoint) convertEventToGL:(NSEvent*)event; +@end + +/** Base class of Mac directors + @since v0.99.5 + */ +@interface CCDirectorMac : CCDirector +{ + BOOL _isFullScreen; + int _resizeMode; + CGPoint _winOffset; + CGSize _originalWinSize; + + NSWindow *_fullScreenWindow; + + // Event Dispatcher + CCEventDispatcher *_eventDispatcher; + + // cache + NSWindow *_windowGLView; + NSView *_superViewGLView; + NSRect _originalWinRect; // Original size and position +} + +// whether or not the view is in fullscreen mode +@property (nonatomic, readonly) BOOL isFullScreen; + +// resize mode: with or without scaling +@property (nonatomic, readwrite) int resizeMode; + +@property (nonatomic, readwrite) CGSize originalWinSize; + +/** Sets the view in fullscreen or window mode */ +- (void) setFullScreen:(BOOL)fullscreen; + +/** Converts window size coordinates to logical coordinates. + Useful only if resizeMode is kCCDirectorResize_Scale. + If resizeMode is kCCDirectorResize_NoScale, then no conversion will be done. +*/ +- (CGPoint) convertToLogicalCoordinates:(CGPoint)coordinates; +@end + + +/** DisplayLinkDirector is a Director that synchronizes timers with the refresh rate of the display. + * + * Features and Limitations: + * - Only available on 3.1+ + * - Scheduled timers & drawing are synchronizes with the refresh rate of the display + * - Only supports animation intervals of 1/60 1/30 & 1/15 + * + * It is the recommended Director if the SDK is 3.1 or newer + * + * @since v0.8.2 + */ +@interface CCDirectorDisplayLink : CCDirectorMac +{ + CVDisplayLinkRef displayLink; +} +@end + +#endif // __CC_PLATFORM_MAC + diff --git "a/21451198\345\215\242\350\266\205/project5/MyPlane/libs/cocos2d/Platforms/Mac/CCDirectorMac.m" "b/21451198\345\215\242\350\266\205/project5/MyPlane/libs/cocos2d/Platforms/Mac/CCDirectorMac.m" new file mode 100644 index 00000000..f7041825 --- /dev/null +++ "b/21451198\345\215\242\350\266\205/project5/MyPlane/libs/cocos2d/Platforms/Mac/CCDirectorMac.m" @@ -0,0 +1,589 @@ +/* + * cocos2d for iPhone: http://www.cocos2d-iphone.org + * + * Copyright (c) 2010 Ricardo Quesada + * Copyright (c) 2011 Zynga Inc. + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + * THE SOFTWARE. + */ + +// Only compile this code on Mac. These files should not be included on your iOS project. +// But in case they are included, it won't be compiled. +#import "../../ccMacros.h" +#ifdef __CC_PLATFORM_MAC + +#import + +#import "CCDirectorMac.h" +#import "CCEventDispatcher.h" +#import "CCGLView.h" +#import "CCWindow.h" + +#import "../../CCNode.h" +#import "../../CCScheduler.h" +#import "../../ccMacros.h" +#import "../../CCGLProgram.h" +#import "../../ccGLStateCache.h" + +// external +#import "kazmath/kazmath.h" +#import "kazmath/GL/matrix.h" + +#pragma mark - +#pragma mark Director Mac extensions + + +@interface CCDirector () +-(void) setNextScene; +-(void) showStats; +-(void) calculateDeltaTime; +-(void) calculateMPF; +@end + +@implementation CCDirector (MacExtension) +-(CGPoint) convertEventToGL:(NSEvent*)event +{ + NSPoint point = [[self view] convertPoint:[event locationInWindow] fromView:nil]; + CGPoint p = NSPointToCGPoint(point); + + return [(CCDirectorMac*)self convertToLogicalCoordinates:p]; +} + +-(void) setEventDispatcher:(CCEventDispatcher *)dispatcher +{ + NSAssert(NO, @"override me"); +} + +-(CCEventDispatcher *) eventDispatcher +{ + NSAssert(NO, @"override me"); + return nil; +} +@end + +#pragma mark - +#pragma mark Director Mac + +@implementation CCDirectorMac + +@synthesize isFullScreen = _isFullScreen; +@synthesize originalWinSize = _originalWinSize; + +-(id) init +{ + if( (self = [super init]) ) { + _isFullScreen = NO; + _resizeMode = kCCDirectorResize_AutoScale; + + _originalWinSize = CGSizeZero; + _fullScreenWindow = nil; + _windowGLView = nil; + _winOffset = CGPointZero; + + _eventDispatcher = [[CCEventDispatcher alloc] init]; + } + + return self; +} + +- (void) dealloc +{ + [_eventDispatcher release]; + [__view release]; + [_superViewGLView release]; + [_fullScreenWindow release]; + [_windowGLView release]; + + [super dealloc]; +} + +// +// setFullScreen code taken from GLFullScreen example by Apple +// +- (void) setFullScreen:(BOOL)fullscreen +{ +// _isFullScreen = !_isFullScreen; +// +// if (_isFullScreen) +// { +// [self.view enterFullScreenMode:[[self.view window] screen] withOptions:nil]; +// } +// else +// { +// [self.view exitFullScreenModeWithOptions:nil]; +// [[self.view window] makeFirstResponder: self.view]; +// } +// +// return; + + // Mac OS X 10.6 and later offer a simplified mechanism to create full-screen contexts +#if MAC_OS_X_VERSION_MIN_REQUIRED > MAC_OS_X_VERSION_10_5 + + if (_isFullScreen == fullscreen) + return; + + CCGLView *openGLview = (CCGLView*) self.view; + BOOL viewAcceptsTouchEvents = openGLview.acceptsTouchEvents; + + if( fullscreen ) { + _originalWinRect = [openGLview frame]; + + // Cache normal window and superview of openGLView + if(!_windowGLView) + _windowGLView = [[openGLview window] retain]; + + [_superViewGLView release]; + _superViewGLView = [[openGLview superview] retain]; + + + // Get screen size + NSRect displayRect = [[NSScreen mainScreen] frame]; + + // Create a screen-sized window on the display you want to take over + _fullScreenWindow = [[CCWindow alloc] initWithFrame:displayRect fullscreen:YES]; + + // Remove glView from window + [openGLview removeFromSuperview]; + + // Set new frame + [openGLview setFrame:displayRect]; + + // Attach glView to fullscreen window + [_fullScreenWindow setContentView:openGLview]; + + // Show the fullscreen window + [_fullScreenWindow makeKeyAndOrderFront:self]; + [_fullScreenWindow makeMainWindow]; + + } else { + + // Remove glView from fullscreen window + [openGLview removeFromSuperview]; + + // Release fullscreen window + [_fullScreenWindow release]; + _fullScreenWindow = nil; + + // Attach glView to superview + [_superViewGLView addSubview:openGLview]; + + // Set new frame + [openGLview setFrame:_originalWinRect]; + + // Show the window + [_windowGLView makeKeyAndOrderFront:self]; + [_windowGLView makeMainWindow]; + } + + // issue #1189 + [_windowGLView makeFirstResponder:openGLview]; + + _isFullScreen = fullscreen; + + [openGLview retain]; // Retain +1 + + // re-configure glView + [self setView:openGLview]; + + [openGLview setAcceptsTouchEvents:viewAcceptsTouchEvents]; + + [openGLview release]; // Retain -1 + + [openGLview setNeedsDisplay:YES]; +#else +#error Full screen is not supported for Mac OS 10.5 or older yet +#error If you don't want FullScreen support, you can safely remove these 2 lines +#endif +} + +-(void) setView:(CCGLView *)view +{ + if( view != __view) { + + [super setView:view]; + + // cache the NSWindow and NSOpenGLView created from the NIB + if( !_isFullScreen && CGSizeEqualToSize(_originalWinSize, CGSizeZero)) + { + _originalWinSize = _winSizeInPixels; + } + } +} + +-(int) resizeMode +{ + return _resizeMode; +} + +-(void) setResizeMode:(int)mode +{ + if( mode != _resizeMode ) { + + _resizeMode = mode; + + [self setProjection:_projection]; + [self.view setNeedsDisplay: YES]; + } +} + +-(void) setViewport +{ + CGPoint offset = CGPointZero; + float widthAspect = _winSizeInPixels.width; + float heightAspect = _winSizeInPixels.height; + + + if( _resizeMode == kCCDirectorResize_AutoScale && ! CGSizeEqualToSize(_originalWinSize, CGSizeZero ) ) { + + float aspect = _originalWinSize.width / _originalWinSize.height; + widthAspect = _winSizeInPixels.width; + heightAspect = _winSizeInPixels.width / aspect; + + if( heightAspect > _winSizeInPixels.height ) { + widthAspect = _winSizeInPixels.height * aspect; + heightAspect = _winSizeInPixels.height; + } + + _winOffset.x = (_winSizeInPixels.width - widthAspect) / 2; + _winOffset.y = (_winSizeInPixels.height - heightAspect) / 2; + + offset = _winOffset; + } + + glViewport(offset.x, offset.y, widthAspect, heightAspect); +} + +-(void) setProjection:(ccDirectorProjection)projection +{ + CGSize size = _winSizeInPixels; + if( _resizeMode == kCCDirectorResize_AutoScale && ! CGSizeEqualToSize(_originalWinSize, CGSizeZero ) ) { + size = _originalWinSize; + } + + [self setViewport]; + + switch (projection) { + case kCCDirectorProjection2D: + + kmGLMatrixMode(KM_GL_PROJECTION); + kmGLLoadIdentity(); + + kmMat4 orthoMatrix; + kmMat4OrthographicProjection(&orthoMatrix, 0, size.width, 0, size.height, -1024, 1024); + kmGLMultMatrix( &orthoMatrix ); + + kmGLMatrixMode(KM_GL_MODELVIEW); + kmGLLoadIdentity(); + break; + + + case kCCDirectorProjection3D: + { + + float zeye = [self getZEye]; + + kmGLMatrixMode(KM_GL_PROJECTION); + kmGLLoadIdentity(); + + kmMat4 matrixPerspective, matrixLookup; + + // issue #1334 + kmMat4PerspectiveProjection( &matrixPerspective, 60, (GLfloat)size.width/size.height, 0.1f, MAX(zeye*2,1500) ); +// kmMat4PerspectiveProjection( &matrixPerspective, 60, (GLfloat)size.width/size.height, 0.1f, 1500); + + + kmGLMultMatrix(&matrixPerspective); + + + kmGLMatrixMode(KM_GL_MODELVIEW); + kmGLLoadIdentity(); + kmVec3 eye, center, up; + + float eyeZ = size.height * zeye / _winSizeInPixels.height; + + kmVec3Fill( &eye, size.width/2, size.height/2, eyeZ ); + kmVec3Fill( ¢er, size.width/2, size.height/2, 0 ); + kmVec3Fill( &up, 0, 1, 0); + kmMat4LookAt(&matrixLookup, &eye, ¢er, &up); + kmGLMultMatrix(&matrixLookup); + break; + } + + case kCCDirectorProjectionCustom: + if( [_delegate respondsToSelector:@selector(updateProjection)] ) + [_delegate updateProjection]; + break; + + default: + CCLOG(@"cocos2d: Director: unrecognized projection"); + break; + } + + _projection = projection; + + ccSetProjectionMatrixDirty(); +} + + +// If scaling is supported, then it should always return the original size +// otherwise it should return the "real" size. +-(CGSize) winSize +{ + if( _resizeMode == kCCDirectorResize_AutoScale ) + return _originalWinSize; + + return _winSizeInPixels; +} + +-(CGSize) winSizeInPixels +{ + return [self winSize]; +} + +- (CGPoint) convertToLogicalCoordinates:(CGPoint)coords +{ + CGPoint ret; + + if( _resizeMode == kCCDirectorResize_NoScale ) + ret = coords; + + else { + + float x_diff = _originalWinSize.width / (_winSizeInPixels.width - _winOffset.x * 2); + float y_diff = _originalWinSize.height / (_winSizeInPixels.height - _winOffset.y * 2); + + float adjust_x = (_winSizeInPixels.width * x_diff - _originalWinSize.width ) / 2; + float adjust_y = (_winSizeInPixels.height * y_diff - _originalWinSize.height ) / 2; + + ret = CGPointMake( (x_diff * coords.x) - adjust_x, ( y_diff * coords.y ) - adjust_y ); + } + + return ret; +} + +-(void) setEventDispatcher:(CCEventDispatcher *)dispatcher +{ + if( dispatcher != _eventDispatcher ) { + [_eventDispatcher release]; + _eventDispatcher = [dispatcher retain]; + } +} + +-(CCEventDispatcher *) eventDispatcher +{ + return _eventDispatcher; +} +@end + + +#pragma mark - +#pragma mark DirectorDisplayLink + + +@implementation CCDirectorDisplayLink + +- (CVReturn) getFrameForTime:(const CVTimeStamp*)outputTime +{ +#if (CC_DIRECTOR_MAC_THREAD == CC_MAC_USE_DISPLAY_LINK_THREAD) + if( ! _runningThread ) + _runningThread = [NSThread currentThread]; + + NSAutoreleasePool *pool = [[NSAutoreleasePool alloc] init]; + + [self drawScene]; + + // Process timers and other events + [[NSRunLoop currentRunLoop] runMode:NSDefaultRunLoopMode beforeDate:nil]; + + [pool release]; + +#else + [self performSelector:@selector(drawScene) onThread:_runningThread withObject:nil waitUntilDone:YES]; +#endif + + return kCVReturnSuccess; +} + +// This is the renderer output callback function +static CVReturn MyDisplayLinkCallback(CVDisplayLinkRef displayLink, const CVTimeStamp* now, const CVTimeStamp* outputTime, CVOptionFlags flagsIn, CVOptionFlags* flagsOut, void* displayLinkContext) +{ + CVReturn result = [(CCDirectorDisplayLink*)displayLinkContext getFrameForTime:outputTime]; + return result; +} + +- (void) startAnimation +{ + [super startAnimation]; + + if(_isAnimating) + return; + + CCLOG(@"cocos2d: startAnimation"); +#if (CC_DIRECTOR_MAC_THREAD == CC_MAC_USE_OWN_THREAD) + _runningThread = [[NSThread alloc] initWithTarget:self selector:@selector(mainLoop) object:nil]; + [_runningThread start]; +#elif (CC_DIRECTOR_MAC_THREAD == CC_MAC_USE_MAIN_THREAD) + _runningThread = [NSThread mainThread]; +#endif + + gettimeofday( &_lastUpdate, NULL); + + // Create a display link capable of being used with all active displays + CVDisplayLinkCreateWithActiveCGDisplays(&displayLink); + + // Set the renderer output callback function + CVDisplayLinkSetOutputCallback(displayLink, &MyDisplayLinkCallback, self); + + // Set the display link for the current renderer + CCGLView *openGLview = (CCGLView*) self.view; + CGLContextObj cglContext = [[openGLview openGLContext] CGLContextObj]; + CGLPixelFormatObj cglPixelFormat = [[openGLview pixelFormat] CGLPixelFormatObj]; + CVDisplayLinkSetCurrentCGDisplayFromOpenGLContext(displayLink, cglContext, cglPixelFormat); + + // Activate the display link + CVDisplayLinkStart(displayLink); + + _isAnimating = YES; +} + +- (void) stopAnimation +{ + if(!_isAnimating) + return; + + CCLOG(@"cocos2d: stopAnimation"); + + if( displayLink ) { + CVDisplayLinkStop(displayLink); + CVDisplayLinkRelease(displayLink); + displayLink = NULL; + +#if CC_DIRECTOR_MAC_THREAD == CC_MAC_USE_OWN_THREAD + [_runningThread cancel]; + [_runningThread release]; + _runningThread = nil; +#elif (CC_DIRECTOR_MAC_THREAD == CC_MAC_USE_MAIN_THREAD) + _runningThread = nil; +#endif + } + + _isAnimating = NO; +} + +-(void) dealloc +{ + if( displayLink ) { + CVDisplayLinkStop(displayLink); + CVDisplayLinkRelease(displayLink); + } + [super dealloc]; +} + +// +// Mac Director has its own thread +// +-(void) mainLoop +{ + while( ![[NSThread currentThread] isCancelled] ) { + // There is no autorelease pool when this method is called because it will be called from a background thread + // It's important to create one or you will leak objects + NSAutoreleasePool *pool = [[NSAutoreleasePool alloc] init]; + + [[NSRunLoop currentRunLoop] run]; + + [pool release]; + } +} + +// +// Draw the Scene +// +- (void) drawScene +{ + /* calculate "global" dt */ + [self calculateDeltaTime]; + + // We draw on a secondary thread through the display link + // When resizing the view, -reshape is called automatically on the main thread + // Add a mutex around to avoid the threads accessing the context simultaneously when resizing + + [self.view lockOpenGLContext]; + + /* tick before glClear: issue #533 */ + if( ! _isPaused ) + [_scheduler update: _dt]; + + glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); + + /* to avoid flickr, nextScene MUST be here: after tick and before draw. + XXX: Which bug is this one. It seems that it can't be reproduced with v0.9 */ + if( _nextScene ) + [self setNextScene]; + + kmGLPushMatrix(); + + + /* draw the scene */ + [_runningScene visit]; + + /* draw the notification node */ + [_notificationNode visit]; + + if( _displayStats ) + [self showStats]; + + kmGLPopMatrix(); + + _totalFrames++; + + + // flush buffer + [self.view.openGLContext flushBuffer]; + + [self.view unlockOpenGLContext]; + + if( _displayStats ) + [self calculateMPF]; +} + +// set the event dispatcher +-(void) setView:(CCGLView *)view +{ + [super setView:view]; + + [view setEventDelegate:_eventDispatcher]; + [_eventDispatcher setDispatchEvents: YES]; + + // Enable Touches. Default no. + // Only available on OS X 10.6+ +#if MAC_OS_X_VERSION_MIN_REQUIRED > MAC_OS_X_VERSION_10_5 + [view setAcceptsTouchEvents:NO]; +// [view setAcceptsTouchEvents:YES]; +#endif + + + // Synchronize buffer swaps with vertical refresh rate + [[view openGLContext] makeCurrentContext]; + GLint swapInt = 1; + [[view openGLContext] setValues:&swapInt forParameter:NSOpenGLCPSwapInterval]; +} + +@end + +#endif // __CC_PLATFORM_MAC diff --git "a/21451198\345\215\242\350\266\205/project5/MyPlane/libs/cocos2d/Platforms/Mac/CCEventDispatcher.h" "b/21451198\345\215\242\350\266\205/project5/MyPlane/libs/cocos2d/Platforms/Mac/CCEventDispatcher.h" new file mode 100644 index 00000000..43c7f691 --- /dev/null +++ "b/21451198\345\215\242\350\266\205/project5/MyPlane/libs/cocos2d/Platforms/Mac/CCEventDispatcher.h" @@ -0,0 +1,343 @@ +/* + * cocos2d for iPhone: http://www.cocos2d-iphone.org + * + * Copyright (c) 2010 Ricardo Quesada + * Copyright (c) 2011 Zynga Inc. + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + * THE SOFTWARE. + */ + +// Only compile this code on Mac. These files should not be included on your iOS project. +// But in case they are included, it won't be compiled. +#import "../../ccMacros.h" +#ifdef __CC_PLATFORM_MAC + +#import + +#import "CCGLView.h" +#import "../../Support/uthash.h" // hack: uthash needs to be imported before utlist to prevent warning +#import "../../Support/utlist.h" +#import "../../ccConfig.h" + +#pragma mark - +#pragma mark CCMouseEventDelegate + +/** CCMouseEventDelegate protocol. + Implement it in your node to receive any of mouse events + */ +@protocol CCMouseEventDelegate +@optional + +// +// left +// +/** called when the "mouseDown" event is received. + Return YES to avoid propagating the event to other delegates. + */ +-(BOOL) ccMouseDown:(NSEvent*)event; + +/** called when the "mouseDragged" event is received. + Return YES to avoid propagating the event to other delegates. + */ +-(BOOL) ccMouseDragged:(NSEvent*)event; + +/** called when the "mouseMoved" event is received. + Return YES to avoid propagating the event to other delegates. + By default, "mouseMoved" is disabled. To enable it, send the "setAcceptsMouseMovedEvents:YES" message to the main window. + */ +-(BOOL) ccMouseMoved:(NSEvent*)event; + +/** called when the "mouseUp" event is received. + Return YES to avoid propagating the event to other delegates. + */ +-(BOOL) ccMouseUp:(NSEvent*)event; + + +// +// right +// + +/** called when the "rightMouseDown" event is received. + Return YES to avoid propagating the event to other delegates. + */ +-(BOOL) ccRightMouseDown:(NSEvent*)event; + +/** called when the "rightMouseDragged" event is received. + Return YES to avoid propagating the event to other delegates. + */ +-(BOOL) ccRightMouseDragged:(NSEvent*)event; + +/** called when the "rightMouseUp" event is received. + Return YES to avoid propagating the event to other delegates. + */ +-(BOOL) ccRightMouseUp:(NSEvent*)event; + +// +// other +// + +/** called when the "otherMouseDown" event is received. + Return YES to avoid propagating the event to other delegates. + */ +-(BOOL) ccOtherMouseDown:(NSEvent*)event; + +/** called when the "otherMouseDragged" event is received. + Return YES to avoid propagating the event to other delegates. + */ +-(BOOL) ccOtherMouseDragged:(NSEvent*)event; + +/** called when the "otherMouseUp" event is received. + Return YES to avoid propagating the event to other delegates. + */ +-(BOOL) ccOtherMouseUp:(NSEvent*)event; + +// +// scroll wheel +// + +/** called when the "scrollWheel" event is received. + Return YES to avoid propagating the event to other delegates. + */ +- (BOOL)ccScrollWheel:(NSEvent *)theEvent; + + +// +// enter / exit +// + +/** called when the "mouseEntered" event is received. + Return YES to avoid propagating the event to other delegates. + */ +- (void)ccMouseEntered:(NSEvent *)theEvent; + +/** called when the "mouseExited" event is received. + Return YES to avoid propagating the event to other delegates. + */ +- (void)ccMouseExited:(NSEvent *)theEvent; + +@end + +#pragma mark - +#pragma mark CCKeyboardEventDelegate + +/** CCKeyboardEventDelegate protocol. + Implement it in your node to receive any of keyboard events + */ +@protocol CCKeyboardEventDelegate +@optional +/** called when the "keyUp" event is received. + Return YES to avoid propagating the event to other delegates. + */ +-(BOOL) ccKeyUp:(NSEvent*)event; + +/** called when the "keyDown" event is received. + Return YES to avoid propagating the event to other delegates. + */ +-(BOOL) ccKeyDown:(NSEvent*)event; +/** called when the "flagsChanged" event is received. + Return YES to avoid propagating the event to other delegates. + */ +-(BOOL) ccFlagsChanged:(NSEvent*)event; +@end + +#pragma mark - +#pragma mark CCTouchEventDelegate + +/** CCTouchEventDelegate protocol. + Implement it in your node to receive any of touch events + */ +@protocol CCTouchEventDelegate +@optional +/** called when the "touchesBegan" event is received. + Return YES to avoid propagating the event to other delegates. + */ +- (BOOL)ccTouchesBeganWithEvent:(NSEvent *)event; + +/** called when the "touchesMoved" event is received. + Return YES to avoid propagating the event to other delegates. + */ +- (BOOL)ccTouchesMovedWithEvent:(NSEvent *)event; + +/** called when the "touchesEnded" event is received. + Return YES to avoid propagating the event to other delegates. + */ +- (BOOL)ccTouchesEndedWithEvent:(NSEvent *)event; + +/** called when the "touchesCancelled" event is received. + Return YES to avoid propagating the event to other delegates. + */ +- (BOOL)ccTouchesCancelledWithEvent:(NSEvent *)event; + +@end + +#pragma mark - +#pragma mark CCGestureEventDelegate + +/** CCGestureEventDelegate protocol. + Implement it in your node to receive any of gesture events + */ +@protocol CCGestureEventDelegate +@optional + +/** called when the "beginGesture" event is received. + Return YES to avoid propagating the event to other delegates. + */ +- (BOOL)ccBeginGestureWithEvent:(NSEvent *)event; + +/** called when the "magnify" gesture event is received. + Return YES to avoid propagating the event to other delegates. + */ +- (BOOL)ccMagnifyWithEvent:(NSEvent *)event; + +/** called when the "smartMagnify" gesture event is received. + Return YES to avoid propagating the event to other delegates. + */ +- (BOOL)ccSmartMagnifyWithEvent:(NSEvent *)event; + +/** called when the "rotate" gesture event is received. + Return YES to avoid propagating the event to other delegates. + */ +- (BOOL)ccRotateWithEvent:(NSEvent *)event; + +/** called when the "swipe" gesture event is received. + Return YES to avoid propagating the event to other delegates. + */ +- (BOOL)ccSwipeWithEvent:(NSEvent *)event; + +/** called when the "endGesture" event is received. + Return YES to avoid propagating the event to other delegates. + */ +- (BOOL)ccEndGestureWithEvent:(NSEvent *)event; + +@end + +#pragma mark - CCEventObject + +@interface CCEventObject : NSObject +{ +@public + NSEvent *event; + SEL selector; +} +@end + +#pragma mark - CCEventDispatcher + +struct _listEntry; +struct _listDeletedEntry; +struct _listAddedEntry; + +/** CCEventDispatcher + + This is object is responsible for dispatching the events: + - Mouse events + - Keyboard events + - Touch events + + Only available on Mac + */ +@interface CCEventDispatcher : NSObject +{ + BOOL _dispatchEvents; + BOOL _locked; + + struct _listEntry *_keyboardDelegates; + struct _listEntry *_mouseDelegates; + struct _listEntry *_touchDelegates; + struct _listEntry *_gestureDelegates; + + struct _listDeletedEntry *_delegatesToBeRemoved; + struct _listAddedEntry *_delegatesToBeAdded; + +} + +@property (nonatomic, readwrite) BOOL dispatchEvents; + +#pragma mark CCEventDispatcher - Mouse + +/** Adds a mouse delegate to the dispatcher's list. + Delegates with a lower priority value will be called before higher priority values. + All the events will be propagated to all the delegates, unless the one delegate returns YES. + + IMPORTANT: The delegate will be retained. + */ +-(void) addMouseDelegate:(id) delegate priority:(NSInteger)priority; + +/** removes a mouse delegate */ +-(void) removeMouseDelegate:(id) delegate; + +/** Removes all mouse delegates, releasing all the delegates */ +-(void) removeAllMouseDelegates; + +#pragma mark CCEventDispatcher - Keyboard + +/** Adds a Keyboard delegate to the dispatcher's list. + Delegates with a lower priority value will be called before higher priority values. + All the events will be propagated to all the delegates, unless the one delegate returns YES. + + IMPORTANT: The delegate will be retained. + */ +-(void) addKeyboardDelegate:(id) delegate priority:(NSInteger)priority; + +/** removes a mouse delegate */ +-(void) removeKeyboardDelegate:(id) delegate; + +/** Removes all mouse delegates, releasing all the delegates */ +-(void) removeAllKeyboardDelegates; + +#pragma mark CCEventDispatcher - Touches + +/** Adds a Touch delegate to the dispatcher's list. + Delegates with a lower priority value will be called before higher priority values. + All the events will be propagated to all the delegates, unless the one delegate returns YES. + + IMPORTANT: The delegate will be retained. + */ +- (void)addTouchDelegate:(id)delegate priority:(NSInteger)priority; + +/** Removes a touch delegate */ +- (void)removeTouchDelegate:(id) delegate; + +/** Removes all touch delegates, releasing all the delegates */ +- (void)removeAllTouchDelegates; + +#pragma mark CCEventDispatcher - Gesture + +/** Adds a gesture delegate to the dispatcher's list. + Delegates with a lower priority value will be called before higher priority values. + All the events will be propagated to all the delegates, unless the one delegate returns YES. + + IMPORTANT: The delegate will be retained. + */ +- (void)addGestureDelegate:(id)delegate priority:(NSInteger)priority; + +/** Removes a gesture delegate */ +- (void)removeGestureDelegate:(id) delegate; + +/** Removes all gesture delegates, releasing all the delegates */ +- (void)removeAllGestureDelegates; + +#pragma mark CCEventDispatcher - Dispatch + +-(void) dispatchEvent:(CCEventObject*)event; + +@end + + +#endif // __CC_PLATFORM_MAC diff --git "a/21451198\345\215\242\350\266\205/project5/MyPlane/libs/cocos2d/Platforms/Mac/CCEventDispatcher.m" "b/21451198\345\215\242\350\266\205/project5/MyPlane/libs/cocos2d/Platforms/Mac/CCEventDispatcher.m" new file mode 100644 index 00000000..2d88840a --- /dev/null +++ "b/21451198\345\215\242\350\266\205/project5/MyPlane/libs/cocos2d/Platforms/Mac/CCEventDispatcher.m" @@ -0,0 +1,849 @@ +/* + * cocos2d for iPhone: http://www.cocos2d-iphone.org + * + * Copyright (c) 2010 Ricardo Quesada + * Copyright (c) 2011 Zynga Inc. + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + * THE SOFTWARE. + */ + +// Only compile this code on Mac. These files should not be included on your iOS project. +// But in case they are included, it won't be compiled. +#import "../../ccMacros.h" +#ifdef __CC_PLATFORM_MAC + +#import "CCEventDispatcher.h" +#import "../../CCDirector.h" +#import "../../ccConfig.h" + +enum { + // mouse + kCCImplementsMouseDown = 1 << 0, + kCCImplementsMouseMoved = 1 << 1, + kCCImplementsMouseDragged = 1 << 2, + kCCImplementsMouseUp = 1 << 3, + kCCImplementsRightMouseDown = 1 << 4, + kCCImplementsRightMouseDragged = 1 << 5, + kCCImplementsRightMouseUp = 1 << 6, + kCCImplementsOtherMouseDown = 1 << 7, + kCCImplementsOtherMouseDragged = 1 << 8, + kCCImplementsOtherMouseUp = 1 << 9, + kCCImplementsScrollWheel = 1 << 10, + kCCImplementsMouseEntered = 1 << 11, + kCCImplementsMouseExited = 1 << 12, + + kCCImplementsTouchesBegan = 1 << 13, + kCCImplementsTouchesMoved = 1 << 14, + kCCImplementsTouchesEnded = 1 << 15, + kCCImplementsTouchesCancelled = 1 << 16, + + // gesture + kCCImplementsBeginGestureWithEvent = 1 << 0, + kCCImplementsMagnifyWithEvent = 1 << 1, + kCCImplementsSmartMagnifyWithEvent = 1 << 2, + kCCImplementsRotateWithEvent = 1 << 3, + kCCImplementsSwipeWithEvent = 1 << 4, + kCCImplementsEndGestureWithEvent = 1 << 5, + + // keyboard + kCCImplementsKeyUp = 1 << 0, + kCCImplementsKeyDown = 1 << 1, + kCCImplementsFlagsChanged = 1 << 2, +}; + + +typedef struct _listEntry +{ + // XXX do no change the order of these 3 fields. Needed for "subclassing" + struct _listEntry *prev, *next; + id delegate; + // (end) + + NSInteger priority; + NSUInteger flags; +} tListEntry; + +typedef struct _listDeletedEntry +{ + // XXX do no change the order of these 3 fields. Needed for "subclassing" + struct _listDeletedEntry *prev, *next; + id delegate; + // (end) + + struct _listEntry **listToBeDeleted; + +} tListDeletedEntry; + +typedef struct _listAddedEntry +{ + // XXX do no change the order of these 3 fields. Needed for "subclassing" + struct _listAddedEntry *prev, *next; + id delegate; + // (end) + + NSInteger priority; + NSUInteger flags; + struct _listEntry **listToBeAdded; +} tListAddedEntry; + + + +#pragma mark - CCEventObject + +@implementation CCEventObject +@end + +#pragma mark - CCEventDispatcher + +@interface CCEventDispatcher() +-(BOOL) removeDelegate:(id)delegate fromList:(tListEntry**)list; +@end + +@implementation CCEventDispatcher + +@synthesize dispatchEvents=_dispatchEvents; + +-(id) init +{ + if( (self = [super init]) ) + { + // events enabled by default + _dispatchEvents = YES; + + // delegates + _keyboardDelegates = NULL; + _mouseDelegates = NULL; + _touchDelegates = NULL; + _gestureDelegates = NULL; + + _delegatesToBeAdded = NULL; + _delegatesToBeRemoved = NULL; + + _locked = NO; + } + + return self; +} + +- (void) dealloc +{ + [super dealloc]; +} + +#pragma mark CCEventDispatcher - add / remove delegates + + +-(void) addLaterDelegate:(id)delegate priority:(NSInteger)priority flags:(NSUInteger)flags list:(tListEntry**)list +{ + // XXX: Since, "remove" is "executed" after "add", it is not needed to check if the delegate was already added for removal. + // In fact, if you remove it now, it could be a bug, since EventDispatcher doesn't support updated priority. + // And the only way to update the priority is by deleting, re-adding the delegate with a new priority + tListAddedEntry *listElement = malloc( sizeof(*listElement) ); + + listElement->delegate = [delegate retain]; + listElement->priority = priority; + listElement->flags = flags; + listElement->listToBeAdded = list; + listElement->next = listElement->prev = NULL; + + DL_APPEND( _delegatesToBeAdded, listElement ); +} + +-(void) addDelegate:(id)delegate priority:(NSInteger)priority flags:(NSUInteger)flags list:(tListEntry**)list +{ + tListEntry *listElement = malloc( sizeof(*listElement) ); + + listElement->delegate = [delegate retain]; + listElement->priority = priority; + listElement->flags = flags; + listElement->next = listElement->prev = NULL; + + // empty list ? + if( ! *list ) { + DL_APPEND( *list, listElement ); + + } else { + BOOL added = NO; + + for( tListEntry *elem = *list; elem ; elem = elem->next ) { + if( priority < elem->priority ) { + + if( elem == *list ) + DL_PREPEND(*list, listElement); + else { + listElement->next = elem; + listElement->prev = elem->prev; + + elem->prev->next = listElement; + elem->prev = listElement; + } + + added = YES; + break; + } + } + + // Not added? priority has the higher value. Append it. + if( !added ) + DL_APPEND(*list, listElement); + } +} + +-(void) removeLaterDelegate:(id)delegate fromList:(tListEntry**)list +{ + // Only add it if it was not already added for deletion + if( ! [self removeDelegate:delegate fromList:(tListEntry**)&_delegatesToBeAdded] ) { + + tListDeletedEntry *listElement = malloc( sizeof(*listElement) ); + + listElement->delegate = [delegate retain]; + listElement->listToBeDeleted = list; + listElement->next = listElement->prev = NULL; + + DL_APPEND( _delegatesToBeRemoved, listElement ); + } +} + +-(BOOL) removeDelegate:(id)delegate fromList:(tListEntry**)list +{ + tListEntry *entry, *tmp; + + DL_FOREACH_SAFE( *list, entry, tmp ) { + if( entry->delegate == delegate ) { + DL_DELETE( *list, entry ); + [delegate release]; + free(entry); + return YES; + break; + } + } + return NO; +} + +-(void) removeAllDelegatesFromList:(tListEntry**)list +{ + NSAssert( ! _locked, @"BUG. Open a ticket. Can't call this function when processing events."); + + @synchronized(self) { + tListEntry *entry, *tmp; + + DL_FOREACH_SAFE( *list, entry, tmp ) { + DL_DELETE( *list, entry ); + [entry->delegate release]; + free(entry); + } + } +} + + +-(void) addMouseDelegate:(id) delegate priority:(NSInteger)priority +{ + NSUInteger flags = 0; + + flags |= ( [delegate respondsToSelector:@selector(ccMouseDown:)] ? kCCImplementsMouseDown : 0 ); + flags |= ( [delegate respondsToSelector:@selector(ccMouseDragged:)] ? kCCImplementsMouseDragged : 0 ); + flags |= ( [delegate respondsToSelector:@selector(ccMouseMoved:)] ? kCCImplementsMouseMoved : 0 ); + flags |= ( [delegate respondsToSelector:@selector(ccMouseUp:)] ? kCCImplementsMouseUp : 0 ); + + flags |= ( [delegate respondsToSelector:@selector(ccRightMouseDown:)] ? kCCImplementsRightMouseDown : 0 ); + flags |= ( [delegate respondsToSelector:@selector(ccRightMouseDragged:)] ? kCCImplementsRightMouseDragged : 0 ); + flags |= ( [delegate respondsToSelector:@selector(ccRightMouseUp:)] ? kCCImplementsRightMouseUp : 0 ); + + flags |= ( [delegate respondsToSelector:@selector(ccOtherMouseDown:)] ? kCCImplementsOtherMouseDown : 0 ); + flags |= ( [delegate respondsToSelector:@selector(ccOtherMouseDragged:)] ? kCCImplementsOtherMouseDragged : 0 ); + flags |= ( [delegate respondsToSelector:@selector(ccOtherMouseUp:)] ? kCCImplementsOtherMouseUp : 0 ); + + flags |= ( [delegate respondsToSelector:@selector(ccMouseEntered:)] ? kCCImplementsMouseEntered : 0 ); + flags |= ( [delegate respondsToSelector:@selector(ccMouseExited:)] ? kCCImplementsMouseExited : 0 ); + + flags |= ( [delegate respondsToSelector:@selector(ccScrollWheel:)] ? kCCImplementsScrollWheel : 0 ); + + if( _locked ) + [self addLaterDelegate:delegate priority:priority flags:flags list:&_mouseDelegates]; + else + [self addDelegate:delegate priority:priority flags:flags list:&_mouseDelegates]; + +} + +-(void) removeMouseDelegate:(id) delegate +{ + if( _locked ) + [self removeLaterDelegate:delegate fromList:&_mouseDelegates]; + else + [self removeDelegate:delegate fromList:&_mouseDelegates]; +} + +-(void) removeAllMouseDelegates +{ + [self removeAllDelegatesFromList:&_mouseDelegates]; +} + +-(void) addKeyboardDelegate:(id) delegate priority:(NSInteger)priority +{ + NSUInteger flags = 0; + + flags |= ( [delegate respondsToSelector:@selector(ccKeyUp:)] ? kCCImplementsKeyUp : 0 ); + flags |= ( [delegate respondsToSelector:@selector(ccKeyDown:)] ? kCCImplementsKeyDown : 0 ); + flags |= ( [delegate respondsToSelector:@selector(ccFlagsChanged:)] ? kCCImplementsFlagsChanged : 0 ); + + if( _locked ) + [self addLaterDelegate:delegate priority:priority flags:flags list:&_keyboardDelegates]; + else + [self addDelegate:delegate priority:priority flags:flags list:&_keyboardDelegates]; +} + +-(void) removeKeyboardDelegate:(id) delegate +{ + if( _locked ) + [self removeLaterDelegate:delegate fromList:&_keyboardDelegates]; + else + [self removeDelegate:delegate fromList:&_keyboardDelegates]; +} + +-(void) removeAllKeyboardDelegates +{ + [self removeAllDelegatesFromList:&_keyboardDelegates]; +} + +-(void) addTouchDelegate:(id) delegate priority:(NSInteger)priority +{ + NSUInteger flags = 0; + + flags |= ( [delegate respondsToSelector:@selector(ccTouchesBeganWithEvent:)] ? kCCImplementsTouchesBegan : 0 ); + flags |= ( [delegate respondsToSelector:@selector(ccTouchesMovedWithEvent:)] ? kCCImplementsTouchesMoved : 0 ); + flags |= ( [delegate respondsToSelector:@selector(ccTouchesEndedWithEvent:)] ? kCCImplementsTouchesEnded : 0 ); + flags |= ( [delegate respondsToSelector:@selector(ccTouchesCancelledWithEvent:)] ? kCCImplementsTouchesCancelled : 0 ); + + if( _locked ) + [self addLaterDelegate:delegate priority:priority flags:flags list:&_touchDelegates]; + else + [self addDelegate:delegate priority:priority flags:flags list:&_touchDelegates]; +} + +-(void) removeTouchDelegate:(id) delegate +{ + if( _locked ) + [self removeLaterDelegate:delegate fromList:&_touchDelegates]; + else + [self removeDelegate:delegate fromList:&_touchDelegates]; +} + +-(void) removeAllTouchDelegates +{ + [self removeAllDelegatesFromList:&_touchDelegates]; +} + +- (void)addGestureDelegate:(id)delegate priority:(NSInteger)priority +{ + NSUInteger flags = 0; + + flags |= ( [delegate respondsToSelector:@selector(ccBeginGestureWithEvent:)] ? kCCImplementsBeginGestureWithEvent : 0 ); + flags |= ( [delegate respondsToSelector:@selector(ccMagnifyWithEvent:)] ? kCCImplementsMagnifyWithEvent : 0 ); + flags |= ( [delegate respondsToSelector:@selector(ccSmartMagnifyWithEvent:)] ? kCCImplementsSmartMagnifyWithEvent : 0 ); + flags |= ( [delegate respondsToSelector:@selector(ccRotateWithEvent:)] ? kCCImplementsRotateWithEvent : 0 ); + flags |= ( [delegate respondsToSelector:@selector(ccSwipeWithEvent:)] ? kCCImplementsSwipeWithEvent : 0 ); + flags |= ( [delegate respondsToSelector:@selector(ccEndGestureWithEvent:)] ? kCCImplementsEndGestureWithEvent : 0 ); + + if( _locked ) + [self addLaterDelegate:delegate priority:priority flags:flags list:&_gestureDelegates]; + else + [self addDelegate:delegate priority:priority flags:flags list:&_gestureDelegates]; +} + +- (void)removeGestureDelegate:(id) delegate +{ + if( _locked ) + [self removeLaterDelegate:delegate fromList:&_gestureDelegates]; + else + [self removeDelegate:delegate fromList:&_gestureDelegates]; +} + +- (void)removeAllGestureDelegates +{ + [self removeAllDelegatesFromList:&_gestureDelegates]; +} + +#pragma mark CCEventDispatcher - Mouse events +// +// Mouse events +// + +// +// Left +// +- (void)mouseDown:(NSEvent *)event +{ + if( _dispatchEvents ) { + tListEntry *entry, *tmp; + + DL_FOREACH_SAFE( _mouseDelegates, entry, tmp ) { + if ( entry->flags & kCCImplementsMouseDown ) { + void *swallows = [entry->delegate performSelector:@selector(ccMouseDown:) withObject:event]; + if( swallows ) + break; + } + } + } +} + +- (void)mouseMoved:(NSEvent *)event +{ + if( _dispatchEvents ) { + tListEntry *entry, *tmp; + + DL_FOREACH_SAFE( _mouseDelegates, entry, tmp ) { + if ( entry->flags & kCCImplementsMouseMoved ) { + void *swallows = [entry->delegate performSelector:@selector(ccMouseMoved:) withObject:event]; + if( swallows ) + break; + } + } + } +} + +- (void)mouseDragged:(NSEvent *)event +{ + if( _dispatchEvents ) { + tListEntry *entry, *tmp; + + DL_FOREACH_SAFE( _mouseDelegates, entry, tmp ) { + if ( entry->flags & kCCImplementsMouseDragged ) { + void *swallows = [entry->delegate performSelector:@selector(ccMouseDragged:) withObject:event]; + if( swallows ) + break; + } + } + } +} + +- (void)mouseUp:(NSEvent *)event +{ + @synchronized(self) { + if( _dispatchEvents ) { + tListEntry *entry, *tmp; + + DL_FOREACH_SAFE( _mouseDelegates, entry, tmp ) { + if ( entry->flags & kCCImplementsMouseUp ) { + void *swallows = [entry->delegate performSelector:@selector(ccMouseUp:) withObject:event]; + if( swallows ) + break; + } + } + } + } +} + +// +// Mouse Right +// +- (void)rightMouseDown:(NSEvent *)event +{ + if( _dispatchEvents ) { + tListEntry *entry, *tmp; + + DL_FOREACH_SAFE( _mouseDelegates, entry, tmp ) { + if ( entry->flags & kCCImplementsRightMouseDown ) { + void *swallows = [entry->delegate performSelector:@selector(ccRightMouseDown:) withObject:event]; + if( swallows ) + break; + } + } + } +} + +- (void)rightMouseDragged:(NSEvent *)event +{ + if( _dispatchEvents ) { + tListEntry *entry, *tmp; + + DL_FOREACH_SAFE( _mouseDelegates, entry, tmp ) { + if ( entry->flags & kCCImplementsRightMouseDragged ) { + void *swallows = [entry->delegate performSelector:@selector(ccRightMouseDragged:) withObject:event]; + if( swallows ) + break; + } + } + } +} + +- (void)rightMouseUp:(NSEvent *)event +{ + if( _dispatchEvents ) { + tListEntry *entry, *tmp; + + DL_FOREACH_SAFE( _mouseDelegates, entry, tmp ) { + if ( entry->flags & kCCImplementsRightMouseUp ) { + void *swallows = [entry->delegate performSelector:@selector(ccRightMouseUp:) withObject:event]; + if( swallows ) + break; + } + } + } +} + +// +// Mouse Other +// +- (void)otherMouseDown:(NSEvent *)event +{ + if( _dispatchEvents ) { + tListEntry *entry, *tmp; + + DL_FOREACH_SAFE( _mouseDelegates, entry, tmp ) { + if ( entry->flags & kCCImplementsOtherMouseDown ) { + void *swallows = [entry->delegate performSelector:@selector(ccOtherMouseDown:) withObject:event]; + if( swallows ) + break; + } + } + } +} + +- (void)otherMouseDragged:(NSEvent *)event +{ + if( _dispatchEvents ) { + tListEntry *entry, *tmp; + + DL_FOREACH_SAFE( _mouseDelegates, entry, tmp ) { + if ( entry->flags & kCCImplementsOtherMouseDragged ) { + void *swallows = [entry->delegate performSelector:@selector(ccOtherMouseDragged:) withObject:event]; + if( swallows ) + break; + } + } + } +} + +- (void)otherMouseUp:(NSEvent *)event +{ + if( _dispatchEvents ) { + tListEntry *entry, *tmp; + + DL_FOREACH_SAFE( _mouseDelegates, entry, tmp ) { + if ( entry->flags & kCCImplementsOtherMouseUp ) { + void *swallows = [entry->delegate performSelector:@selector(ccOtherMouseUp:) withObject:event]; + if( swallows ) + break; + } + } + } +} + +// +// Scroll Wheel +// +- (void)scrollWheel:(NSEvent *)event +{ + if( _dispatchEvents ) { + tListEntry *entry, *tmp; + + DL_FOREACH_SAFE( _mouseDelegates, entry, tmp ) { + if ( entry->flags & kCCImplementsScrollWheel ) { + void *swallows = [entry->delegate performSelector:@selector(ccScrollWheel:) withObject:event]; + if( swallows ) + break; + } + } + } +} + +// +// Mouse enter / exit +- (void)mouseExited:(NSEvent *)event +{ + if( _dispatchEvents ) { + tListEntry *entry, *tmp; + + DL_FOREACH_SAFE( _mouseDelegates, entry, tmp ) { + if ( entry->flags & kCCImplementsMouseExited) { + void *swallows = [entry->delegate performSelector:@selector(ccMouseExited:) withObject:event]; + if( swallows ) + break; + } + } + } +} + +- (void)mouseEntered:(NSEvent *)event +{ + if( _dispatchEvents ) { + tListEntry *entry, *tmp; + + DL_FOREACH_SAFE( _mouseDelegates, entry, tmp ) { + if ( entry->flags & kCCImplementsMouseEntered) { + void *swallows = [entry->delegate performSelector:@selector(ccMouseEntered:) withObject:event]; + if( swallows ) + break; + } + } + } +} + + +#pragma mark CCEventDispatcher - Keyboard events + +// Keyboard events +- (void)keyDown:(NSEvent *)event +{ + if( _dispatchEvents ) { + tListEntry *entry, *tmp; + + DL_FOREACH_SAFE( _keyboardDelegates, entry, tmp ) { + if ( entry->flags & kCCImplementsKeyDown ) { + void *swallows = [entry->delegate performSelector:@selector(ccKeyDown:) withObject:event]; + if( swallows ) + break; + } + } + } +} + +- (void)keyUp:(NSEvent *)event +{ + if( _dispatchEvents ) { + tListEntry *entry, *tmp; + + DL_FOREACH_SAFE( _keyboardDelegates, entry, tmp ) { + if ( entry->flags & kCCImplementsKeyUp ) { + void *swallows = [entry->delegate performSelector:@selector(ccKeyUp:) withObject:event]; + if( swallows ) + break; + } + } + } +} + +- (void)flagsChanged:(NSEvent *)event +{ + if( _dispatchEvents ) { + tListEntry *entry, *tmp; + + DL_FOREACH_SAFE( _keyboardDelegates, entry, tmp ) { + if ( entry->flags & kCCImplementsFlagsChanged ) { + void *swallows = [entry->delegate performSelector:@selector(ccFlagsChanged:) withObject:event]; + if( swallows ) + break; + } + } + } +} + + +#pragma mark CCEventDispatcher - Touch events + +- (void)touchesBeganWithEvent:(NSEvent *)event +{ + if( _dispatchEvents ) { + tListEntry *entry, *tmp; + + DL_FOREACH_SAFE( _touchDelegates, entry, tmp ) { + if ( entry->flags & kCCImplementsTouchesBegan) { + void *swallows = [entry->delegate performSelector:@selector(ccTouchesBeganWithEvent:) withObject:event]; + if( swallows ) + break; + } + } + } +} + +- (void)touchesMovedWithEvent:(NSEvent *)event +{ + if( _dispatchEvents ) { + tListEntry *entry, *tmp; + + DL_FOREACH_SAFE( _touchDelegates, entry, tmp ) { + if ( entry->flags & kCCImplementsTouchesMoved) { + void *swallows = [entry->delegate performSelector:@selector(ccTouchesMovedWithEvent:) withObject:event]; + if( swallows ) + break; + } + } + } +} + +- (void)touchesEndedWithEvent:(NSEvent *)event +{ + if( _dispatchEvents ) { + tListEntry *entry, *tmp; + + DL_FOREACH_SAFE( _touchDelegates, entry, tmp ) { + if ( entry->flags & kCCImplementsTouchesEnded) { + void *swallows = [entry->delegate performSelector:@selector(ccTouchesEndedWithEvent:) withObject:event]; + if( swallows ) + break; + } + } + } +} + +- (void)touchesCancelledWithEvent:(NSEvent *)event +{ + if( _dispatchEvents ) { + tListEntry *entry, *tmp; + + DL_FOREACH_SAFE( _touchDelegates, entry, tmp ) { + if ( entry->flags & kCCImplementsTouchesCancelled) { + void *swallows = [entry->delegate performSelector:@selector(ccTouchesCancelledWithEvent:) withObject:event]; + if( swallows ) + break; + } + } + } +} + +#pragma mark CCEventDispatcher - Gesture events + +- (void)beginGestureWithEvent:(NSEvent *)event +{ + if( _dispatchEvents ) { + tListEntry *entry, *tmp; + + DL_FOREACH_SAFE( _gestureDelegates, entry, tmp ) { + if ( entry->flags & kCCImplementsBeginGestureWithEvent) { + void *swallows = [entry->delegate performSelector:@selector(ccBeginGestureWithEvent:) withObject:event]; + if( swallows ) + break; + } + } + } +} + +- (void)magnifyWithEvent:(NSEvent *)event +{ + if( _dispatchEvents ) { + tListEntry *entry, *tmp; + + DL_FOREACH_SAFE( _gestureDelegates, entry, tmp ) { + if ( entry->flags & kCCImplementsMagnifyWithEvent) { + void *swallows = [entry->delegate performSelector:@selector(ccMagnifyWithEvent:) withObject:event]; + if( swallows ) + break; + } + } + } +} + +- (void)smartMagnifyWithEvent:(NSEvent *)event +{ + if( _dispatchEvents ) { + tListEntry *entry, *tmp; + + DL_FOREACH_SAFE( _gestureDelegates, entry, tmp ) { + if ( entry->flags & kCCImplementsSmartMagnifyWithEvent) { + void *swallows = [entry->delegate performSelector:@selector(ccSmartMagnifyWithEvent:) withObject:event]; + if( swallows ) + break; + } + } + } +} + +- (void)rotateWithEvent:(NSEvent *)event +{ + if( _dispatchEvents ) { + tListEntry *entry, *tmp; + + DL_FOREACH_SAFE( _gestureDelegates, entry, tmp ) { + if ( entry->flags & kCCImplementsRotateWithEvent) { + void *swallows = [entry->delegate performSelector:@selector(ccRotateWithEvent:) withObject:event]; + if( swallows ) + break; + } + } + } +} + +- (void)swipeWithEvent:(NSEvent *)event +{ + if( _dispatchEvents ) { + tListEntry *entry, *tmp; + + DL_FOREACH_SAFE( _gestureDelegates, entry, tmp ) { + if ( entry->flags & kCCImplementsSwipeWithEvent) { + void *swallows = [entry->delegate performSelector:@selector(ccSwipeWithEvent:) withObject:event]; + if( swallows ) + break; + } + } + } +} + +- (void)endGestureWithEvent:(NSEvent *)event +{ + if( _dispatchEvents ) { + tListEntry *entry, *tmp; + + DL_FOREACH_SAFE( _gestureDelegates, entry, tmp ) { + if ( entry->flags & kCCImplementsEndGestureWithEvent) { + void *swallows = [entry->delegate performSelector:@selector(ccEndGestureWithEvent:) withObject:event]; + if( swallows ) + break; + } + } + } +} + +#pragma mark CCEventDispatcher - Dispatch + +- (void)dispatchEvent:(CCEventObject*)e +{ + @synchronized(self) + { + NSEvent *event = e->event; + SEL selector = e->selector; + + // Dispatch events + if( _dispatchEvents ) { + _locked = YES; + [self performSelector:selector onThread:[[CCDirector sharedDirector] runningThread] withObject:event waitUntilDone:YES]; + _locked = NO; + } + + + [event release]; + + // FIRST: Remove possible delegates + tListDeletedEntry *dEntry, *tTmp; + DL_FOREACH_SAFE( _delegatesToBeRemoved , dEntry, tTmp ) { + + [self removeDelegate:dEntry->delegate fromList:dEntry->listToBeDeleted]; + + DL_DELETE( _delegatesToBeRemoved, dEntry ); + [dEntry->delegate release]; + free(dEntry); + } + + // LATER: Add possible delegates + tListAddedEntry *entry, *tmp; + + DL_FOREACH_SAFE( _delegatesToBeAdded, entry, tmp ) { + + [self addDelegate:entry->delegate priority:entry->priority flags:entry->flags list:entry->listToBeAdded]; + + DL_DELETE( _delegatesToBeAdded, entry ); + [entry->delegate release]; + free(entry); + } + + } +} + +@end + +#endif // __CC_PLATFORM_MAC diff --git "a/21451198\345\215\242\350\266\205/project5/MyPlane/libs/cocos2d/Platforms/Mac/CCGLView.h" "b/21451198\345\215\242\350\266\205/project5/MyPlane/libs/cocos2d/Platforms/Mac/CCGLView.h" new file mode 100644 index 00000000..85b9e862 --- /dev/null +++ "b/21451198\345\215\242\350\266\205/project5/MyPlane/libs/cocos2d/Platforms/Mac/CCGLView.h" @@ -0,0 +1,103 @@ +/* + * cocos2d for iPhone: http://www.cocos2d-iphone.org + * + * Copyright (c) 2010 Ricardo Quesada + * Copyright (c) 2011 Zynga Inc. + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + * THE SOFTWARE. + */ + +// Only compile this code on Mac. These files should not be included on your iOS project. +// But in case they are included, it won't be compiled. +#import "../../ccMacros.h" +#ifdef __CC_PLATFORM_MAC + +#import + +#import "../../ccConfig.h" + +//PROTOCOLS: + +@protocol CCEventDelegate +// Mouse +- (void)mouseDown:(NSEvent *)theEvent; +- (void)mouseUp:(NSEvent *)theEvent; +- (void)mouseMoved:(NSEvent *)theEvent; +- (void)mouseDragged:(NSEvent *)theEvent; +- (void)rightMouseDown:(NSEvent*)event; +- (void)rightMouseDragged:(NSEvent*)event; +- (void)rightMouseUp:(NSEvent*)event; +- (void)otherMouseDown:(NSEvent*)event; +- (void)otherMouseDragged:(NSEvent*)event; +- (void)otherMouseUp:(NSEvent*)event; +- (void)scrollWheel:(NSEvent *)theEvent; +- (void)mouseEntered:(NSEvent *)theEvent; +- (void)mouseExited:(NSEvent *)theEvent; + + +// Keyboard +- (void)keyDown:(NSEvent *)theEvent; +- (void)keyUp:(NSEvent *)theEvent; +- (void)flagsChanged:(NSEvent *)theEvent; + +// Touches +- (void)touchesBeganWithEvent:(NSEvent *)event; +- (void)touchesMovedWithEvent:(NSEvent *)event; +- (void)touchesEndedWithEvent:(NSEvent *)event; +- (void)touchesCancelledWithEvent:(NSEvent *)event; + +// Gestures +- (void)beginGestureWithEvent:(NSEvent *)event; +- (void)magnifyWithEvent:(NSEvent *)event; +- (void)smartMagnifyWithEvent:(NSEvent *)event; +- (void)rotateWithEvent:(NSEvent *)event; +- (void)swipeWithEvent:(NSEvent *)event; +- (void)endGestureWithEvent:(NSEvent *)event; + +@end + +/** CCGLView + + Only available for Mac OS X + */ +@interface CCGLView : NSOpenGLView { + id _eventDelegate; +} + +/** Event delegate */ +@property (nonatomic, readwrite, assign) id eventDelegate; + +/** initializes the CCGLView with a frame rect and an OpenGL context */ +- (id) initWithFrame:(NSRect)frameRect shareContext:(NSOpenGLContext*)context; + +/** uses and locks the OpenGL context */ +-(void) lockOpenGLContext; + +/** unlocks the openGL context */ +-(void) unlockOpenGLContext; + +/** returns the depth format of the view in BPP */ +- (NSUInteger) depthFormat; + +// private ++(void) load_; +@end + +#endif // __CC_PLATFORM_MAC + diff --git "a/21451198\345\215\242\350\266\205/project5/MyPlane/libs/cocos2d/Platforms/Mac/CCGLView.m" "b/21451198\345\215\242\350\266\205/project5/MyPlane/libs/cocos2d/Platforms/Mac/CCGLView.m" new file mode 100644 index 00000000..fd4cc69d --- /dev/null +++ "b/21451198\345\215\242\350\266\205/project5/MyPlane/libs/cocos2d/Platforms/Mac/CCGLView.m" @@ -0,0 +1,325 @@ +/* + * cocos2d for iPhone: http://www.cocos2d-iphone.org + * + * Copyright (c) 2010 Ricardo Quesada + * Copyright (c) 2011 Zynga Inc. + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + * THE SOFTWARE. + */ + +/* + * Idea of subclassing NSOpenGLView was taken from "TextureUpload" Apple's sample + */ + +// Only compile this code on Mac. These files should not be included on your iOS project. +// But in case they are included, it won't be compiled. +#import "../../ccMacros.h" +#ifdef __CC_PLATFORM_MAC + +#import "../../Platforms/CCGL.h" +#import "CCGLView.h" +#import "CCDirectorMac.h" +#import "CCEventDispatcher.h" +#import "../../ccConfig.h" +#import "../../ccMacros.h" + + +@implementation CCGLView + +@synthesize eventDelegate = _eventDelegate; + ++(void) load_ +{ + CCLOG(@"%@ loaded", self); +} + +- (id) initWithFrame:(NSRect)frameRect +{ + self = [self initWithFrame:frameRect shareContext:nil]; + return self; +} + +- (id) initWithFrame:(NSRect)frameRect shareContext:(NSOpenGLContext*)context +{ + NSOpenGLPixelFormatAttribute attribs[] = + { +// NSOpenGLPFAAccelerated, +// NSOpenGLPFANoRecovery, + NSOpenGLPFADoubleBuffer, + NSOpenGLPFADepthSize, 24, + +#if 0 + // Must specify the 3.2 Core Profile to use OpenGL 3.2 + NSOpenGLPFAOpenGLProfile, + NSOpenGLProfileVersion3_2Core, +#endif + + 0 + }; + + NSOpenGLPixelFormat *pixelFormat = [[NSOpenGLPixelFormat alloc] initWithAttributes:attribs]; + + if (!pixelFormat) + CCLOG(@"No OpenGL pixel format"); + + if( (self = [super initWithFrame:frameRect pixelFormat:[pixelFormat autorelease]]) ) { + + if( context ) + [self setOpenGLContext:context]; + + // event delegate + _eventDelegate = nil; + } + + return self; +} + +- (void) update +{ + // XXX: Should I do something here ? + [super update]; +} + +- (void) prepareOpenGL +{ + // XXX: Initialize OpenGL context + + [super prepareOpenGL]; + + // Make this openGL context current to the thread + // (i.e. all openGL on this thread calls will go to this context) + [[self openGLContext] makeCurrentContext]; + + // Synchronize buffer swaps with vertical refresh rate + GLint swapInt = 1; + [[self openGLContext] setValues:&swapInt forParameter:NSOpenGLCPSwapInterval]; + +// GLint order = -1; +// [[self openGLContext] setValues:&order forParameter:NSOpenGLCPSurfaceOrder]; +} + +- (NSUInteger) depthFormat +{ + return 24; +} + +- (void) reshape +{ + // We draw on a secondary thread through the display link + // When resizing the view, -reshape is called automatically on the main thread + // Add a mutex around to avoid the threads accessing the context simultaneously when resizing + + [self lockOpenGLContext]; + + NSRect rect = [self bounds]; + + CCDirector *director = [CCDirector sharedDirector]; + [director reshapeProjection: NSSizeToCGSize(rect.size) ]; + + // avoid flicker + // Only draw if there is something to draw, otherwise it actually creates a flicker of the current glClearColor + if(director.runningScene){ + [director drawScene]; + } +// [self setNeedsDisplay:YES]; + + [self unlockOpenGLContext]; +} + + +-(void) lockOpenGLContext +{ + NSOpenGLContext *glContext = [self openGLContext]; + NSAssert( glContext, @"FATAL: could not get openGL context"); + + [glContext makeCurrentContext]; + CGLLockContext([glContext CGLContextObj]); +} + +-(void) unlockOpenGLContext +{ + NSOpenGLContext *glContext = [self openGLContext]; + NSAssert( glContext, @"FATAL: could not get openGL context"); + + CGLUnlockContext([glContext CGLContextObj]); +} + +- (void) dealloc +{ + CCLOGINFO(@"cocos2d: deallocing %@", self); + + [super dealloc]; +} + +#define DISPATCH_EVENT(__event__, __selector__) \ + id obj = _eventDelegate; \ + CCEventObject *event = [[CCEventObject alloc] init]; \ + event->event = [__event__ retain]; \ + event->selector = __selector__; \ + [obj performSelector:@selector(dispatchEvent:) \ + onThread:[[CCDirector sharedDirector] runningThread] \ + withObject:event \ + waitUntilDone:NO]; \ + [event release]; + +#pragma mark CCGLView - Mouse events + +- (void)mouseDown:(NSEvent *)theEvent +{ + DISPATCH_EVENT(theEvent, _cmd); +} + +- (void)mouseMoved:(NSEvent *)theEvent +{ + DISPATCH_EVENT(theEvent, _cmd); +} + +- (void)mouseDragged:(NSEvent *)theEvent +{ + DISPATCH_EVENT(theEvent, _cmd); +} + +- (void)mouseUp:(NSEvent *)theEvent +{ + DISPATCH_EVENT(theEvent, _cmd); +} + +- (void)rightMouseDown:(NSEvent *)theEvent { + DISPATCH_EVENT(theEvent, _cmd); +} + +- (void)rightMouseDragged:(NSEvent *)theEvent { + DISPATCH_EVENT(theEvent, _cmd); +} + +- (void)rightMouseUp:(NSEvent *)theEvent { + DISPATCH_EVENT(theEvent, _cmd); +} + +- (void)otherMouseDown:(NSEvent *)theEvent { + DISPATCH_EVENT(theEvent, _cmd); +} + +- (void)otherMouseDragged:(NSEvent *)theEvent { + DISPATCH_EVENT(theEvent, _cmd); +} + +- (void)otherMouseUp:(NSEvent *)theEvent { + DISPATCH_EVENT(theEvent, _cmd); +} + +- (void)mouseEntered:(NSEvent *)theEvent { + DISPATCH_EVENT(theEvent, _cmd); +} + +- (void)mouseExited:(NSEvent *)theEvent { + DISPATCH_EVENT(theEvent, _cmd); +} + +-(void) scrollWheel:(NSEvent *)theEvent { + DISPATCH_EVENT(theEvent, _cmd); +} + +#pragma mark CCGLView - Key events + +-(BOOL) becomeFirstResponder +{ + return YES; +} + +-(BOOL) acceptsFirstResponder +{ + return YES; +} + +-(BOOL) resignFirstResponder +{ + return YES; +} + +- (void)keyDown:(NSEvent *)theEvent +{ + DISPATCH_EVENT(theEvent, _cmd); +} + +- (void)keyUp:(NSEvent *)theEvent +{ + DISPATCH_EVENT(theEvent, _cmd); +} + +- (void)flagsChanged:(NSEvent *)theEvent +{ + DISPATCH_EVENT(theEvent, _cmd); +} + +#pragma mark CCGLView - Touch events +- (void)touchesBeganWithEvent:(NSEvent *)theEvent +{ + DISPATCH_EVENT(theEvent, _cmd); +} + +- (void)touchesMovedWithEvent:(NSEvent *)theEvent +{ + DISPATCH_EVENT(theEvent, _cmd); +} + +- (void)touchesEndedWithEvent:(NSEvent *)theEvent +{ + DISPATCH_EVENT(theEvent, _cmd); +} + +- (void)touchesCancelledWithEvent:(NSEvent *)theEvent +{ + DISPATCH_EVENT(theEvent, _cmd); +} + +#pragma mark CCGLView - Gesture events +- (void)beginGestureWithEvent:(NSEvent *)theEvent +{ + DISPATCH_EVENT(theEvent, _cmd); +} + +- (void)magnifyWithEvent:(NSEvent *)theEvent +{ + DISPATCH_EVENT(theEvent, _cmd); +} + +- (void)smartMagnifyWithEvent:(NSEvent *)theEvent +{ + DISPATCH_EVENT(theEvent, _cmd); +} + +- (void)rotateWithEvent:(NSEvent *)theEvent +{ + DISPATCH_EVENT(theEvent, _cmd); +} + +- (void)swipeWithEvent:(NSEvent *)theEvent +{ + DISPATCH_EVENT(theEvent, _cmd); +} + +- (void)endGestureWithEvent:(NSEvent *)theEvent +{ + DISPATCH_EVENT(theEvent, _cmd); +} + +@end + +#endif // __CC_PLATFORM_MAC diff --git "a/21451198\345\215\242\350\266\205/project5/MyPlane/libs/cocos2d/Platforms/Mac/CCWindow.h" "b/21451198\345\215\242\350\266\205/project5/MyPlane/libs/cocos2d/Platforms/Mac/CCWindow.h" new file mode 100644 index 00000000..7f37d4dc --- /dev/null +++ "b/21451198\345\215\242\350\266\205/project5/MyPlane/libs/cocos2d/Platforms/Mac/CCWindow.h" @@ -0,0 +1,41 @@ +/* + * cocos2d for iPhone: http://www.cocos2d-iphone.org + * + * Copyright (c) 2010 Ricardo Quesada + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + * THE SOFTWARE. + */ + +// Only compile this code on Mac. These files should not be included on your iOS project. +// But in case they are included, it won't be compiled. +#import "../../ccMacros.h" +#ifdef __CC_PLATFORM_MAC + +#import + + +@interface CCWindow : NSWindow +{ +} +- (id) initWithFrame:(NSRect)frame fullscreen:(BOOL)fullscreen; + +@end + + +#endif // __CC_PLATFORM_MAC