タッチで線のスプライトを描画し、それらの線をタッチで操作しようとしています。線画はフォーラム リンク: cocos2d フォーラムに基づいています。
操作には、線のドラッグと回転が含まれます。ドラッグは中央領域に触れたときだけで、うまく機能しています。
回転について、私がする必要があるのは、タッチが終点領域のいずれかにある場合、タッチの移動に合わせてもう一方の端を固定したまま、(長さを変更せずに) 線を回転させる必要があることです。
以下は、私がこれまでに行ったことです..
#import <GameKit/GameKit.h>
// When you import this file, you import all the cocos2d classes
#import "cocos2d.h"
// HelloWorldLayer
@interface HelloWorldLayer : CCLayer <GKAchievementViewControllerDelegate, GKLeaderboardViewControllerDelegate>
{
CGPoint lastTouchPoint;
CCSprite *line;
CCSprite *selectedSprite;
CGFloat rotation;
NSMutableArray *pointLoader;
NSMutableArray *startPointLoader;
BOOL moved;
BOOL doubleTap;
BOOL touchedTop;
BOOL touchedBottom;
}
// returns a CCScene that contains the HelloWorldLayer as the only child
+(CCScene *) scene;
@end
実装ファイルは次のとおりです。
#import "HelloWorldLayer.h"
#import "CCTouchDispatcher.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;
}
-(id) init
{
// always call "super" init
// Apple recommends to re-assign "self" with the "super's" return value
if( (self=[super init]) ) {
// create and initialize our seeker sprite, and add it to this layer
lastTouchPoint = ccp(-1.0f,-1.0f);
pointLoader = [[NSMutableArray alloc]init];
startPointLoader = [[NSMutableArray alloc]init];
self.isTouchEnabled = YES;
[[CCDirector sharedDirector] setDisplayStats:NO];
}
return self;
}
-(void) registerWithTouchDispatcher{
[[[CCDirector sharedDirector] touchDispatcher] addTargetedDelegate:self priority:0 swallowsTouches:YES];
}
-(BOOL)ccTouchBegan:(UITouch *)touch withEvent:(UIEvent *)event{
line = [CCSprite spriteWithFile:@"list.png"];
if( touch ) {
CGPoint location = [touch locationInView: [touch view]];
location = [[CCDirector sharedDirector] convertToGL:location];
if ([pointLoader count] != 0) {
[self selectSpriteOnTouch:location];
}
//
if( CGPointEqualToPoint(lastTouchPoint, ccp(-1.0f,-1.0f) ) ){
lastTouchPoint = ccp(location.x, location.y);
[startPointLoader addObject:NSStringFromCGPoint(lastTouchPoint)];
}
}
return YES;
}
-(void)ccTouchMoved:(UITouch *)touch withEvent:(UIEvent *)event{
if (selectedSprite) {
CGRect firstRect = CGRectMake(selectedSprite.boundingBox.origin.x, selectedSprite.boundingBox.origin.y, selectedSprite.boundingBox.size.width/3, selectedSprite.boundingBox.size.height);
CGRect secondRect = CGRectMake(selectedSprite.boundingBox.origin.x+(2*selectedSprite.boundingBox.size.width/3), selectedSprite.boundingBox.origin.y, selectedSprite.boundingBox.size.width/3, selectedSprite.boundingBox.size.height);
CGPoint touchLocation = [touch locationInView:[touch view]];
touchLocation = [[CCDirector sharedDirector] convertToGL:touchLocation];
touchLocation = [self convertTouchToNodeSpace:touch];
CGPoint oldTouchLocation = [touch previousLocationInView:touch.view];
oldTouchLocation = [[CCDirector sharedDirector] convertToGL:oldTouchLocation];
oldTouchLocation = [self convertToNodeSpace:oldTouchLocation];
if (CGRectContainsPoint(firstRect, touchLocation)) {
NSLog(@"Touched top");
//Code to rotate when clicking on top region of line
touchedTop = YES;
lastTouchPoint = ccp(-1.0f,-1.0f);
}
else if (CGRectContainsPoint(secondRect, touchLocation)){
NSLog(@"Touched bottom");
touchedBottom = YES;
//Code to rotate when clicking on bottom region of line
lastTouchPoint = ccp(-1.0f,-1.0f);
}
else{
CGPoint translation = ccpSub(touchLocation, oldTouchLocation);
[self Translation:translation];
lastTouchPoint = ccp(-1.0f,-1.0f);
}
}
else{
moved = YES;
}
}
-(void)ccTouchEnded:(UITouch *)touch withEvent:(UIEvent *)event{
//If there was a touch move..
if (moved==YES) {
line = [CCSprite spriteWithFile:@"list.png"];
CGPoint location = [touch locationInView: [touch view]];
location = [[CCDirector sharedDirector] convertToGL:location];
CGPoint endPoint = ccp(location.x, location.y);
CGPoint diff = ccpSub(lastTouchPoint, endPoint);
float rads = atan2f( diff.y, diff.x);
float degs = -CC_RADIANS_TO_DEGREES(rads);
float dist = ccpDistance(lastTouchPoint, endPoint);
[line setAnchorPoint:ccp(0.0f, 0.5f)];
[line setPosition:endPoint];
[line setScaleX:dist/line.boundingBox.size.width];
[line setRotation: degs];
[pointLoader addObject:line];
[self addChild:line z:0];
moved = NO;
lastTouchPoint = ccp(-1.0f,-1.0f);
CCLOG(@" line location is (%f,%f)",line.position.x, line.position.y);
CCLOG(@"lastTouchPoint is now(%f,%f), location is (%f,%f)", lastTouchPoint.x, lastTouchPoint.y, location.x, location.y);
}
else if (touchedTop ==YES) {
[selectedSprite.parent removeChild:selectedSprite cleanup:YES];
line = [CCSprite spriteWithFile:@"list.png"];
CGPoint location = [touch locationInView: [touch view]];
location = [[CCDirector sharedDirector] convertToGL:location];
CGPoint endPoint = ccp(location.x, location.y);
CGPoint diff = ccpSub(selectedSprite.position, endPoint);
float rads = atan2f( diff.y, diff.x);
float degs = -CC_RADIANS_TO_DEGREES(rads);
float dist = ccpDistance(selectedSprite.position, endPoint);
[line setAnchorPoint:ccp(0.0f, 0.5f)];
[line setPosition:endPoint];
[line setScaleX:dist/line.boundingBox.size.width];
[line setRotation: degs];
[pointLoader addObject:line];
[self addChild:line z:0];
touchedTop = NO;
lastTouchPoint = ccp(-1.0f,-1.0f);
}
else if (touchedBottom ==YES) {
[selectedSprite.parent removeChild:selectedSprite cleanup:YES];
line = [CCSprite spriteWithFile:@"list.png"];
CGPoint location = [touch locationInView: [touch view]];
location = [[CCDirector sharedDirector] convertToGL:location];
CGPoint endPoint = ccp(location.x, location.y);
CGPoint diff = ccpSub(selectedSprite.position, endPoint);
float rads = atan2f( diff.y, diff.x);
float degs = -CC_RADIANS_TO_DEGREES(rads);
float dist = ccpDistance(selectedSprite.position, endPoint);
[line setAnchorPoint:ccp(0.0f, 0.5f)];
[line setPosition:endPoint];
[line setScaleX:dist/line.boundingBox.size.width];
[line setRotation: degs];
[pointLoader addObject:line];
[self addChild:line z:0];
touchedBottom = NO;
lastTouchPoint = ccp(-1.0f,-1.0f);
}
//
else if ([touch tapCount]==3){ //code to clear all screen
[self removeAllChildrenWithCleanup:YES];
rotatorSprite = nil;
selectedSprite = nil;
[pointLoader removeAllObjects];
NSLog(@"Screen Cleared");
lastTouchPoint = ccp(-1.0f,-1.0f);
}
}
- (void)selectSpriteOnTouch:(CGPoint)touchLocation {
// for (CCSprite *sprite in pointLoader) {
// if (CGRectContainsPoint(sprite.boundingBox, touchLocation)) {
// NSLog(@"sprite was touched");
//// [self removeChild:sprite cleanup:YES];
// [sprite.parent removeChild:sprite cleanup:YES];
//// break; // putting break does not solve the multiple deletion problem... it only disables the deletion
// NSLog(@"sprite moving");
//
//
// }
// }
// lastTouchPoint = ccp(-1.0f,-1.0f);
if (doubleTap == YES) {
id rotate = [CCRotateBy actionWithDuration:10 angle:360];
for(CCSprite *sprite in pointLoader){
if(CGRectContainsPoint(sprite.boundingBox, touchLocation)){
rotatorSprite = sprite;
[rotatorSprite setAnchorPoint:ccp(0.0f, 0.5f)];
[rotatorSprite runAction:rotate];
break;
}
}
doubleTap = NO;
lastTouchPoint = ccp(-1.0f,-1.0f);
}
else{
CCSprite * newSprite = nil;
for (CCSprite *sprite in pointLoader) {
// CGRect rect = CGRectMake(sprite.position.x-(sprite.contentSize.width/2), sprite.position.y-(sprite.contentSize.height/2),
// sprite.contentSize.width, sprite.contentSize.height);
// if (CGRectContainsPoint(rect, touchLocation)) {
if (CGRectContainsPoint(sprite.boundingBox, touchLocation)) {
newSprite = sprite;
NSLog(@"Sprite was Touched");
CCLOG(@" newSprite location is (%f,%f)",newSprite.position.x, newSprite.position.y);
break;
}
}
if (newSprite != selectedSprite) {
selectedSprite = newSprite;
}
}
}
- (void)Translation:(CGPoint)translation {
if (selectedSprite) {
CGPoint newPos = ccpAdd(selectedSprite.position, translation);
selectedSprite.position = newPos;
CCLOG(@" selectedSprite location is (%f,%f)",selectedSprite.position.x, selectedSprite.position.y);
}
lastTouchPoint = ccp(-1.0f,-1.0f);
}
// 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
回転は発生していますが、必要に応じてではなく、x 軸と y 軸に平行になると停止します。
回転の問題を解決するのを手伝ってください....
ありがとう