I am developing a cocos2d game. In that game I hace a character, and according to the touch positions on the caracter different actions should be triggered,How can i Implement this in my cocos2d game.
Is there any method to implement transparent button in cocos2d.
Thanks in advance
When you create a CCMenuItemSprite (a button), you assign it a sprite to use for display.
You can then change the appearance of the button by changing the opacity property of the sprite, or by making it not visible at all.
CCSprite *buttonSpr = [CCSprite spriteWithSpriteFrameName:#"spr.png"];
CCMenuItem *button = [CCMenuItemSprite itemFromNormalSprite:buttonSpr selectedSprite:buttonSpr target:self selector:#selector(buttonTapped:)];
//opacity
buttonSpr.opacity = 50;
//invisible
buttonSpr.visible = false;
I'm not entirely sure that I understand the question and more information would be helpful, but I'll answer it the best I can.
Assuming you have a character class I would implement checkTouchesBegan and do something like this:
-(BOOL) checkTouchesBegan: (CGPoint*) location
{
//conver the touch coordinates to fit your system
int converty = location->y-160;
int convertx = location->x-240;
//determine where the touch is in relation to the center of the character
float ydif = (1.0)*(converty - character_y);
float xdif = (1.0)*(convertx - character_x);
//determine the angle of the touch
float degrees = atan2f(xdif, ydif) * 57;
//determine the distance between the character and the touch
float squared = xdif*xdif + ydif*ydif;
//if the touch is above the character and within a certain distance
if(degrees >= 45 && degrees < 135 && sqrt(squared) < 100)
{
doSomething;
return YES;
}
//if the touch is below the character and within a certain distance
else if(degrees < -45 && degrees >= -135 && sqrt(squared) < 100)
{
doSomething;
return YES;
}
//if the touch is to the right of the character and within a certain distance
else if(degrees >= -45 && degrees < 45 && sqrt(squared) < 100)
{
doSomething;
return YES;
}
//if the touch is to the left of the character and within a certain distance
else if(sqrt(squared) < 100)
{
doSomething;
return YES;
}
return NO;
}
Hope this helps some!
Related
I added a -(void) detectTouch: (UIPanGestureRecognizer *) event for UIScrollView and detecting the angle on which user is moving his finger. My task is to scroll the UIScrollView horizontally only when user is moving the finger between 0 - 30 degrees (just to make sure he is drawing a horizontal straight line) otherwise I have to disable the UIScrollView scroll.
I am detecting the angle by drawing a triangle using the touch starting point and ending point.
Problem: I enabled the UIScrollView scroll when the angle is < 30 degrees but this is not working on the first time. Although I enabled scroll using scrollEnabled = YES it is working only when user is stopped touching the screen (taking the finger from the screen).
The following code I used to
- (void)viewDidLoad
{
[super viewDidLoad];
[self PanGesture:self.view callBack:#selector(detectTouch:) delegate:self];
incrementer = 0;
}
-(void) detectTouch: (UIPanGestureRecognizer *) event{
// Calculating point A on gesture starts
if(event.state == UIGestureRecognizerStateBegan){
pointA.x = fabs([event translationInView:event.view].x);
pointA.y = fabs([event translationInView:event.view].y);
NSLog(#"A: %f, %f", pointA.x, pointA.y);
}
incrementer += 1;
// Start calculating Point B, Point C on calling this function 3 times
if(incrementer >= 3){
// Calculating point C
pointC.x = fabs([event translationInView:event.view].x);
pointC.y = fabs([event translationInView:event.view].y);
NSLog(#"C: %f, %f", pointC.x, pointC.y);
// calculate pointB using A, C
pointB.x = fabs(pointC.x);
pointB.y = fabs(pointA.y);
NSLog(#"B: %f, %f", pointB.x, pointB.y);
float X = pointB.x - pointA.x;
float Y = pointC.y - pointB.y;
float angle = (atan(fabs(Y) / fabs(X)) * 180 / M_PI);
if(angle > 30){
// This disable is not working on while user is moving the finger
self.myScrollView.scrollEnabled = NO;
NSLog(#"UIScroll Disabled");
}else{
// This enable is not working on while user is moving the finger
self.myScrollView.scrollEnabled = YES;
NSLog(#"UIScroll Enabled");
}
incrementer = 0;
}
}
How can I enable UIScrollView scroll while user is moving the touch?
Since UIScrollView seems to accept scrolling only with a new touch after you set .scrollEnabled to YES, I would do the following:
set .scrollEnabled to NO
Track the touch (e. g. with touchesMoved::)
check whether you 30 degrees condition is met
use the movement to adjust UIScrollView.contentOffset
I m start learning game development. As a beginner i create one demo game in which one cannon hit bullets to the enemies (coming toward cannon from different direction).
Now i stuck on cannon sprite image rotation anywhere user touch on the screen or enemies. How i do that, My initial code as following,
void HelloWorld:: ccTouchesBegan(CCSet *touches, CCEvent * event)
{
CCSize winSize = CCDirector::sharedDirector()->getWinSize();
CCTouch* touch = (CCTouch*)( touches->anyObject() );
CCPoint location = touch->locationInView(touch->view());
location = CCDirector::sharedDirector()->convertToGL(location);
//Rotate cannon direction toward touch point
CCPoint diffPoint = ccpSub(_cannonImage->getPosition(), location);
float angleRadians = atanf((float)diffPoint.y/(float)diffPoint.x);
float angleOffset = CC_DEGREES_TO_RADIANS(180);
if(diffPoint.x < 0){
angleRadians += angleOffset;
}else{
angleRadians -= angleOffset;
}
CCLog("angle to be rotate = %f", angleRadians);
_cannonImage->runAction(CCRotateBy::actionWithDuration(0.1, angleRadians));
}
The code is written in cocos2d-x . I also accepting answer by someone who written in plain cocos2d.
Thanks
iHungry
The perfect answer as follows,
float HelloWorld::changingAngleAccordingToCoordinateSystem(CCPoint imageCenter, CCPoint touchLocation, float calculatedAngle){
//Consideration :- all Angles is in Degree
if((calculatedAngle >= 0 && calculatedAngle <= 90) || (calculatedAngle >= 90 && calculatedAngle <= 180)){
//Ist quardant
calculatedAngle = calculatedAngle;
}
else if(calculatedAngle < 0 && calculatedAngle >= -90){
//IInd quardant
calculatedAngle = 270 + (90 + calculatedAngle);
}
else if(calculatedAngle < -90 && calculatedAngle >= -180){
calculatedAngle = 180 + (180 + calculatedAngle);
}
return calculatedAngle;
}
//Rotate cannon direction toward touch point
float diff_X = touchLocation.x - myImage->getPosition().x;
float diff_Y = touchLocation.y - myImage->getPosition().y;
CCPoint diffPoint = CCPoint(diff_X, diff_Y);
float angleRadians = atan2f(diffPoint.y,diffPoint.x);
angleRadians = CC_RADIANS_TO_DEGREES(angleRadians);
angleRadians = HelloWorld::changingAngleAccordingToCoordinateSystem(myImage->getPosition(), touchLocation, angleRadians);
myImage->setRotation(-angleRadians);
i used this code to rotate my sprite. i Was moving the sprite according to my accelerometer reading.
float angleRadians =-accelX;
float angleDegrees = CC_RADIANS_TO_DEGREES(angleRadians);
objGlider->sprite_Glider.rotation = cocosAngle;
Check it. The reason of slow may be that you may be using CClog or NSLog in the code.
Here goes the complete code.
if(!boolPlayerDied)
{
static float prevX=0, prevY=0;
#define kFilterFactor 1.0f// don't use filter. the code is here just as an example
float accelX = (float) acceleration.x * kFilterFactor + (1- kFilterFactor)*prevX;
float accelY = (float) acceleration.y * kFilterFactor + (1- kFilterFactor)*prevY;
prevX = accelX;
prevY = accelY;
accelX = accelX-0.5;// Angle check fot tgfor the player to play
float angleRadians =-accelX;
float angleDegrees = CC_RADIANS_TO_DEGREES(angleRadians);
if(accelX>0)
{
cocosAngle = 1.1 * angleDegrees;
}
else
{
if(accelX<-0.5)
accelX=-0.5;
cocosAngle = 1.1 * angleDegrees;
}
objGlider->sprite_Glider.rotation = cocosAngle;
}
objGlider is the object of the class which creates glider sprite and sprite_Glider is the sprite used in glider class.
you can use rotation property with your sprite to be rotated. In cocos2Dx it might be setRotation.
First of all, replace
float angleRadians = atanf((float)diffPoint.y/(float)diffPoint.x);
float angleOffset = CC_DEGREES_TO_RADIANS(180);
if(diffPoint.x < 0){
angleRadians += angleOffset;
}else{
angleRadians -= angleOffset;
}
by
float angleRadians = atan2f(diffPoint.y, diffPoint.x);
Then it would be better to set rotation immediately (without actions) to process multiple frequent touches.
_cannonImage->setRotation(angleRadians);
Maybe you will need to adjust rotation like setRotation(-angleRadians) or setRotation(angleRadians+90) - it depends on your coordinate system.
I want to have a movable/scalable/rotable view inside another view. The inner view can go outside the outer view's frame but I want to keep part of it inside the outer one so the inner view isn't lost.
I simplified the problem in this xcode project https://github.com/nextorlg/Intersection.
If the inner view was only movable and scalable the problem would be already solved but when the inner view rotates this solution it is not good because the frame contains the view but it is not the view itself.
Every transformation performed to the inner view I use this function to validate the new view position, if it is not valid I revert the last transformation ( this is the movable view code https://github.com/nextorlg/Intersection/blob/master/intersec/MovableView.m )
-(BOOL) validInset {
CGRect outerLimit = CGRectMake(0, 0, self.superview.frame.size.width, self.superview.frame.size.height);
CGRect intersectionRect = CGRectIntersection(self.frame, outerLimit);
NSLog(#"self.frame:%f,%f,%f,%f", self.frame.origin.x, self.frame.origin.y, self.frame.size.width, self.frame.size.height);
NSLog(#"outer.frame:%f,%f,%f,%f", outerLimit.origin.x, outerLimit.origin.y, outerLimit.size.width, outerLimit.size.height);
NSLog(#"intersec.frame:%f,%f,%f,%f", intersectionRect.origin.x, intersectionRect.origin.y, intersectionRect.size.width, intersectionRect.size.height);
NSLog(#"========================");
if ( CGRectIsNull(intersectionRect) ||
intersectionRect.size.width < INSET ||
intersectionRect.size.height < INSET ) {
return NO;
}
else {
return YES;
}
}
The question is, how can I be sure the inner view it is not lost behind the outer view when the first is rotated some (45 for example) degrees and dragged to a corner?
One comment, I want to keep just some pixels inside the outer view because the inner view can be bigger (scaled) than the outer one.
I recommend you to download and run the project to understan better the problem, it is difficult to understand it just reading this.
Thank you!
As you stated, your method will only work fine when the inner view is not rotated.
The easiest method I am aware of for solving your problem is simply to test if the center or a vertex of one of the views is inside the other one.
-(BOOL) validInset {
// Get the vertices of A (outerLimit)
CGRect outerLimit = self.superview.bounds;
CGPoint pointA[] = {
CGPointMake(outerLimit.origin.x, outerLimit.origin.y ),
CGPointMake(outerLimit.size.width, outerLimit.origin.y ),
CGPointMake(outerLimit.size.width, outerLimit.size.height ),
CGPointMake(outerLimit.origin.x, outerLimit.size.height )};
// Adjust outerLimit's borders
pointA[0].x += INSET, pointA[0].y += INSET;
pointA[1].x -= INSET, pointA[1].y += INSET;
pointA[2].x -= INSET, pointA[2].y -= INSET;
pointA[3].x += INSET, pointA[3].y -= INSET;
// Get the vertices of B (innerView)
CGRect innerView = self.bounds;
CGPoint pointB[] = {
CGPointMake(innerView.origin.x, innerView.origin.y ),
CGPointMake(innerView.size.width, innerView.origin.y ),
CGPointMake(innerView.size.width, innerView.size.height ),
CGPointMake(innerView.origin.x, innerView.size.height )};
// Test if the center of B is inside A or vice versa
CGPoint center, converted;
center = CGPointMake(pointB[0].x + (pointB[1].x - pointB[0].x)/2, pointB[0].y + (pointB[2].y - pointB[0].y)/2);
if( converted = [self convertPoint:center toView:self.superview],
converted.x >= pointA[0].x &&
converted.x <= pointA[1].x &&
converted.y >= pointA[0].y &&
converted.y <= pointA[2].y ) return YES;
center = CGPointMake(pointA[0].x + (pointA[1].x - pointA[0].x)/2, pointA[0].y + (pointA[2].y - pointA[0].y)/2);
if( converted = [self convertPoint:center toView:self.superview],
converted.x >= pointA[0].x &&
converted.x <= pointA[1].x &&
converted.y >= pointA[0].y &&
converted.y <= pointA[2].y ) return YES;
// Test if vertices of B are inside A or vice versa
for (int i = 0; i < 4; i++) {
if( converted = [self convertPoint:pointB[i] toView:self.superview],
converted.x >= pointA[0].x &&
converted.x <= pointA[1].x &&
converted.y >= pointA[0].y &&
converted.y <= pointA[2].y ) return YES;
if( converted = [self.superview convertPoint:pointA[i] toView:self],
converted.x >= pointB[0].x &&
converted.x <= pointB[1].x &&
converted.y >= pointB[0].y &&
converted.y <= pointB[2].y ) return YES;
}
return NO;
}
This code will do the job for dealing with the transformations that you use in your example, but it is not a general purpose answer.
A non iphone-related answer to this question is found here.
And you can also read some background about rectangle and point intersection here.
edit:
For the transformations that can be applied to an UIView, to test the vertices and the center will be enough for most cases.
The two well-known exceptions are:
when h1 < h2/2 and w1/2 > w2 (or h2 < h1/2 and w2/2 > w1),
when 2w2 < h2/2 and r1 > w2 (or 2w1 < h1/2 and r2 > w1);
where:
r = the distance between the center of the UIView and a vertex;
w = the length of the shortest side of the UIView;
h = the length of the longest side of the UIView.
If you face one of these cases, you should use another method, like the one in the first link.
is there anyway we can do rotation of image in a pendulum effect in iphone using UIView Animation or CoreAnimation
Use CGAffineTransformRotate to rotate your UIImageView e.g.
yourImage.transform = CGAffineTransformRotate(CGAffineTransformIdentity, M_PI * (_angle/ 180.0));
Also, you'll need to set up the anchor point on your image, prior to rotating it, so that you can make it swing from the correct position. e.g.
yourImage.layer.anchorPoint = CGPointMake(0.5,0); // Set anchor to top middle.
Obviously, you'll need to set up a timer to adjust move the image and control the angle. You could do something like the following in a timer. (untested)
_angle = 45; // Set starting angle.
_direction = 1; // Set starting direction.
-(void) movePend
{
if(_direction == 45){
_direction = 1;
} else if(_direction == 180) {
_direction = 0;
}
_angle = (_direction) ? _angle-- : _angle++; // Determine which way to rotate.
yourImage.transform = CGAffineTransformRotate(CGAffineTransformIdentity, M_PI * (_angle/ 180.0));
}
I have this IBAction that is suppose to make a character onscreen jump, however when its called it just moves the character up once, then each call after that the character just moves down more and more. This function should just be called then the character would 'jump' up and then fall straight down off the screen since i havent put in any collision with the ground. ANy suggestions why this is happening? tim is the name of my UIImageView that holds the chracater, btw.
-(IBAction)Jump:(id)sender
{
int jumpSpeed = JumpSpeedLimit;
CGPoint newCenter = tim.center;
if(!mainJumping){
//then start jumping
mainJumping = TRUE;
jumpSpeed = JumpSpeedLimit*-1;
newCenter.x -= jumpSpeed;
tim.center = newCenter;
} else {
//then continue jumping if already in the air
//crazy math that I won't explain
if(jumpSpeed < 0){
jumpSpeed *= 1 - JumpSpeedLimit/75;
if(jumpSpeed > -JumpSpeedLimit/5){
jumpSpeed *= -1;
}
}
if(jumpSpeed > 0 && jumpSpeed <= JumpSpeedLimit){
jumpSpeed *= 1 + JumpSpeedLimit/50;
}
newCenter = tim.center;
newCenter.x -= jumpSpeed;
tim.center = newCenter;
/*
//if hits the floor, then stop jumping
if(tim.center.x >= 360 - tim.bounds.size.height){
mainJumping = FALSE;
newCenter = tim.center;
newCenter.x = 360 - tim.bounds.size.height;
tim.center = newCenter;
}*/
}
}
You are fundamentally designing this wrong. You want it to be that pressing the "jump" button sets some sort of flag, and then in your game engine code, process that flag.
Sounds like a job for CoreAnimation more than one for a repeated call to an IBAction. Create an animation path on which your view should move and add a timing function to give the gravity acceleration effect, something along the lines of the animation cookbook sample: http://developer.apple.com/documentation/GraphicsImaging/Conceptual/CoreAnimation_Cookbook/Articles/Timing.html#//apple_ref/doc/uid/TP40006077-SW1