存档

2009年3月 的存档

How can i use MYSQL database connection in iphone application useing cocos2d?

2009年3月23日 没有评论

I am working on project and i need to connect MYSQL database. I am success to connect SQLite in my project ( using cocos2d).But i can not connect MYSQL database in my project.
I any one do like this than help me for how to connect . Give me the necessary information.

You will not be able to connect to MySQL directly from the iPhone. You must use some intermediate layer such as a Web application with PHP.

So, you will have something like this:

  1. iPhone POSTING a request to the WebServer using HTTP
  2. Web Server connecting to the MySQL database
  3. Web Server returning data to the iPhone (XML, plain text)
  4. iPhone processing the data

You can use this technique to query and insert/update/delete data.

This site contains a libmysqlclient.a file compiled for the iphone (arm).

http://www.eval-art.com/2008/09/05/libmysqlclient-for-iphone-2/

分类: cocos2d, stackoverflow精选 标签:

iPhone cocos2d sprites in array, memory problems

2009年3月21日 没有评论

I’m trying to keep track of my sprites in an array, add and remove
them from layers, and then finally clear them out of the array.

I’m using the following code:

Sprite * Trees[50];
Layer * Forest;

Forest =  [Layer node];
Forest.isTouchEnabled = YES;
[self addChild:Forest z:30];

// do this a bunch of times
Trees[0] = [[Sprite spriteWithFile:@"mytree.png"] retain];
[Trees[0] setPosition:cpv(240,160)];
[Forest addChild:Trees[0] z:5];

And then when I want to destroy a tree I use:

[Forest removeChild:Trees[0] cleanup:YES];
[Trees[0] release];

My problem is that when I look in Instruments, I’m never reclaiming
that memory, there is never a drop back down. I thought that by
releasing the sprite it would free up the memory. Am I doing this
completely wrong?

I know that when you are using the simulator with cocos2d, the memory doesn’t look like it’s being released, so you have to run it on the device to get an accurate picture of what’s going on.

There is a good discussion here about cocos2d and memory.

What I’ve noticed is that everything that you create and retain must be released, but it isn’t released from memory until I do this:

[[TextureMgr sharedTextureMgr] removeAllTextures];

That will release the memory.

Here’s a bigger example:

Sprite * sPopup = [[Sprite spriteWithFile:@"popup.png"] retain];
    sPopup.position = cpv(240,440);
    [self addChild: sPopup z:2];
[sPopup release];

Then, when I’m done with sPopup in another function I have this:

[[TextureMgr sharedTextureMgr] removeAllTextures];

and the memory is freed.

My suspicion is that you are “over” retaining:

Trees[0] = [[Sprite spriteWithFile:@"mytree.png"] retain];

If Trees is a local variable in a function you do not have to retain in that case if spriteWithFile is returning a Sprite with an autorelease.

The section on delay release in the apple documentation discusses this further. The long and short of it is that the receiver of the autorelease is guaranteed to have the object be valid for the duration of its scope. If you need the object beyond the scope of the function (e.g. Trees is a property of a class) then yes, in that case you need a retain (or just synthesize a property configured to retain).

By issuing the extra retain, it is likely that your retain count is always too high (never reaches 0) and hence your object is not garbage collected.

For good measure, I’d suggest reviewing this paragraph as well that talks about the validity of objects.

Even though you call [Trees[x] release], I believe you still need to ‘delete’ the item from the array, like Trees[x] = nil or something, as the array itself is still containing the object.

The ‘retain’ in the Sprite creation is also not necessary, as [Forest addChild:z:] will place a retain on it as well (afaik).

分类: cocos2d, stackoverflow精选 标签:

UIScrollview with UIButtons – how to recreate springboard?

2009年3月16日 没有评论

I’m trying to create a springboard-like interface within my app. I’m trying to use UIButtons added to a UIScrollView. The problem I’m running in to is with the buttons not passing any touches to the UIScrollView – if I try to flick/slide and happen to press on the button it doesn’t register for the UIScrollView, but if I flick the space between buttons it will work. The buttons do click/work if I touch them.

Is there a property or setting that forces the button to send the touch events up to its parent (superview)? Do the buttons need to be added to something else before being added the UIScrollView?

Here is my code:

//init scrolling area
UIScrollView *scrollView = [[UIScrollView alloc] initWithFrame:CGRectMake(0, 0, 480, 480)];
scrollView.contentSize = CGSizeMake(480, 1000);
scrollView.bounces = NO;
scrollView.delaysContentTouches = NO;

//create background image
UIImageView *rowsBackground = [[UIImageView alloc] initWithImage:[self scaleAndRotateImage:[UIImage imageNamed:@"mylongbackground.png"]]];
rowsBackground.userInteractionEnabled = YES;

//create button
UIButton *btn = [[UIButton buttonWithType:UIButtonTypeCustom] retain];
btn.frame = CGRectMake(100, 850, 150, 150);
btn.bounds = CGRectMake(0, 0, 150.0, 150.0);
[btn setImage:[self scaleAndRotateImage:[UIImage imageNamed:@"basicbutton.png"]] forState:UIControlStateNormal];
[btn addTarget:self action:@selector(buttonClick) forControlEvents:UIControlEventTouchUpInside];

//add "stuff" to scrolling area
[scrollView addSubview:rowsBackground];
[scrollView addSubview:btn];

//add scrolling area to cocos2d
//this is just a UIWindow
[[[Director sharedDirector] openGLView] addSubview:scrollView];

//mem-mgmt
[rowsBackground release];
[btn release];
[scrollView release];

In order for UIScrollView to determine the difference between a click that passes through to its content view(s) and a touch that turns into a swipe or pinch, it needs to delay the touch and see if your finger has moved during that delay. By setting delaysContentTouches to NO in your above example, you’re preventing this from happening. Therefore, the scroll view is always passing the touch to the button, instead of canceling it when it turns out that the user is performing a swipe gesture. Try setting delaysContentTouches to YES.

It might also be a good idea, structurally, to add all the views to be hosted in your scroll view to a common content view and only use that one view as the scroll view’s subview.

UIScrollView handles a lot of events itself. You need to handle touchesDidEnd and hit test for buttons inside the UIScrollView manually.

Another way is:
1. Substitute de button by a simple custom UIView
2. Put the flag “userInterationEnable = yes;” on the init method
3. In the view override the UIResponder method “touchesEnded” here you can trigger the action you need like a button.

In my experience the first answer, i.e., simply setting delaysContentTouches to YES, does not change anything with regard to the problem. The buttons will still not deliver tracking results to the scroll view. The third answer is both simple and very usable. Thanks sieroaoj!

However, for the third answer to work you also need delaysContentTouches set to YES. Otherwise the method touchesEnded will also be called for tracking within the view. Therefore I could solve the problem by:

  1. Substitute de button by a simple custom UIView
  2. Put the flag “userInterationEnable = yes;” on the init method
  3. In the view override the UIResponder method “touchesEnded” here
    you can trigger the action you

Fourth. set delaysContentTouches to YES

OK here is your answer:

Subclass UIButton. (NOTE: call [super ….] at the start of each override.

  • Add a property. One of type BOOL
    (called enableToRestore)
  • Add a property. One of type CGPoint
    (called startTouchPosition)
  • in the awakeFromNib and
    initWithFrame, set the
    enableToRestore to the isEnabled
    property)
  • Override “touchesBegan: withEvent:”
    to store the start of the touch
    position.
  • Override “touchesMoved: withEvent:” to
    check to see if there is horizontal
    movement.
  • If YES, set enabled to NO and
    selected to NO.

Sample code:

- (void)touchesBegan:(NSSet *)touches withEvent:(UIEvent *)event 
{
    UITouch *touch = [touches anyObject];

    [super touchesBegan:touches withEvent:event];
    [self setStartTouchPosition:[touch locationInView:self]];
}


//
// Helper Function
//
- (BOOL)isTouchMovingHorizontally:(UITouch *)touch 
{
    CGPoint currentTouchPosition = [touch locationInView:self];
    BOOL      rValue = NO;

    if (fabsf([self startTouchPosition].x - currentTouchPosition.x) >= 2.0) 
    {
        rValue = YES;
    }

    return (rValue);
}

//
// This is called when the finger is moved.  If the result is a left or right
// movement, the button will disable resulting in the UIScrollView being the
// next responder.  The parrent ScrollView will then re-enable the button
// when the finger event is ended of cancelled.
//
- (void)touchesMoved:(NSSet *)touches withEvent:(UIEvent *)event 
{
    [super touchesMoved:touches withEvent:event];
    if ([self isTouchMovingHorizontally:[touches anyObject]]) 
    {
        [self setEnabled:NO];
        [self setSelected:NO];
    } 
}

This will activate the UIScrollView.

Subclass UIScrollView. (NOTE: call [super ….] at the start of each override.

  • Override both “touchesEnded: withEvent:” and “touchesCancelled: withEvent:”
  • In the override, reset all subviews (and their subviews) enabled flag.
  • NOTE: Use a Category and add the method to UIView:

.

- (void) restoreAllEnables
{
    NSArray   *views = [self subviews];

    for (UIView *aView in views)
    {
        if ([aView respondsToSelector:@selector(restoreEnable)])
        {
            [aView restoreEnable];
        }
    }
}

- (void) touchesEnded:(NSSet *)touches withEvent:(UIEvent *)event
{
    [super touchesEnded:touches withEvent:event];
    [self restoreAllEnables];
}

- (void)touchesCancelled:(NSSet *)touches withEvent:(UIEvent *)event
{
    [super touchesEnded:touches withEvent:event];
    [self restoreAllEnables];
}
  • In the Category:

.

-(void) restoreEnable
{
    NSArray   *views = [self subviews];

    if ([self respondsToSelector:@selector(enableToRestore)])
    {
        [self setEnabled:[self enableToRestore]];
    }

    for (UIView *aView in views)
    {
        if ([aView respondsToSelector:@selector(restoreEnable)])
        {
            [aView restoreEnable];
        }
    }
}

EDIT
Note: I never got Answer 3 to work.
Likewise: the setDelaysContentTouches:NO (set in the view controller or someplace) is to be set for best results on Answer 4. This provides very fast response to the buttons. Setting setDelaysContentTouches:YES puts a serious impact (150ms) on response time to the buttons and makes light,fast touching not possible.

I have a similar case that a number of buttons on a UIScrollView, and I want to scroll these buttons. At the beginning, I subclassed both UIScrollView and UIButton. However, I noticed that my subclassed UIScrollView did not receive touchesEnded event, so I changed to only subclass UIButton.


@interface MyPhotoButton : UIButton {
}

- (void)touchesMoved:(NSSet *)touches withEvent:(UIEvent *)event;
- (void)touchesEnded:(NSSet *)touches withEvent:(UIEvent *)event;
- (void)touchesCancelled:(NSSet *)touches withEvent:(UIEvent *)event;
@end

@implementation MyPhotoButton

- (void)touchesMoved:(NSSet *)touches withEvent:(UIEvent *)event {
    [super touchesMoved:touches withEvent:event];
    [self setEnabled:NO];
    [self setSelected:NO];
}

- (void)touchesEnded:(NSSet *)touches withEvent:(UIEvent *)event {
    [super touchesEnded:touches withEvent:event];
    [self setEnabled:YES];
}

- (void)touchesCancelled:(NSSet *)touches withEvent:(UIEvent *)event {
    [super touchesCancelled:touches withEvent:event];
    [self setEnabled:YES];
}

@end

Solution that worked for me included:

  1. Setting canCancelContentTouches in UIScrollView to YES.
  2. Extending UIScrollView to override touchesShouldCancelInContentView:(UIView *)view to return YES when view is a UIButton.

According to documentation touchesShouldCancelInContentView returns “YES to cancel further touch messages to view, NO to have view continue to receive those messages. The default returned value is YES if view is not a UIControl object; otherwise, it returns NO.”

Since UIButton is a UIControl the extension is necessary to get canCancelContentTouches to take effect which enables scrolling.

分类: cocos2d, stackoverflow精选 标签: