I'm trying to move a UIImageView up and down while making it bigger. Now when I do those things separately it works like I thought it would, but when i combine them it looks really glitchy and like I wanted it to look.
Here is my code so you can copy it into Xcode and see what happens for yourself.
Add a UIImageView with whatever image you got in interface builder and add this code to the viewController.h:
IBOutlet UIImageView *bg1;
int steps;
float a;
And this to the viewController.m
#define kA 3
- (void)viewDidLoad {
[super viewDidLoad];
steps = 0;
a = kA;
[NSTimer scheduledTimerWithTimeInterval:.04 target:self selector:#selector(walk)
userInfo:nil repeats:YES];
}
-(void)resetA { // This function makes it possible for the UIImageView to move up and down
if (a > 0) a=-kA;
else a=kA;
steps++;
NSLog(#"%i", steps);
}
-(void)walk { // This function makes the UIImageView bigger and move up and down
if (a > 0) [bg1 setFrame:CGRectMake(0, 0, bg1.bounds.size.width+a,
bg1.bounds.size.height+a)];
else [bg1 setFrame:CGRectMake(0, 0, bg1.bounds.size.width-a,
bg1.bounds.size.height-a)];
[bg1 setCenter:CGPointMake(160, bg1.center.y+a)];
a *= 0.9;
if (a < 0.15 & a > 0 || a > -0.15 & a < 0) [self resetA];
}
Related
I want to move my UIView of size (x=50,y=50) in the boundary of simulator screen means rectangular without animation infinitely.
To moving view continuously in your simulator boundary you have to put logic there is no predefined method without animation. if you are using animation then below given link is useful. How to repeat animation from current state not from startingstate? or without animation the below code will help you.
And yes please note that **
pos
** is a object of CGPoint class and you don't have to allocate it simply declare in interface.
- (void)viewDidLoad
{
pos = v1.center;
NSLog(#"POSITION === %f",pos.x);
[NSTimer scheduledTimerWithTimeInterval:0.05
target:self
selector:#selector(rotateBoundary)
userInfo:nil
repeats:YES];
[super viewDidLoad];
//[self performSelector:#selector(rotateBoundary) withObject:self afterDelay:5.0];
// Do any additional setup after loading the view, typically from a nib.
}
-(void)rotateBoundary
{
if (pos.x>=20 && pos.x<=290 && pos.y==25)
{
NSLog(#"Top left to right.");
pos.x+=5;
v1.center = pos;
NSLog(#"pos.x === %f",pos.x);
}
if(pos.x >= 290 && pos.y<=430)
{
NSLog(#"Right top to down.");
pos.y+=5;
v1.center = pos;
NSLog(#"pos.y === %f",pos.y);
}
if(pos.y == 430 && pos.x>=20)
{
NSLog(#"Down right to left.");
pos.x-=5;
v1.center = pos;
NSLog(#"pos.x === %f",pos.x);
}
if (pos.x <= 20 && pos.y>=25)
{
NSLog(#"Down left to top.");
pos.y-=5;
v1.center = pos;
NSLog(#"pos.y === %f",pos.y);
}
}
I want to cut a sprite in 6 equivalent parts just with one image, a .png file which I found on the web, no with texturepacker, (the image below by example)
I can take other way, but I want to know if I can do that. any one haves idea?
I'll revise my answer if this isn't what you were asking about, but I think you are asking how to 'manually run an animation' using a spritesheet without a plist.
Here's one way. It would be better if you encapsulated this into it's own class, but this can push you in the right direction I think:
ManualAnimationTest.h
#interface ManualAnimationTest : CCLayer
{
CCSprite *animatedSprite;
int x,y;
float animatedSpriteWidth, animatedSpriteHeight;
int animatedSpriteColumns, animatedSpriteRows;
}
#end
ManualAnimationTest.m
#import "ManualAnimationTest.h"
#implementation ManualAnimationTest
-(id) init
{
if( (self=[super init]))
{
CGSize s = [CCDirector sharedDirector].winSize;
x = 0;
y = 0;
animatedSpriteColumns = 3;
animatedSpriteRows = 2;
animatedSpriteWidth = 95.0f;
animatedSpriteHeight = 125.0f;
animatedSprite = [CCSprite spriteWithFile:#"animal_animation.png" rect:CGRectMake(x * animatedSpriteWidth,y * animatedSpriteHeight,animatedSpriteWidth,animatedSpriteHeight)];
[self addChild:animatedSprite];
[animatedSprite setPosition:ccp(s.width / 2.0f, s.height / 2.0f)];
[self schedule:#selector(animateAnimatedSprite) interval:0.5f];
}
return self;
}
-(void) animateAnimatedSprite
{
[animatedSprite setTextureRect:CGRectMake(x * animatedSpriteWidth, y * animatedSpriteHeight, animatedSpriteWidth, animatedSpriteHeight)];
x +=1;
if(x > (animatedSpriteColumns - 1))
{
x = 0;
y +=1;
}
if(y > (animatedSpriteRows - 1))
{
y = 0;
}
}
#end
I want to have multiple images (in this case, basketballs) move around on the screen.
How can I create multiple balls with the same name? I have one ball which is already moving around. So all the other balls should use the same calculation with the same property name for bumping and stuff like that.
Can someone help me? I know Java well, but not Obj C.
EDIT:
ball.center = CGPointMake(ball.center.x + ballmovement.x, ball.center.y + ball movement.y);
if (ball.center.x > self.view.frame.size.width || ball.center.x < 0) {
ballmovement.x = -1* ballmovement.x;
}
if (ball.center.y > self.view.frame.size.height || ball.center.y < 0) {
ballmovement.y = -1* ballmovement.y;
This is my simple calculation. This code is in my loop method. this loop method is called by this code in my viewDidLoad method:
[NSTimer scheduledTimerWithTimeInterval:0.050 target:self selector:#selector(loop) userInfo:nil repeats:YES];
In the MainView .h file i wrote
BasketballView *ball;
new Balls are created by this code in my button action method:
for (int x = 0; x < numberOfBalls; x++)
{
ball = [[BasketballView alloc]initWithFrame:CGRectMake(arc4random()%100,arc4random()%100, 40, 40) andCustomProperty:#"my string" andAnotherProperty:100];
[self.view addSubview:ball];
}
When i run my application, only one ball is moving!
do you need more code?
thanks for your help
EDIT 2:
every ball is moving now, but they are not moving correctly .. here is what i did. i created a NSMuteableArray. i added this code in my Button action method:
[array addObject:ball];
after that, i added in the loop method some code. here is the new loop code that i have right now:
for (int i=0; i<array.count;i++){
ball = [array objectAtIndex:i];
ball.center = CGPointMake(ball.center.x + ballmovement.x, ball.center.y + ballmovement.y);
}
if (ball.center.x > self.view.frame.size.width || ball.center.x < 0) {
ballmovement.x = -1* ballmovement.x;
}
if (ball.center.y > self.view.frame.size.height || ball.center.y < 0) {
ballmovement.y = -1* ballmovement.y;
right now, every ball is changing direction when one ball hits the boarder. so all the other balls move like the this one ball. they ignore the boarders. only if this one ball hits the boarder, they change their direction.
if i put the code for the ball movement inside the for-loop, the balls change their direction everytime one of the balls hits the boarder. they are moving like crazy, because every .5 seconds a ball hits one of the boarders
I think what you looking for is a way to add a bunch of objects from the same class. To do this, I would suggest that you overwrite an UIImageView class. If you do that, you can add custom properties to the balls. See the example below:
In your header file, you would have the following:
#import <UIKit/UIKit.h>
#interface BasketBallView : UIImageView
#property (nonatomic, strong) NSString *customProperty;
#property (assign) NSInteger anotherProperty;
//custom init method if you want
- (id) initWithFrame:(CGRect)frame andCustomProperty:(NSString *)CustomProperty andAnotherProperty:(NSInteger)AnotherProperty;
-(void)startMovement;
#end
The implementation would be something like this:
#import "BasketBallView.h"
#implementation BasketBallView
- (id)initWithFrame:(CGRect)frame
{
self = [super initWithFrame:frame];
if (self) {
[self setImage:[UIImage imageNamed:#"your_bb_image.png"]];
}
return self;
}
-(id) initWithFrame:(CGRect)frame andCustomProperty:(NSString *)CustomProperty andAnotherProperty:(NSInteger)AnotherProperty
{
self = [self initWithFrame:frame];
if (self) {
self.customProperty = CustomProperty;
self.anotherProperty = AnotherProperty;
}
return self;
}
-(void)startMovement{
[NSTimer scheduledTimerWithTimeInterval:0.050 target:self selector:#selector(loop) userInfo:nil repeats:YES];
}
-(void)moveBall{
self.center = CGPointMake(self.center.x + ballmovement.x, self.center.y + ballmovement.y);
if (self.center.x > self.superview.frame.size.width || self.center.x < 0) {
ballmovement.x = -1* ballmovement.x;
}
if (self.center.y > self.superview.frame.size.height || self.center.y < 0) {
ballmovement.y = -1* ballmovement.y;
}
/*
// Only override drawRect: if you perform custom drawing.
// An empty implementation adversely affects performance during animation.
- (void)drawRect:(CGRect)rect
{
// Drawing code
}
*/
#end
To then use and access your object from your viewcontroller, do it as follows:
BasketBallView *bb = [[BasketBallView alloc]initWithFrame:CGRectMake(0, 0, 100, 100) andCustomProperty:#"my string" andAnotherProperty:100];
[self.view addSubview:bb];
You could, of course, throw the above lines of code into a loop, and add it multiple times to the view.
Edit:
If you want to add the BasketBallView to the view for the Interface Builder, you'll need to customize the initWithCoder method in the implementation file. In that method, you would similarly set your image, etc.
I would suggest that you don't add the BasketBallViews via the Interface Builder, however. Since you need a random number of balls, you need to add them from the code and use the method I outlined above. You would add them like this:
for(int i = 0; i < yourRandomNumber; i++){
BasketBallView *bb = [[BasketBallView alloc]initWithFrame:CGRectMake(0, 0, 100, 100) andCustomProperty:#"my string" andAnotherProperty:100];
[self.view addSubview:bb];
}
You can't add copies of views to another view, in other words, you can't create the ball in the IB, then make copies of it in the code and add it to your view.
The properties I added to the class are just examples of some customization that you could add to the class if you needed to.
You can certainly still use the center property since the BasketBallView is an subclass of the UIImageView, and therefore inherits all the UIImageView properties.
If you have access to iOS7, or can wait another month, Apple's new SpriteKit framework will be able to do a lot of the physics and GPU rendering for you. Then it's just a case of making multiple instances of your "Basketball Class".
You need to add the uiimageview several times on the screen.... and set tag with number 100 or 1001
like
balview.tag = 100;
for (int x=0; x < 5; x++)
{
[self.view addSubview:ballView];
}
do calculation for all in one time
forin(UIImageView *view in [self.view subviews])
{
if (view.tag == 100)
{
//do something
}
}
for (int x = 0; x < 5; x++)
{
UIImageView* ball = [[UIImageView alloc] initWithImage:[UIImage imageNamed:#"YourImageName"]];
ball.frame = CGRectMake(20, 20*x, 20, 20);
[self.view addSubview:ball];
}
I can think of two solutions:
1: Add all balls to an array and access them by the index (seems more feasible to me)
2: Add them tags and access them by
[self.view viewWithTag:<BallTag>];
Edit: Seems like you have chosen the first alternative. Now you need to improve your method for only one ball to move and invoke it whenever you desire.
- (void)moveBallWithIndex:(int)idx{
//for (int i=0; i<array.count;i++){
//Loop removed. It was the reason why all the balls were moving
BasketballView * ball = [array objectAtIndex:idx];
ball.center = CGPointMake(ball.center.x + ballmovement.x, ball.center.y + ballmovement.y);
if (ball.center.x > self.view.frame.size.width || ball.center.x < 0) {
ballmovement.x = -1* ballmovement.x;
}
if (ball.center.y > self.view.frame.size.height || ball.center.y < 0) {
ballmovement.y = -1* ballmovement.y;
}
}
Edit: It seems like you carried the move method to the ball class, for limitations I can think o fthree alternatives:
Create two properties on the ball class named "maxX" and "maxY" during init/set after init and use them in the move method
Improve your move method with two parameters like
- (void)moveWithhinMaxX:(float)maxX andMaxY:(float)maxY;
and use them for limitation inside the move method
Improve your move method by giving the superview on the move method like:
- (void)moveWithinView:(float)newSuperview{
//[newSuperview addSubview:self]; add as subview if necessary
//Use newSuperview's bounds for limitations
and inside it you can add the ball as subview to superview and use its bounds for limitation
I want to set 5 buttons on uiview at random position. Buttons need maintain some spacing to each other. I mean buttons should not overlap to each other.
All buttons set on UIView come from corners with rotation animation.
btn1.transform = CGAffineTransformMakeRotation(40);
btn2.transform = CGAffineTransformMakeRotation(60);
btn3.transform = CGAffineTransformMakeRotation(90);
btn4.transform = CGAffineTransformMakeRotation(30);
btn5.transform = CGAffineTransformMakeRotation(20);
I Can rotate buttons using above code but can you pls. help me for set buttons on random position with out overlapping by each other.
If points are fix than I can set buttons with animation by this code but I want random position of buttons.
[AnimationView moveBubble:CGPointMake(18, 142) duration:1 : btn1];
[AnimationView moveBubble:CGPointMake(118, 142) duration:1 : btn2];
[AnimationView moveBubble:CGPointMake(193, 142) duration:1 : btn3];
[AnimationView moveBubble:CGPointMake(18, 216) duration:1 : btn4];
Thanks in advance.
1st, add buttons to an NSArray, only to make things easier:
NSArray *buttonArray = #[btn1,btn2,btn3,btn4,btn5];
Now, this code tries to Arrange them at random positions.
int xTemp, yTemp;
for (int i = 0; i < 5; i++) {
while (YES) {
xTemp = arc4random_uniform(view.frame.size.width - [buttonArray[i] frame].size.width);
yTemp = arc4random_uniform(view.frame.size.height - [buttonArray[i] frame].size.height);
if (![self positionx:xTemp y:yTemp intersectsAnyButtonTillIndex:i inButtonArray:buttonArray]) {
[AnimationView moveBubble:CGPointMake(xTemp, yTemp) duration:1 : buttonArray[i]];
break;
}
}
}
Implement this function somewhere too:
- (BOOL) positionx:(int)xTemp y:(int)yTemp intersectsAnyButtonTillIndex:(int)index inButtonArray:(NSArray *)buttonArray {
//Again please change the < to <= , I'm sorry, doing too many things at once.
for (int i = 0; i <= index; i++) {
CGRect frame = [buttonArray[i] frame];
//EDIT : In the logic earlier, I had wrongly done a minus where I should have done a plus.
if ((xTemp > frame.origin.x && xTemp < (frame.size.width + frame.origin.x)) && (yTemp > frame.origin.y && yTemp < (frame.size.height + frame.origin.y))) return YES;
}
return NO;
OK this is a workign soln., I hope, just added something to WolfLink's answer. Check This.
for (UIButton *button in buttonArray) {
button.frame = CGRectMake(arc4random_uniform(view.frame.size.width - button.frame.size.width), arc4random_uniform(view.frame.size.height - button.frame.size.height), button.frame.size.width, button.frame.size.height);
while ([self button:button intersectsButtonInArray:buttonArray]) {
button.frame = CGRectMake(arc4random_uniform(view.frame.size.width - button.frame.size.width), arc4random_uniform(view.frame.size.height - button.frame.size.height), button.frame.size.width, button.frame.size.height);
}
//another function
-(BOOL)button:(UIButton *)button intersectsButtonInArray:(NSArray *)array {
for (UIButton *testButton in array) {
if (CGRectIntersectsRect(button.frame, testButton.frame) && ![button isEqual:testButton]) {
return YES;
}
}
return NO;
}
Based on spiritofmysoul.wordpress's code:
//in the function where you randomize the buttons
NSArray *buttonArray = #[btn1,btn2,btn3,btn4,btn5];
for (UIButton *button in buttonArray) {
float widthOffset = self.frame.size.width-button.frame.size.width;
float heightOffset = self.frame.size.height-button.frame.size.height;
button.frame = CGRectMake(arc4random()%widthOffset, arc4random()%heightOffset, button.frame.size.width, button.frame.size.height);
while ([self button:button intersectsButtonInArray:buttonArray]) {
button.frame = CGRectMake(arc4random(), arc4random(), button.frame.size.width, button.frame.size.height);
}
//another function
-(BOOL)button:(UIButton *)button intersectsButtonInArray:(NSArray *)array {
for (UIButton *testButton in array) {
if (CGRectIntersectsRect(button.frame, testButton.frame) && ![button isEqual:testButton]) {
return YES;
}
}
return NO;
}
Beware: This will work well for small amounts of buttons on a large space but as you add buttons and you run out of space, this method will take much longer to run. If there is not enough space for all the buttons, it will become an infinite loop.
Following code i am writing to hide some buttons in viewDidLoad. Here Buttons Are hiding
- (void)viewDidLoad
{
for (int i = 100; i<117; i++)
{
UIButton *smileyButton = (UIButton *)[scroll viewWithTag:i];
UITextField *smileyFields = (UITextField *)[scroll viewWithTag:i];
UIImageView *smileyImage = (UIImageView *)[scroll viewWithTag:i];
smileyFields.hidden = YES;
smileyButton.hidden = YES;
}
}
Now in Following Action am making Buttons Visible. But buttons are not Visible
-(IBAction)editButton:(id)sender
{
for (int i = 100; i<117; i++)
{
UIButton *smileyButton = (UIButton *)[scroll viewWithTag:i];
UITextField *smileyFields = (UITextField *)[scroll viewWithTag:i];
UIImageView *smileyImage = (UIImageView *)[scroll viewWithTag:i];
[smileyFields setHidden:NO]; //TextFields Not Visible
[smileyButton setHidden:NO]; //Buttons Not Visbile
}
}
If you have several views with the same tag, function viewWithTag will return only one view, so if you call this 3 times, you get always the same view.
To do what you want, you could iterate all subviews and check tags:
for (UIView *aView in scrollView.subviews) {
if (aView.tag >= 100 && aView.tag < 117) {
aView.hidden = NO;
}
}
Are you building the view controller in Interface Builder? If so, set the Tag of each thing you want to hide to a different number: try something simple like 1, 2, 3, etc. If you're building in code set the tag property instead. Remember your maximum tag number (let's assume it's 4).
Then add the following to your .h:
- (void)setTaggedViewsHidden:(BOOL)hidden;
and the following to your .m:
- (void)setTaggedViewsHidden:(BOOL)hidden {
for (NSInteger tag = 1; tag <= 4; tag++) {
[scroll viewWithTag:tag].hidden = hidden;
}
}
In your viewDidLoad call it like so:
[self setTaggedViewsHidden:YES];
and in your editButton: selector call it as:
[self setTaggedViewsHidden:NO];
Remember to adjust the code in setTaggedViewsHidden to match the tags you're using. The best way to do this is to #define a constant for the min and max tags and use those in the for loop.