I'm programatically creating a grid of UIViews for a tile based game. The trouble is that, in a three by three grid, only the centre tile is getting drawn at initialisation. The other tiles show up when they're tapped on - but not until (which isn't very good) - and changes to the tile at other times often don't appear. I've adapted my code from Mac OS NSViews (which works very well).
In the subclass for the 'grid' UIView (i.e. the container for the 'tile' UIViews):
- (void)renewRows:(NSInteger)rows columns:(NSInteger)columns {
for (int i=0; i<rows; i++) {
for (int j=0; j<columns; j++) {
CGRect tileRect;
tileRect.origin.x = j*tileSize.width;
tileRect.origin.y = i*tileSize.height;
tileRect.size.width = tileSize.width;
tileRect.size.height = tileSize.height;
id tileView = [[tilePrototype alloc]initWithFrame:tileRect patternNumber:arc4random_uniform(3) + 1];
//add touch recogniser. Will need additional recognisers for left and right swipe
UITapGestureRecognizer *singleFingerTap =
[[UITapGestureRecognizer alloc] initWithTarget:self
action:#selector(tapTile:)];
[tileView addGestureRecognizer:singleFingerTap];
[self addSubview:tileView];
}
}
}
Quite apart from the fact that the tiles show (and animate) correctly when they're tapped, I can see that the tiles are being created in the right place by stepping through this code in debug.
In my Tile UIView I have a drawRect as follows:
- (void)drawRect:(CGRect)dirtyRect {
NSLog(#"%f %f %f %f", dirtyRect.origin.x, dirtyRect.origin.y, dirtyRect.size.width, dirtyRect.size.height);
CGContextRef context = UIGraphicsGetCurrentContext();
_grid = (YANGrid *)[self superview];
double tileWidth = dirtyRect.size.width;
if (_flags.isRotating || _flags.iscentrenode ) {
CGRect centredSquare = CGRectMake(-(tileWidth/4), -(tileWidth/4), tileWidth/2, tileWidth/2);
[_backgroundColor set];
UIRectFill(dirtyRect);
CGContextSaveGState(context);
[self drawPatternConnections];
// Render Nodes
if (_flags.iscentrenode) {
[PatternGraphics centrenodeInRect:¢redSquare];
} else if (_flags.deviceType) {
[PatternGraphics outletnodeInRect:¢redSquare turnedOn:(_flags.isPowered && !_flags.isRotating)];
}
CGContextRestoreGState(context);
}
}
Can anyone here see if I'm missing anything - why aren't my tile UIViews being drawn correctly!
Related
I am building up a simple application that is made up of a UITableViewController with languages and when a specific cell is clicked, a UIPageViewController is brought up to represent the images for that selected language. The user can scroll through the images and everything works as desired. The next step was to build a zooming capability into the UIPageViewController so the user could zoom into the images with a pinch gesture.
I have achieved this with the following code:
- (void)viewDidLoad
{
[super viewDidLoad];
self.leafletImages = [NSMutableArray arrayWithObjects:[[ImageModel alloc] initWithImageName:#"3facts-chinese-page1.jpg"], [[ImageModel alloc] initWithImageName:#"3facts-chinese-page2.jpg"], [[ImageModel alloc] initWithImageName:#"3facts-chinese-page3.jpg"], [[ImageModel alloc] initWithImageName:#"3facts-chinese-page4.jpg"], [[ImageModel alloc] initWithImageName:#"3facts-chinese-page5.jpg"], [[ImageModel alloc] initWithImageName:#"3facts-chinese-page6.jpg"], nil];
// Lots of code for the building up of the UIPageViewController
LeafletImageSizeViewController *imageViewController = [[LeafletImageSizeViewController alloc] init];
imageViewController.model = [_modelArray objectAtIndex:0];
NSArray *viewControllers = [NSArray arrayWithObject:imageViewController];
[self.pageViewController setViewControllers:viewControllers
direction:UIPageViewControllerNavigationDirectionForward
animated:NO
completion:nil];
// Gesture
UIPinchGestureRecognizer *pinchRecognizer = [[UIPinchGestureRecognizer alloc] initWithTarget:self action:#selector(pinchDetected:)];
[self.view addGestureRecognizer:pinchRecognizer];
pinchRecognizer.delegate=self;
}
The class creating the image and the size is:
- (void)useThreeFactsSize
CGRect insetFrame;
insetFrame = CGRectMake(310, 70, self.view.frame.size.width-615, self.view.frame.size.height-85);
_imageView = [[UIImageView alloc] initWithFrame:insetFrame];
[_imageView setAutoresizingMask:UIViewAutoresizingFlexibleWidth | UIViewAutoresizingFlexibleHeight];
[_imageView setImage:[UIImage imageNamed:_model.imageName]];
[[self view] addSubview:_imageView];
[self.view setBackgroundColor:[UIColor clearColor]];
}
The pinchDetection method is:
-(void)pinchDetected:(UIPinchGestureRecognizer *)pinchRecognizer
{
CGFloat scale = pinchRecognizer.scale;
self.pageViewController.view.transform = CGAffineTransformScale(self.pageViewController.view.transform, scale, scale);
pinchRecognizer.scale = 1.0;
}
Now, I can zoom into the images of the UIPageViewController without any issues and it works really well.
What I want to do however is two things:
Not allow the image to be zoomed out beyond the original scale
Create a double tap gesture to bring the image back to it's original scale
With feature 1, the user can zoom into the image, but also completely zoom out of the image which shrinks the image and the UIPageViewController pageIndicators. There's no reason the user should be able to zoom out of the image, so I'd like to allow the user to zoom in to any scale, but not to zoom out beyond what the original size of the image on screen in the UIPageViewController.
With feature 2, I'd like to implement a gesture to double tap the screen and for the zoomed image to go back to it's original scale (like the Photos.app).
Update
With reference to the answer, I have updated the question to reflect how I'm going about doing the images. With point 2 and the double tap gesture, the following code almost works:
- (void)scrollViewTwoFingerTapped:(UITapGestureRecognizer *)recognizer
{
NSLog(#"Double Tap");
self.pageViewController.view.transform = CGAffineTransformIdentity;
}
What it's currently doing is if I zoom in with a pinch and pan around, and then double tap, it centres the image to the point of where I tapped, so sometimes the borders are being shown, etc, rather than making the image centre to where it's supposed to be.
For point 1:
if (pinchRecognizer.scale > 1) {
CGFloat scale = pinchRecognizer.scale;
self.pageViewController.view.transform = CGAffineTransformScale(self.pageViewController.view.transform, scale, scale);
pinchRecognizer.scale = 1.0;
}
If I have self.imageview, it doesn't work because it's nil and even if I make a call to the class setting the size, it's nil as well.
I suspect I have a number of things wrong with my code!
For reference, I have panning working with:
- (void)panGestureDetected:(UIPanGestureRecognizer *)recognizer
{
UIGestureRecognizerState state = [recognizer state];
if (state == UIGestureRecognizerStateBegan || state == UIGestureRecognizerStateChanged)
{
CGPoint translation = [recognizer translationInView:recognizer.view];
[recognizer.view setTransform:CGAffineTransformTranslate(recognizer.view.transform, translation.x, translation.y)];
[recognizer setTranslation:CGPointZero inView:recognizer.view];
}
else if(state==UIGestureRecognizerStateEnded){
UIView *imageView = recognizer.view;
UIView *container = imageView.superview;
CGFloat targetX = CGRectGetMinX(imageView.frame);
CGFloat targetY = CGRectGetMinY(imageView.frame);
if(targetX>0){
// targetX = 0;
}else if(CGRectGetMaxX(imageView.frame)<CGRectGetWidth(container.bounds)){
targetX = CGRectGetWidth(container.bounds)-CGRectGetWidth(imageView.frame);
}
if(targetY>0){
// targetY = 0;
}else if(CGRectGetMaxY(imageView.frame)<CGRectGetHeight(container.bounds)){
// targetY = CGRectGetHeight(container.bounds)-CGRectGetHeight(imageView.frame);
}
// imageView.frame = CGRectMake(targetX, targetY, CGRectGetWidth(imageView.frame), CGRectGetHeight(imageView.frame));
[UIView animateWithDuration:0.3 animations:^{
imageView.frame = CGRectMake(targetX, targetY, CGRectGetWidth(imageView.frame), CGRectGetHeight(imageView.frame));
}];
}
}
That's working very well at the moment, but there's definitely a conflict with everything else.
I'd really appreciate any guidance in the right direction on this.
1.) To not allow the image to be zoomed out beyond it's original scale you first just need to check if the scale you're about to set it to is greater than 1 or not. If it's less than one, you don't want to rescale your image as that would mean it gets smaller. So...
#IBAction func doPinch(sender: UIPinchGestureRecognizer) {
if sender.scale > 1 {
let transform = CGAffineTransformMakeScale(sender.scale, sender.scale)
imageView.transform = transform
}
}
2.) You seem to be changing the view's frame to try and change it's scale, but you never adjusted the view's frame yourself in the first place. You're adjusting the view's transform. That means in order to return it to it's original size you must remove whatever transform you put on it. To do this you put it back to it's identity. So...
#IBAction func doDoubleTap(sender: UITapGestureRecognizer) {
imageView.transform = CGAffineTransformIdentity
}
My code samples are in Swift but you should be able to adjust it to Objective-C yourself. Also, you seem to be adjusting the transform/scale of the entire page view itself. I would suggest you change the scale of only the image view. That makes more sense as that's actually what you're trying to zoom into.
I can't find any helpful tutorials or explanation on how to use a CCScrollView. I have a grid-layout of sprites and labels (listing achievements for an iOS game). There are more than can fit on the screen so I want the user to be able to scroll.
To scroll, the user would swipe/pan upwards, to reveal the sprites etc which are lower.
I've found a few code samples and they seem to indicate you just need to add your content node to the scroll node and it will take care of the rest.
It doesn't seem to work. There's no scroll, and the pan/touch events on the scroll layer never seem to fire. The close button I have at the same child (sibling to the scroll view) no longer works as well.
I'm not using SpriteBuilder.
// Node to hold all sprites/labels
scrollContents = [CCNode node];
// I add a bunch of sprites/labels in a grid view
for( NSString *key in badgeKeys ){
// logic to load the sprite would be here
CCSprite *badge = [CCSprite spriteWithSpriteFrame:frame];
badge.positionType = CCPositionTypeNormalized;
badge.position = ccp(xPos,yPos);
[scrollContents addChild:badge];
// some logic to increment x/y position logic, for grid layout
}
// Scroll view
scrollView = [[CCScrollView alloc] initWithContentNode:scrollContents];
scrollView.horizontalScrollEnabled = NO;
scrollView.verticalScrollEnabled = YES;
[scrollView setBounces:NO];
// My sprites never even show unless I manually set this
scrollContents.contentSize = CGSizeMake(self.contentSize.width,960);
NSLog(#"scrollContents contentsize: %f %f", scrollContents.contentSize.width,scrollContents.contentSize.height);
[self addChild:scrollView];
ok, here is a working example (i deconstructed part of my code to give you a fully working code sample) of a scrolling menu with 'live' buttons inside. I just tested this 'deconstruction' , it works
- (void) scrollingMenuWithCharmsTest {
// setup something to scroll
GameInventory *gi = [GameInventory sharedGameInventory];
while (gi.armorCharms.count < 20) {
[gi addArmorCharm:[ArmorCharm createRandomArmorCharm]];
}
CCNode *contentNode = [self charmsContentNodeFor:gi.armorCharms
showEquiped:NO
spacingBetweenMenuItems:8
target:self
selector:#selector(onArmorCharmSelected:)];
// setup a clipping node to crop out the CCScrollingMenu
CCNodeColor *ccn = [CCNodeColor nodeWithColor:[CCColor blackColor] width:180 height:200];
ccn.anchorPoint = ccp(0, 0);
CCClippingNode *cn = [CCClippingNode clippingNodeWithStencil:ccn];
cn.alphaThreshold = 0.05f;
[self addChild:cn];
cn.inverted = NO;
cn.positionInPointsV = ccp(50, 50);
cn.anchorPoint = ccp(0, 0);
cn.contentSizeInPoints = CGSizeMake(180, 200);
// setup scrolling menu
CCScrollView * bsm = [[CCScrollView alloc] initWithContentNode:contentNode];
bsm.contentSize=CGSizeMake(180,200);
[cn addChild:bsm];
bsm.position = ccp(0, 0);
bsm.bounces = YES;
bsm.pagingEnabled = NO;
bsm.verticalScrollEnabled = YES;
bsm.horizontalScrollEnabled = NO;
bsm.contentSizeInPoints = CGSizeMake(180, 200); // inPoints only after the node has a parent
for (CharmAbstractBoxMenuItem *lmi in bsm.contentNode.children) {
TRACE(#"item %# is at %#", lmi.item.description, NSStringFromCGPoint(lmi.positionInPointsV));
}
TRACE(#"number of pages : %i", bsm.numVerticalPages);
}
- (CCNode *)charmsContentNodeFor:(NSDictionary *)keyedItems
showEquiped:(BOOL)isShowEquiped
spacingBetweenMenuItems:(float)inSpacing
target:(id)inTarget
selector:(SEL)inSelector {
NSSortDescriptor *sortOrder = [NSSortDescriptor sortDescriptorWithKey:#"self" ascending:YES];
NSArray *sortedKeys = [[keyedItems allKeys] sortedArrayUsingDescriptors:[NSArray arrayWithObject:sortOrder]];
float initialY = 0;
float currentY = initialY;
NSUInteger itemNumber = 0;
CGFloat width = 0;
CGFloat height = 0;
CCNode *contentNode = [CCNode node];
for (NSUInteger loopi = 0; loopi < [sortedKeys count]; loopi++) {
NSString *key = [sortedKeys objectAtIndex:loopi];
CharmAbstract *ci = [keyedItems objectForKey:key];
if (ci) {
CharmAbstractBoxMenuItem *cmi = [CharmAbstractBoxMenuItem itemBoxFor:ci
target:inTarget
selector:inSelector
];
cmi.toolTip = ci.toolTip;
cmi.position = ccp(deviceOffset(0), currentY);
cmi.key = key;
[contentNode addChild:cmi z:0 name:[NSString stringWithFormat:#"%li", (long) itemNumber]];
currentY += cmi.contentSizeInPoints.height + inSpacing;
itemNumber++;
if (cmi.contentSize.width > width) width = cmi.contentSize.width;
height += cmi.contentSize.height;
if (loopi < sortedKeys.count - 1) height += inSpacing;
}
else {
MPLOG(#"*** Key [%#] yielded no items.", key);
}
}
contentNode.contentSizeType = CCSizeTypePoints;
contentNode.contentSize = CGSizeMake(width, height);
return contentNode;
}
some notes :
i gave you my 'build content node' routine so you know the ins and outs of positions and sizes.
my charmBoxMenuItemss derive from 'CCButton' and are hot ... In the full version of this code snippet, i extended CCScrollView to prevent the buttons from being 'hot' outside the crop area (although they are cropped out from view, they are still 'visible' by default, and could respond when a random tap occurs above or below the crop area).
For clipping node with stencil, you need to add this in your setupCocos2dWithOptions line:
CCSetupDepthFormat : [NSNumber numberWithUnsignedInt:GL_DEPTH24_STENCIL8_OES]
I have a UIScrollView with a number of rectangular subviews lined up, of equal sizes. Then I need to be able to pass a CGPoint to that UIScrollView and I want it to give me the rectangular subview that contains the CGPoint. That's basically hitTest:event, except hitTest:event: doesn't work with UIScrollView once CGPoint goes beyond the UIScrollView bounds and doesn't look into its actual content.
What's everyone been doing about this? How to "hit test" on a UIScrollView content view?
Here's some code to illustrate the problem:
NSArray *rectangles = [self getBeautifulRectangles];
CGFloat rectangleLength;
rectangleLength = 100;
// add some rectangle subviews
for (int i = 0; i < rectangles.count; i++) {
UIView *rectangle = [rectangles objectAtIndex:i];
[rectangle setFrame:CGRectMake(i * rectangleLength, 0, rectangleLength, rectangleLength)];
[_scrollView addSubview:rectangle];
}
[_scrollView setContentSize:CGSizeMake(rectangleLength * rectangles.count, rectangleLength)];
// add scroll view to parent view
UIView *containerView = [[UIView alloc] initWithFrame:CGRectMake(0,0,320, rectangleLength)];
[containerView addSubview:_scrollView];
// compute CGPoint to center of first rectangle
CGPoint number1RectanglePoint = CGPointMake(0 * rectangleLength + 50, 50);
// compute CGPoint to center of fifth rectangle
CGPoint number5RectanglePoint = CGPointMake(4 * rectangleLength + 50, 50);
UIView *firstSubview = [containerView hitTest:number1RectanglePoint withEvent:nil];
UIView *fifthSubview = [containerView hitTest:number5RectanglePoint withEvent:nil];
if (firstSubview) NSLog(#"first rectangle OK");
if (fifthSubview) NSLog(#"fifth rectangle OK");
output: first rectangle OK
You should be able to loop through the scrollview subviews
+(UIView *)touchedViewIn:(UIScrollView *)scrollView atPoint:(CGPoint)touchPoint {
CGPoint actualPoint = CGPointMake(touchPoint.x + scrollView.contentOffset.x, scrollView.contentOffset.y + touchPoint.y);
for (UIView * subView in scrollView.subviews) {
if(CGRectContainsPoint(subView.frame, actualPoint)) {
NSLog(#"THIS IS THE ONE");
return subView;
}
}
//Nothing touched
return nil;
}
I guess you pass the wrong CGPoint coordinate to the hitTest:withEvent: method causing wrong behavior if the scroll view is scrolled.
The coordinate you pass to this method must be in the target views coordinate system. I guess your coordinate is in the UIScrollView's superview's coordinate system.
You can convert the coordinate prior to using it for the hit test using CGPoint hitPoint = [scrollView convertPoint:yourPoint fromView:scrollView.superview].
In your example you let the container view perform the hit testing, but the container can only see & hit the visible portion of the scroll view and thus your hit fails.
In order to hit subviews of the scroll view which are outside of the visible area you have to perform the hit test on the scroll view directly:
UIView *firstSubview = [_scrollView hitTest:number1RectanglePoint withEvent:nil];
UIView *fifthSubview = [_scrollView hitTest:number5RectanglePoint withEvent:nil];
In the iOS game flappy bird, there are pipes that generate after a certain distance and they generate at random heights
I am also trying to make flappy bird pipes (I called it a tree branch in my code instead of pipe). Except the pipes are moving vertically instead of horizontally because it is a vertical scrolling game (it scrolls like the game doodle jump)
This is a drawing of what I want it to be: https://docs.google.com/drawings/d/18bxsVsNOlScCvgi1mwuzD2At7R6xKM3QCh6BfAVMuMo/edit?usp=sharing
(The horizontal lines are the branches)
So this is what I have tried to do so far to make the vertical branches (or pipes)...
in my .h
CCSprite *branch;
NSMutableArray *_branches;
CCSprite *obstacle;
CCNode *previousBranch;
CGFloat previousBranchYPosition;
in my .m
#implementation HelloWorldLayer
static const CGFloat firstBranchPosition = 426.f;
static const CGFloat distanceBetweenBranches = 140.f;
#define ARC4RANDOM_MAX 0x100000000
static const CGFloat minimumXPositionRightBranch = 280.f;
static const CGFloat maximumXPositionLeftBranch = 50.f;
static const CGFloat pipeDistance = 100.f;
static const CGFloat maximumXPositionRightBranch = maximumXPositionLeftBranch - pipeDistance;
setBranchInitialPosition method
/* This is where I am setting the initial position of the branches.
So I am specifying the position of the first branch and the other branches after it so it gets placed every time a certain distance is passed. I have a left branch and a right branch*/
-(void) setBranchInitialPosition {
CGFloat random = ((double)arc4random() / ARC4RANDOM_MAX);
CGFloat range = maximumXPositionRightBranch - minimumXPositionRightBranch;
_rightBranch.position = ccp(minimumXPositionRightBranch + (random * range), _rightBranch.position.y);
_leftBranch.position = ccp(_rightBranch.position.x + pipeDistance, _leftBranch.position.y);
}
spawnNewBranches method
// This is how I want the branches to spawn and I want to add them to an array full of branches
- (void)spawnNewBranches {
previousBranch = [_branches lastObject];
previousBranchYPosition = previousBranch.position.y;
if (!previousBranch) {
// this is the first obstacle
previousBranchYPosition = firstBranchPosition;
}
_rightBranch = [CCSprite spriteWithFile:#"branch.png"];
_leftBranch = [CCSprite spriteWithFile:#"branch.png"];
[_leftBranch addChild:_rightBranch];
[self setBranchInitialPosition];
obstacle = [CCSprite node];
[obstacle addChild:_leftBranch];
obstacle.position = ccp(160, previousBranchYPosition + distanceBetweenBranches);
[self addChild:obstacle];
[_branches addObject:obstacle];
}
scroll method
-(void) scroll:(ccTime)dt
{
// moves the bg
background.position = ccp(screenCenter.x, background.position.y + [[NSUserDefaults standardUserDefaults] integerForKey:#"scrollSpeed"]*dt);
bg2.position = ccp(screenCenter.x, background.position.y-background.contentSize.height);
// it adds the new bg's to the screen before the old bg's move off the screen
if (background.position.y >= screenSize.height*1.5)
{
background.position = ccp(screenCenter.x, (screenCenter.y)-(background.size.height/2));
} else if (bg2.position.y >= screenSize.height*1.5) {
bg2.position = ccp(screenCenter.x, (screenCenter.y)-(bg2.size.height/2));
}
// This is where I want them to appear every certain distance and also move with the brackground
obstacle.position = ccp(obstacle.position.x, obstacle.position.y*[[NSUserDefaults standardUserDefaults] integerForKey:#"scrollSpeed"]*dt);
NSMutableArray *offScreenObstacles = nil;
if (obstacle.position.y >= screenSize.height*1.5) {
[offScreenObstacles addObject:obstacle];
}
for (CCNode *obstacleToRemove in offScreenObstacles) {
[obstacleToRemove removeFromParent];
[_branches removeObject:obstacleToRemove];
// for each removed obstacle, add a new one
[self spawnNewBranches];
}
}
Right now, the branches are appearing, but they stay in the bottom left corner and they dont move or spawn at all. I want to make them move with the background and spawn after a certain distance while also being generated in random heights. I provided you with all my code, do you know how I can make this work? Thanks in advance!
You may want to try placement of the pipes based on a trigonometric curve like sine or cosine (https://en.wikipedia.org/wiki/Trigonometric_functions). It seems like you are placing the pipes within a fairly define random range though if you change this range to an offset from the plot of the trigonometric curve it would take into account the ability of the player to transition between the open gaps better. At least that's my feel. I think the code would be easier to follow as well as I'm a bit confused going through it. You can also easily vary the difficulty of the curve by changing the parameters such as increasing the amplitude or frequency.
I created a copy of Flappy Bird just for fun. I used this code to create the pipes:
-(void)createPipes{
//Create Random
int from = 65;
int max = [[UIScreen mainScreen] bounds].size.height - 124;
int delta = max - from - dy;
int y = from + arc4random() % (delta - from);
//Pipe Bottom
UIImageView *pipeBottom = [[UIImageView alloc] init];
[pipeBottom setContentMode:UIViewContentModeTop];
[pipeBottom setImage:[UIImage imageNamed:#"pipeBottom"]];
[pipeBottom setFrame:CGRectMake(320, y+dy, 60, max - y - dy)];
[pipeBottom setClipsToBounds:YES];
//Pipe Top
UIImageView *pipeTop = [[UIImageView alloc] init];
[pipeTop setFrame:CGRectMake(320, 0, 60, y)];
[pipeTop setContentMode:UIViewContentModeBottom];
[pipeTop setImage:[UIImage imageNamed:#"pipeTop"]];
[self.view insertSubview:pipeTop atIndex:1];
[self.view insertSubview:pipeBottom atIndex:1];
if (!self.pipes)
self.pipes = [[NSMutableArray alloc] init];
[self.pipes addObject:pipeBottom];
[self.pipes addObject:pipeTop];
}
and to move them:
-(void)moveArray:(NSMutableArray *)array{
float ds = dv * dt;
NSMutableArray *trash = [NSMutableArray array];
for (UIImageView *obj in array) {
CGRect frame = obj.frame;
frame.origin.x -= ds;
if (frame.origin.x < -frame.size.width) {
[obj removeFromSuperview];
[trash addObject:obj];
}else{
obj.frame = frame;
}
}
[array removeObjectsInArray:trash];
}
-(void)movePipes{
[self moveArray:self.pipes];
}
I call this function every 0.01 seconds, to run the game:
-(void)runGame{
_time += dt;
if (_time >= 180.0/dv) {
_time = 0;
[self createPipes];
}
[self movePipes];
[self moveEnemies];
[self moveYoshi];
[self moveBar];
[self verifyScore];
[self verifyCollision];
[self verifyState];
}
I defined dt = 0.01 and dv = 110.
You can see my parody in youtube: (http://www.youtube.com/watch?v=tTcYdpSIKJg)
I hope this help you.
Best, Rafael Castro.
In my subclass of UIView, custom drawing. The original drawing works fine, i.e. when triggered from viewDidLoad or else from a swipe or shake gesture, which clears the screen and redraws.
The problem comes when I try to draw on top of what's already there-- it behaves erratically, usually invisible and offset from where I've placed it, but then it appears if I press the home button. On home-button press, as the view disappears I get a glimpse of what I've tried to draw. If I relaunch the app all the drawing is there. What gives?
Here's how I'm set up:
- (void)drawRect:(CGRect)rect; {
cgRect = [[UIScreen mainScreen] bounds];
cgSize = cgRect.size;
context = UIGraphicsGetCurrentContext();
for (int i=0; i<(cgSize.width / spacing); i++) {
for (int j=0; j<(cgSize.height / spacing); j++) {
[self drawObjectAtPosX:i*spacing andY:j*spacing withId:i*(cgSize.height / spacing) + j];
}
}
There are invisible buttons over certain objects. When they are pressed, the object is to be redrawn in a different color:
-(void)buttonPressed:theButton {
int which = [theButton tag];
if ([[objectArray objectAtIndex:which] shouldBeRedrawn]) {
[self redrawObjectforID:which];
}
}
-(void)redrawObjectforID:(int)which {
myObject *chosenOne = [objectArray objectAtIndex:which];
CGFloat m_x = chosenOne.x;
CGFloat m_y = chosenOne.y;
context = UIGraphicsGetCurrentContext();
CGContextSetRGBStrokeColor(context, 205/255.0,173/255.0,0.0,1.0); // LINE color
CGContextSetRGBFillColor(context, 205/255.0,197/255.0,0.0,1.0); // FILL color
CGContextTranslateCTM(context, m_x, m_y);
CGContextRotateCTM(context, chosenOne.rotation);
for (int i=0; i<4; i++) {
[self drawObjectSegmentatX:m_x andY:m_y forID:which inContext:context]; // custom drawing stuff
CGContextRotateCTM(context, radians(90));
}
CGContextRotateCTM(context, -chosenOne.rotation);
CGContextTranslateCTM(context, -m_x, -m_y);
}
Answering my own, but here's what I learned today:
All custom drawing needs to be in DrawRect. The glitchy behavior I was seeing was the result of DrawRect being called by the view disappearing or being reinstated. Moved, and it works.
Location of the custom redraw is still off, but that's another question.