Cocos2d - only one scheduler called - opengl-es

I'm trying to trace 2 paths on screen through a series of vertices (connect the dots style). Each should be a different color, and each has its own list of vertices.
I started out by creating a class which can trace a path, then creating 2 instances of this class, one for each path. I overrode the draw method. It worked just fine except for some reason only the first instance of the class called the draw method. I figured it was a problem with OpenGL so I did it again using CCDrawNode and it still had the same bug.
Only one instance (blackPath) draws any objects on screen. In fact the scheduled updateEndpoint: method is not even called for the whitePath object, although it is successfully created.
My Drawer.m Class:
const float size = 10;
const float speed = 5;
ccColor4F pathColor;
int numPoints;
NSArray * path;
CGPoint endPoint;
#implementation Drawer
-(id)initWithPath:(NSArray*)p andColorIsBlack:(BOOL)isBlack{
self = [super init];
// Record input
path = p.copy;
pathColor = ccc4f(1.0f, 1.0f, 1.0f, 1.0f);
if(isBlack){
pathColor = ccc4f(0.0f, 0.0f, 0.0f, 1.0f);
}
// Set variables
numPoints = 1;
endPoint = [[path firstObject] position];
NSLog(#"Drawer initialized with path of length %u and color %hhd (isblack)", p.count, isBlack);
[self schedule:#selector(updateEndpoint:)];
return self;
}
-(void)updateEndpoint:(ccTime)dt{
NSLog(#"(%f, %f, %f, %f) Path", pathColor.r, pathColor.g, pathColor.b, pathColor.a);
[self drawDot:endPoint radius:size color:pathColor];
CGPoint dest = [[path objectAtIndex:numPoints] position];
float dx = dest.x - endPoint.x;
float dy = dest.y - endPoint.y;
// new coords are current + distance * sign of distance
float newX = endPoint.x + MIN(speed, fabsf(dx)) * ((dx>0) - (dx<0));
float newY = endPoint.y + MIN(speed, fabsf(dy)) * ((dy>0) - (dy<0));
endPoint = ccp(newX, newY);
if(endPoint.x == dest.x && endPoint.y == dest.y){
if(numPoints < path.count-1){
numPoints+=1;
}
else{
[self unschedule:#selector(updateEndpoint:)];
}
}
}
And here is where I instantiate the objects:
-(id) init{
self = [super init];
[self addAllCards];
[self addScore];
xShrinkRate = [[Grid getInstance] sqWidth] / shrinkTime;
yShrinkRate = [[Grid getInstance] sqHeight] / shrinkTime;
dropList = [NSMutableArray new];
notDropList = [NSMutableArray new];
[self schedule:#selector(dropCard:) interval:0.075];
[self schedule:#selector(shrinkCards:)];
Drawer * whitePath = [[Drawer alloc] initWithPath:[[Score getInstance] whitePath] andColorIsBlack:false];
[self addChild:whitePath];
Drawer * blackPath = [[Drawer alloc] initWithPath:[[Score getInstance] blackPath] andColorIsBlack:true];
[self addChild:blackPath];
return self;
}

Change the (non-const) global variables to instance variables of the class like so:
#implementation Drawer
{
ccColor4F pathColor;
int numPoints;
NSArray * path;
CGPoint endPoint;
}

Related

Sprite Kit: How To Subclass SKNode to create a Vehicle class (complex object with joints)

Has anyone figured out (natively) how to subclass SKNode to include multiple bodies connect by joints - for instance, a car?
There doesn't seem to be a way to add the sub class's joints to the parent scene's physicsWorld property.
Also, when trying to compile and run the object below, even without the joint, I get a BAD_EXC_ACCESS error.
Thank you #Smick for the initial vehicle code as posted here:Sprite Kit pin joints appear to have an incorrect anchor
Truck Class:
#import "Truck.h"
#implementation Truck
-(id)initWithPosition:(CGPoint)pos {
SKSpriteNode *carBody = [SKSpriteNode spriteNodeWithColor:[UIColor whiteColor] size:CGSizeMake(120, 8)];
carBody.physicsBody = [SKPhysicsBody bodyWithRectangleOfSize:carBody.size];
carBody.position = pos;
carBody.physicsBody.mass = 1.0;
SKSpriteNode *carTop = [SKSpriteNode spriteNodeWithColor:[UIColor whiteColor] size:CGSizeMake(50, 8)];
carTop.position = CGPointMake(230, 708);
carTop.physicsBody = [SKPhysicsBody bodyWithRectangleOfSize:carTop.size];
carTop.physicsBody.mass = 0;
SKPhysicsJointFixed *carBodyJoint = [SKPhysicsJointFixed jointWithBodyA:carBody.physicsBody
bodyB:carTop.physicsBody
anchor:CGPointMake(0, 0)];
return self;
}
+(Truck*)initWithPosition:(CGPoint)pos {
return [[self alloc] initWithPosition:pos];
}
#end
MyScene:
sorry for late post, but just hit this myself.
Physics joints dont work unless the nodes being attached have already been added to the SKScene's scene graph.
During the initWithPosition above, that's not the case.
Passing in a SKScene also didn't work for me, I suspect because the Vehicle node still hasn't been added to the scene graph.
You can still encapsulate your physics joints within the class, but you have to call another method after the
[self addChild:car]
Here's my refinement on what you already had:
Vehicle.h
#interface Vehicle : SKNode
#property (nonatomic) SKSpriteNode *leftWheel;
#property (nonatomic) SKSpriteNode *ctop;
-(id)initWithPosition:(CGPoint)pos;
-(void)initPhysics;
#end
Vehicle.m
//
#import "Vehicle.h"
#implementation Vehicle {
SKSpriteNode *chassis;
SKSpriteNode *rightWheel;
SKSpriteNode *leftShockPost;
SKSpriteNode *rightShockPost;
int wheelOffsetY;
CGFloat damping;
CGFloat frequency;
}
- (SKSpriteNode*) makeWheel
{
SKSpriteNode *wheel = [SKSpriteNode spriteNodeWithImageNamed:#"Wheel.png"];
// wheel.physicsBody = [SKPhysicsBody bodyWithCircleOfRadius:wheel.size.width/2];
return wheel;
}
-(id)initWithPosition:(CGPoint)pos {
if (self = [super init]) {
wheelOffsetY = 60;
damping = 1;
frequency = 4;
chassis = [SKSpriteNode spriteNodeWithColor:[UIColor whiteColor] size:CGSizeMake(120, 8)];
chassis.position = pos;
[self addChild:chassis];
_ctop = [SKSpriteNode spriteNodeWithColor:[UIColor greenColor] size:CGSizeMake(70, 16)];
_ctop.position = CGPointMake(chassis.position.x+20, chassis.position.y+12);
[self addChild:_ctop];
_leftWheel = [self makeWheel];
_leftWheel.position = CGPointMake(chassis.position.x - chassis.size.width / 2, chassis.position.y - wheelOffsetY); //Always set position before physicsBody
[self addChild:_leftWheel];
rightWheel = [self makeWheel];
rightWheel.position = CGPointMake(chassis.position.x + chassis.size.width / 2, chassis.position.y - wheelOffsetY);
[self addChild:rightWheel];
//------------- LEFT SUSPENSION ----------------------------------------------------------------------------------------------- //
leftShockPost = [SKSpriteNode spriteNodeWithColor:[UIColor blueColor] size:CGSizeMake(7, wheelOffsetY)];
leftShockPost.position = CGPointMake(chassis.position.x - chassis.size.width / 2, chassis.position.y - leftShockPost.size.height/2);
[self addChild:leftShockPost];
//------------- RIGHT SUSPENSION ----------------------------------------------------------------------------------------------- //
rightShockPost = [SKSpriteNode spriteNodeWithColor:[UIColor blueColor] size:CGSizeMake(7, wheelOffsetY)];
rightShockPost.position = CGPointMake(chassis.position.x + chassis.size.width / 2, chassis.position.y - rightShockPost.size.height/2);
[self addChild:rightShockPost];
}
return self;
}
-(void) initPhysics {
chassis.physicsBody = [SKPhysicsBody bodyWithRectangleOfSize:chassis.size];
_ctop.physicsBody = [SKPhysicsBody bodyWithRectangleOfSize:_ctop.size];
SKPhysicsJointFixed *cJoint = [SKPhysicsJointFixed jointWithBodyA:chassis.physicsBody
bodyB:_ctop.physicsBody
anchor:CGPointMake(_ctop.position.x, _ctop.position.y)];
_leftWheel.physicsBody = [SKPhysicsBody bodyWithCircleOfRadius:_leftWheel.size.width/2];
_leftWheel.physicsBody.allowsRotation = YES;
rightWheel.physicsBody = [SKPhysicsBody bodyWithCircleOfRadius:rightWheel.size.width/2];
rightWheel.physicsBody.allowsRotation = YES;
leftShockPost.physicsBody = [SKPhysicsBody bodyWithRectangleOfSize:leftShockPost.size];
SKPhysicsJointSliding *leftSlide = [SKPhysicsJointSliding jointWithBodyA:chassis.physicsBody
bodyB:leftShockPost.physicsBody
anchor:CGPointMake(leftShockPost.position.x, leftShockPost.position.y)
axis:CGVectorMake(0, 1)];
leftSlide.shouldEnableLimits = TRUE;
leftSlide.lowerDistanceLimit = 5;
leftSlide.upperDistanceLimit = wheelOffsetY;
SKPhysicsJointSpring *leftSpring = [SKPhysicsJointSpring jointWithBodyA:chassis.physicsBody bodyB:_leftWheel.physicsBody
anchorA:CGPointMake(chassis.position.x - chassis.size.width / 2, chassis.position.y)
anchorB:_leftWheel.position];
leftSpring.damping = damping;
leftSpring.frequency = frequency;
SKPhysicsJointPin *lPin = [SKPhysicsJointPin jointWithBodyA:leftShockPost.physicsBody bodyB:_leftWheel.physicsBody anchor:_leftWheel.position];
rightShockPost.physicsBody = [SKPhysicsBody bodyWithRectangleOfSize:rightShockPost.size];
SKPhysicsJointSliding *rightSlide = [SKPhysicsJointSliding jointWithBodyA:chassis.physicsBody
bodyB:rightShockPost.physicsBody
anchor:CGPointMake(rightShockPost.position.x, rightShockPost.position.y)
axis:CGVectorMake(0, 1)];
rightSlide.shouldEnableLimits = TRUE;
rightSlide.lowerDistanceLimit = 5;
rightSlide.upperDistanceLimit = wheelOffsetY;
SKPhysicsJointSpring *rightSpring = [SKPhysicsJointSpring jointWithBodyA:chassis.physicsBody bodyB:rightWheel.physicsBody
anchorA:CGPointMake(chassis.position.x + chassis.size.width / 2, chassis.position.y)
anchorB:rightWheel.position];
rightSpring.damping = damping;
rightSpring.frequency = frequency;
SKPhysicsJointPin *rPin = [SKPhysicsJointPin jointWithBodyA:rightShockPost.physicsBody bodyB:rightWheel.physicsBody anchor:rightWheel.position];
// Add all joints to the array.
// Add joints to scene's physics world
[self.scene.physicsWorld addJoint: cJoint];
[self.scene.physicsWorld addJoint: leftSlide];
[self.scene.physicsWorld addJoint: leftSpring];
[self.scene.physicsWorld addJoint: lPin];
[self.scene.physicsWorld addJoint: rightSlide];
[self.scene.physicsWorld addJoint: rightSpring];
[self.scene.physicsWorld addJoint: rPin];
}
#end
and call it from MyScene.m
_car = [[DMVehicle alloc] initWithPosition:location];
[self addChild:_car];
[_car initPhysics];
Hope that helps, I know it has helped me by working through it
So here's what I came up with.
My only issue with this is that it isn't completely self contained as joints must be added to the physics world outside of the class - simple enough as you'll see using two lines of code.
Editing my answer. The suspension requires the wheels to be attached to a sliding body versus attaching the wheels via the slide joint. Doing the former allows wheels to rotate. The latter does not.
Update: I've unmarked this as the answer. Reason being is that, while it runs fine on the simulator, I receive the following error when I attempt to run it on my iPad (running iOS7). When I remove my vehicle class and place one of the vehicle's components that use that UIColor method into my main scene, the error is not thrown.
UICachedDeviceWhiteColor addObject:]: unrecognized selector sent to instance 0x15e21360
2013-12-14 22:44:19.790 SKTestCase[1401:60b] *** Terminating app due to uncaught exception 'NSInvalidArgumentException', reason: '-[UICachedDeviceWhiteColor addObject:]: unrecognized selector sent to instance
For some reason, I no longer receive the UICashed... error (yes, vehicle is still a class) Now I receive:
-[PKPhysicsJointWeld name]: unrecognized selector sent to instance 0x1464f810
2013-12-15 15:28:24.081 MTC[1747:60b] *** Terminating app due to uncaught exception 'NSInvalidArgumentException', reason: '-[PKPhysicsJointWeld name]: unrecognized selector sent to instance 0x1464f810'
*** First throw call stack:
(0x30eaff53 0x3b5186af 0x30eb38e7 0x30eb21d3 0x30e01598 0x3352837d 0x335284d5 0x33527b97 0x33525ca5 0x87385 0x335064f5 0x87ccb 0x33620fe1 0x332aa24b 0x332a5a5b 0x332d4b7d 0x3369e39b 0x3369ca03 0x3369bc53 0x3369bbdb 0x3369bb73 0x33694681 0x3362703f 0x3369b8c1 0x3369b38d 0x3362c21d 0x33629763 0x33694a55 0x33691811 0x3368bd13 0x336266a7 0x336259a9 0x3368b4fd 0x35ab270d 0x35ab22f7 0x30e7a9e7 0x30e7a983 0x30e79157 0x30de3ce7 0x30de3acb 0x3368a799 0x33685a41 0x8a52d 0x3ba20ab7)
libc++abi.dylib: terminating with uncaught exception of type NSException
Vehicle.h:
#import <SpriteKit/SpriteKit.h>
#interface Vehicle : SKNode
#property (nonatomic,assign) NSMutableArray *joints;
#property (nonatomic) SKSpriteNode *leftWheel;
#property (nonatomic) SKSpriteNode *ctop;
-(id)initWithPosition:(CGPoint)pos;
#end
Vehicle.m
#import "Vehicle.h"
#implementation Vehicle
- (SKSpriteNode*) makeWheel
{
SKSpriteNode *wheel = [SKSpriteNode spriteNodeWithImageNamed:#"wheel.png"];
// wheel.physicsBody = [SKPhysicsBody bodyWithCircleOfRadius:wheel.size.width/2];
return wheel;
}
-(id)initWithPosition:(CGPoint)pos {
if (self = [super init]) {
_joints = [NSMutableArray array];
int wheelOffsetY = 60;
CGFloat damping = 1;
CGFloat frequency = 4;
SKSpriteNode *chassis = [SKSpriteNode spriteNodeWithColor:[UIColor whiteColor] size:CGSizeMake(120, 8)];
chassis.position = pos;
chassis.physicsBody = [SKPhysicsBody bodyWithRectangleOfSize:chassis.size];
[self addChild:chassis];
_ctop = [SKSpriteNode spriteNodeWithColor:[UIColor greenColor] size:CGSizeMake(70, 16)];
_ctop.position = CGPointMake(chassis.position.x+20, chassis.position.y+12);
_ctop.physicsBody = [SKPhysicsBody bodyWithRectangleOfSize:_ctop.size];
[self addChild:_ctop];
SKPhysicsJointFixed *cJoint = [SKPhysicsJointFixed jointWithBodyA:chassis.physicsBody
bodyB:_ctop.physicsBody
anchor:CGPointMake(_ctop.position.x, _ctop.position.y)];
_leftWheel = [self makeWheel];
_leftWheel.position = CGPointMake(chassis.position.x - chassis.size.width / 2, chassis.position.y - wheelOffsetY); //Always set position before physicsBody
_leftWheel.physicsBody = [SKPhysicsBody bodyWithCircleOfRadius:_leftWheel.size.width/2];
_leftWheel.physicsBody.allowsRotation = YES;
[self addChild:_leftWheel];
SKSpriteNode *rightWheel = [self makeWheel];
rightWheel.position = CGPointMake(chassis.position.x + chassis.size.width / 2, chassis.position.y - wheelOffsetY);
rightWheel.physicsBody = [SKPhysicsBody bodyWithCircleOfRadius:rightWheel.size.width/2];
rightWheel.physicsBody.allowsRotation = YES;
[self addChild:rightWheel];
//------------- LEFT SUSPENSION ----------------------------------------------------------------------------------------------- //
SKSpriteNode *leftShockPost = [SKSpriteNode spriteNodeWithColor:[UIColor blueColor] size:CGSizeMake(7, wheelOffsetY)];
leftShockPost.position = CGPointMake(chassis.position.x - chassis.size.width / 2, chassis.position.y - leftShockPost.size.height/2);
leftShockPost.physicsBody = [SKPhysicsBody bodyWithRectangleOfSize:leftShockPost.size];
[self addChild:leftShockPost];
SKPhysicsJointSliding *leftSlide = [SKPhysicsJointSliding jointWithBodyA:chassis.physicsBody
bodyB:leftShockPost.physicsBody
anchor:CGPointMake(leftShockPost.position.x, leftShockPost.position.y)
axis:CGVectorMake(0, 1)];
leftSlide.shouldEnableLimits = TRUE;
leftSlide.lowerDistanceLimit = 5;
leftSlide.upperDistanceLimit = wheelOffsetY;
SKPhysicsJointSpring *leftSpring = [SKPhysicsJointSpring jointWithBodyA:chassis.physicsBody bodyB:_leftWheel.physicsBody
anchorA:CGPointMake(chassis.position.x - chassis.size.width / 2, chassis.position.y)
anchorB:_leftWheel.position];
leftSpring.damping = damping;
leftSpring.frequency = frequency;
SKPhysicsJointPin *lPin = [SKPhysicsJointPin jointWithBodyA:leftShockPost.physicsBody bodyB:_leftWheel.physicsBody anchor:_leftWheel.position];
//------------- RIGHT SUSPENSION ----------------------------------------------------------------------------------------------- //
SKSpriteNode *rightShockPost = [SKSpriteNode spriteNodeWithColor:[UIColor blueColor] size:CGSizeMake(7, wheelOffsetY)];
rightShockPost.position = CGPointMake(chassis.position.x + chassis.size.width / 2, chassis.position.y - rightShockPost.size.height/2);
rightShockPost.physicsBody = [SKPhysicsBody bodyWithRectangleOfSize:rightShockPost.size];
[self addChild:rightShockPost];
SKPhysicsJointSliding *rightSlide = [SKPhysicsJointSliding jointWithBodyA:chassis.physicsBody
bodyB:rightShockPost.physicsBody
anchor:CGPointMake(rightShockPost.position.x, rightShockPost.position.y)
axis:CGVectorMake(0, 1)];
rightSlide.shouldEnableLimits = TRUE;
rightSlide.lowerDistanceLimit = 5;
rightSlide.upperDistanceLimit = wheelOffsetY;
SKPhysicsJointSpring *rightSpring = [SKPhysicsJointSpring jointWithBodyA:chassis.physicsBody bodyB:rightWheel.physicsBody
anchorA:CGPointMake(chassis.position.x + chassis.size.width / 2, chassis.position.y)
anchorB:rightWheel.position];
rightSpring.damping = damping;
rightSpring.frequency = frequency;
SKPhysicsJointPin *rPin = [SKPhysicsJointPin jointWithBodyA:rightShockPost.physicsBody bodyB:rightWheel.physicsBody anchor:rightWheel.position];
// Add all joints to the array.
[_joints addObject:cJoint];
[_joints addObject:leftSlide];
[_joints addObject:leftSpring];
[_joints addObject:lPin];
[_joints addObject:rightSlide];
[_joints addObject:rightSpring];
[_joints addObject:rPin];
}
return self;
}
#end
MyScene.m:
#import "MyScene.h"
#import "Vehicle.h"
#implementation MyScene {
Vehicle *car;
}
-(id)initWithSize:(CGSize)size {
if (self = [super initWithSize:size]) {
/* Setup your scene here */
self.physicsBody = [SKPhysicsBody bodyWithEdgeLoopFromRect:CGRectMake(0, 0, self.size.width, self.size.height)];
}
return self;
}
-(void)touchesBegan:(NSSet *)touches withEvent:(UIEvent *)event {
/* Called when a touch begins */
for (UITouch *touch in touches) {
CGPoint location = [touch locationInNode:self];
car = [[Vehicle alloc] initWithPosition:location];
[self addChild:car];
// Add joints to scene's physics world
for (SKPhysicsJoint *j in car.joints) {
[self.physicsWorld addJoint:j];
}
}
}
1) Adding joints: Why don't you just have the vehicle's init method takes an SKScene object? Then you can add the joint within that method. Otherwise, what you have done with the _joints array works, but seems less clean with the extra code needed there.
2) BAD_EXC_ACCESS: I got this as well when I was learning about joints. It went away when the nodes participating in the joint were added to SKScene and not some other sub nodes. The closest info in the Apple documentation that I can find is this: "Attach the physics bodies to a pair of SKNode objects in the scene." That doesn't specify whether this means directly to the SKScene, or to any node within the node tree in the SKScene.
I had the same issue, and this way works for me:
you will receive an Exc_bad_access if you try to add the joint(defined in the truck class)from your scene. You have to run
[self.scene.physicsWorld addJoint:joint]
in your Truck class.
However, you can't add the
[self.scene.physicsWorld addJoint:joint]
into your init method of the Truck, because the Truck has not been added into your scene when running the Truck's init method in your scene.
You'll have to write another method (let's say addJointsIntoScene) in your Truck class to run
[self.scene.physicsWorld addJoint:joint].
After adding your Truck to your scene, run the 'addJointsIntoScene' method to add the joint.
for example,
Truck.m
-(instancetype)initWithPosition:(CGPoint) triggerPosition{
....
joint = .....
....
}
//and another method
-(void)addJointsIntoScene{
[self.scene.physicsWorld addJoint:joint];enter code here
}
MyScene.m
Truck *truck = [[Truck alloc]initWithPosition:triggerPosition];
[self addChild:truck];
[truck addJointsIntoScene];

Dynamically changing lineWidth using UISlider?

I have imported the CrumbPath.h & .m and CrumPathView.h & .m into my project from the Sample code provided by Apple.
It is working fine, until I want to control the lineWidth of the CrumbPath, In a previous question we solved how to use value from 'Sliderchanged' to populate the 'CGFloat lineWidth ='
Linked here: Use value from UISlider to change another variable?
Now I have hit the problem that the line is not showing at all in the simulator...
CrumbPathView.m
#import "CrumbPathView.h"
#import "CrumbPath.h"
#import "FirstViewController.h"
#interface CrumbPathView (FileInternal)
- (CGPathRef)newPathForPoints:(MKMapPoint *)points
pointCount:(NSUInteger)pointCount
clipRect:(MKMapRect)mapRect
zoomScale:(MKZoomScale)zoomScale;
#end
#implementation CrumbPathView
-(IBAction)sliderChanged:(UISlider *)sender
{
}
- (void)drawMapRect:(MKMapRect)mapRect
zoomScale:(MKZoomScale)zoomScale
inContext:(CGContextRef)context
{
CrumbPath *crumbs = (CrumbPath *)(self.overlay);
CGFloat lineWidth = self.sliderChanged.value;
// outset the map rect by the line width so that points just outside
// of the currently drawn rect are included in the generated path.
MKMapRect clipRect = MKMapRectInset(mapRect, -lineWidth, -lineWidth);
[crumbs lockForReading];
CGPathRef path = [self newPathForPoints:crumbs.points
pointCount:crumbs.pointCount
clipRect:clipRect
zoomScale:zoomScale];
[crumbs unlockForReading];
if (path != nil)
{
CGContextAddPath(context, path);
CGContextSetRGBStrokeColor(context, 0.0f, 0.0f, 1.0f, 0.5f);
CGContextSetLineJoin(context, kCGLineJoinRound);
CGContextSetLineCap(context, kCGLineCapRound);
CGContextSetLineWidth(context, lineWidth);
CGContextStrokePath(context);
CGPathRelease(path);
}
}
#end
#implementation CrumbPathView (FileInternal)
static BOOL lineIntersectsRect(MKMapPoint p0, MKMapPoint p1, MKMapRect r)
{
double minX = MIN(p0.x, p1.x);
double minY = MIN(p0.y, p1.y);
double maxX = MAX(p0.x, p1.x);
double maxY = MAX(p0.y, p1.y);
MKMapRect r2 = MKMapRectMake(minX, minY, maxX - minX, maxY - minY);
return MKMapRectIntersectsRect(r, r2);
}
#define MIN_POINT_DELTA 5.0
- (CGPathRef)newPathForPoints:(MKMapPoint *)points
pointCount:(NSUInteger)pointCount
clipRect:(MKMapRect)mapRect
zoomScale:(MKZoomScale)zoomScale
{
// The fastest way to draw a path in an MKOverlayView is to simplify the
// geometry for the screen by eliding points that are too close together
// and to omit any line segments that do not intersect the clipping rect.
// While it is possible to just add all the points and let CoreGraphics
// handle clipping and flatness, it is much faster to do it yourself:
//
if (pointCount < 2)
return NULL;
CGMutablePathRef path = NULL;
BOOL needsMove = YES;
#define POW2(a) ((a) * (a))
// Calculate the minimum distance between any two points by figuring out
// how many map points correspond to MIN_POINT_DELTA of screen points
// at the current zoomScale.
double minPointDelta = MIN_POINT_DELTA / zoomScale;
double c2 = POW2(minPointDelta);
MKMapPoint point, lastPoint = points[0];
NSUInteger i;
for (i = 1; i < pointCount - 1; i++)
{
point = points[i];
double a2b2 = POW2(point.x - lastPoint.x) + POW2(point.y - lastPoint.y);
if (a2b2 >= c2) {
if (lineIntersectsRect(point, lastPoint, mapRect))
{
if (!path)
path = CGPathCreateMutable();
if (needsMove)
{
CGPoint lastCGPoint = [self pointForMapPoint:lastPoint];
CGPathMoveToPoint(path, NULL, lastCGPoint.x, lastCGPoint.y);
}
CGPoint cgPoint = [self pointForMapPoint:point];
CGPathAddLineToPoint(path, NULL, cgPoint.x, cgPoint.y);
}
else
{
// discontinuity, lift the pen
needsMove = YES;
}
lastPoint = point;
}
}
#undef POW2
// If the last line segment intersects the mapRect at all, add it unconditionally
point = points[pointCount - 1];
if (lineIntersectsRect(lastPoint, point, mapRect))
{
if (!path)
path = CGPathCreateMutable();
if (needsMove)
{
CGPoint lastCGPoint = [self pointForMapPoint:lastPoint];
CGPathMoveToPoint(path, NULL, lastCGPoint.x, lastCGPoint.y);
}
CGPoint cgPoint = [self pointForMapPoint:point];
CGPathAddLineToPoint(path, NULL, cgPoint.x, cgPoint.y);
}
return path;
}
#end
CrumbPathView.h
#import <MapKit/MapKit.h>
#import <UIKit/UIKit.h>
#interface CrumbPathView : MKOverlayView
{
}
#property (weak, nonatomic) IBOutlet UISlider *sliderChanged;
#end
When moving the slider the Output console logs the changes, but nothing changes visually. No Errors, but as I mentioned the CrumbPath is not showing at all... as if the lineWidth was set to '0'.

Cocos2d Shooting Method

ok i am new to coding and cocos2d
i have this shooting code that will fire a projectile and when i try to fire on the left side of the screen it the projectile is fired down and right from the position of the ball?
heres my GamePlay.m
#import "GamePlay.h"
CCSprite *player;
CCSprite *grass;
CCSprite *gameBg;
#implementation GamePlay
+(CCScene *) scene
{
// 'scene' is an autorelease object.
CCScene *scene = [CCScene node];
// 'layer' is an autorelease object.
GamePlay *layer = [GamePlay 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" return value
if( (self=[super init]))
{
self.isTouchEnabled = YES;
gameBg = [CCSprite spriteWithFile:#"backgroundGame1.png"];
gameBg.position = ccp(240,160);
[self addChild:gameBg];
grass = [CCSprite spriteWithFile:#"grass.jpg"];
grass.position = ccp(240,25);
[self addChild:grass];
player = [CCSprite spriteWithFile:#"ball.png"];
player.position = ccp(27,95);
[self addChild:player];
x = 5;
y = 5;
}
return self;
}
- (void)ccTouchesBegan:(NSSet *)touches withEvent:(UIEvent *)event
{
UITouch *myTouch = [touches anyObject];
CGPoint point = [myTouch locationInView:[myTouch view]];
point = [[CCDirector sharedDirector] convertToGL:point];
if (point.x > 240 && point.y < 150)
{
[self unschedule:#selector(moveLeft)];
[self schedule:#selector(moveRight) interval:.01];
}
if (point.x < 240 && point.y < 150)
{
[self unschedule:#selector(moveRight)];
[self schedule:#selector(moveLeft) interval:.01];
}
NSLog(#"Touch Began");
// Choose one of the touches to work with
if (point.y > 150)
{
UITouch *touch = [touches anyObject];
CGPoint location = [touch locationInView:[touch view]];
location = [[CCDirector sharedDirector] convertToGL:location];
CGSize winSize = [[CCDirector sharedDirector]winSize];
CCSprite *projectile = [CCSprite spriteWithFile:#"projectile.png"];
projectile.position = ccp(player.position.x,player.position.y);
int offX = location.x - projectile.position.x;
int offY = location.y - projectile.position.y;
[self addChild:projectile];
int realX = winSize.width + (projectile.contentSize.width/2);
float ratio = (float) offY / (float) offX;
int realY = (realX *ratio) + projectile.position.y;
CGPoint realDest = ccp(realX, realY);
int offRealX = realX - projectile.position.x;
int offRealY = realY - projectile.position.y;
float length = sqrtf((offRealX*offRealX)+(offRealY*offRealY));
float velocity = 480/1;
float realMoveDuration = length/velocity;
[projectile runAction:[CCMoveTo actionWithDuration:realMoveDuration position:realDest]];
NSLog(#"Shoot!");
}
}
-(void)ccTouchesEnded:(NSSet *) touches withEvent:(UIEvent *)event
{
UITouch *myTouch = [touches anyObject];
CGPoint point = [myTouch locationInView:[myTouch view]];
point = [[CCDirector sharedDirector] convertToGL:point];
[self unschedule:#selector(moveLeft)];
[self unschedule:#selector(moveRight)];
NSLog(#"Touch Ended");
}
-(void) spriteMoveFinished: (id) sender
{
}
-(void)moveLeft
{
player.position = ccp(player.position.x - x, player.position.y);
if (player.position.x < 15)
{
player.position = ccp(16,player.position.y);
}
}
-(void)moveRight
{
player.position = ccp(player.position.x + x, player.position.y);
if (player.position.x > 465)
{
player.position = ccp(464,player.position.y);
}
}
#end
this is the shooting method (i think it has something to do with the x & y offset?)
if (point.y > 150)
{
UITouch *touch = [touches anyObject];
CGPoint location = [touch locationInView:[touch view]];
location = [[CCDirector sharedDirector] convertToGL:location];
CGSize winSize = [[CCDirector sharedDirector]winSize];
CCSprite *projectile = [CCSprite spriteWithFile:#"projectile.png"];
projectile.position = ccp(player.position.x,player.position.y);
int offX = location.x - projectile.position.x;
int offY = location.y - projectile.position.y;
[self addChild:projectile];
int realX = winSize.width + (projectile.contentSize.width/2);
float ratio = (float) offY / (float) offX;
int realY = (realX *ratio) + projectile.position.y;
CGPoint realDest = ccp(realX, realY);
int offRealX = realX - projectile.position.x;
int offRealY = realY - projectile.position.y;
float length = sqrtf((offRealX*offRealX)+(offRealY*offRealY));
float velocity = 480/1;
float realMoveDuration = length/velocity;
[projectile runAction:[CCMoveTo actionWithDuration:realMoveDuration position:realDest]];
NSLog(#"Shoot!");
}
The best resource is here
Just give it a try.
Cheers
I found the answer here Projectiles/Bullets direction Cocos2d
you needed to do this,
// After adding the projectile:
[self addChild:projectile];
// Add a scalar float:
float scalarX = 1.0f;
// And make it negative if the touch is left of the character:
if (offX < 0.0f) scalar = -1.0f;
// Then just multiply the realX by this scalar to make it point the correct way
int realX = scalar * (winSize.width + (projectile.contentSize.width/2));

Cocos2d: Animation based on accelerometer

Anyone know of any good up to date tutorials out there that show how can one animate a sprite based on accelerometer movement. I want to animate a bird to sway to the position the device was pointed to. For example if the player decides to move the bird to the left via the accelerometer I would like for my bird to play an animation that is swaying to the left.
// Accelerometer
-(void)accelerometer:(UIAccelerometer *)accelerometer didAccelerate:(UIAcceleration *)acceleration {
birdSpeedY = 9.0 + acceleration.x*15;
birdSpeedX = -acceleration.y*20;
}
// Updating bird based on accelerometer
-(void)updateBird {
float maxY = winSize.height - bird.contentSize.height/2;
float minY = bird.contentSize.height/2;
float newY = bird.position.y + birdSpeedY;
newY = MIN(MAX(newY, minY), maxY);
float maxX = winSize.width - bird.contentSize.width/2;
float minX = bird.contentSize.width/2;
float newX = bird.position.x + birdSpeedX;
newX = MIN(MAX(newX, minX), maxX);
bird.position = ccp(newX, newY);
}
// Making background scroll automatically
-(void)update:(ccTime)dt {
[self updateBird];
CGPoint backgroundScrollVel = ccp(-100, 0);
parallaxNode.position = ccpAdd(parallaxNode.position, ccpMult(backgroundScrollVel, dt));
}
-(id)init {
self = [super init];
if (self != nil) {
winSize = [CCDirector sharedDirector].winSize;
CCSpriteFrameCache *cache=[CCSpriteFrameCache sharedSpriteFrameCache];
[cache addSpriteFramesWithFile:#"birdAtlas.plist"];
NSMutableArray *framesArray=[NSMutableArray array];
for (int i=1; i<10; i++) {
NSString *frameName=[NSString stringWithFormat:#"bird%d.png", i];
id frameObject=[cache spriteFrameByName:frameName];
[framesArray addObject:frameObject];
}
// animation object
id animObject=[CCAnimation animationWithFrames:framesArray delay:0.1];
// animation action
id animAction=[CCAnimate actionWithAnimation:animObject restoreOriginalFrame:NO];
animAction=[CCRepeatForever actionWithAction:animAction];
bird=[CCSprite spriteWithSpriteFrameName:#"bird1.png"];
bird.position=ccp(60,160);
CCSpriteBatchNode *batchNode=[CCSpriteBatchNode batchNodeWithFile:#"birdAtlas.png"];
[self addChild:batchNode z:100];
[batchNode addChild:bird];
[bird runAction:animAction];
self.isAccelerometerEnabled = YES;
[self scheduleUpdate];
[self addScrollingBackgroundWithTileMapInsideParallax];
}
return self;
}
- (void) dealloc
{
[super dealloc];
}
#end
You can try the Accelerometer methods with it and change the position of the Sprite using ccp(). You also need to know is that project for the Landscape or Portrait in the Mode.
You Can Try the Stuff below
- (void)accelerometer:(UIAccelerometer*)accelerometer didAccelerate:(UIAcceleration*)acceleration
{
[lbl setString:[NSString stringWithFormat:#"X=>%.2lf Y=>%.2lf",(double)acceleration.x,(double)acceleration.y]];
double x1= -acceleration.y *10;
double y1= acceleration.x *15;
if(acceleration.x >0.05)
{
y1*=spped_incr; // Make Movement Here
}
[Sprite_Name runAction:[CCMoveTo actionWithDuration:0.1f position:ccpAdd(ccp(x1,y1), Sprite_Name.position)]];
}
The Above Stuff is for the Landscape Mode.... if You need in Portrait Mode you need to change the Axis and use the TRY & Error Method.

reset image in tableView imageCell is blurry

i'm trying to show an 'info' icon during a cursor 'rollover' on an NSTableView cell. i'm getting a copy of the cell's image, drawing the 'info' icon on it, and telling the cell to setImage with this copy. just drawing the icon will scale it and it won't be the same size in every one as the images in the table are different sizes. i'm not having a problem with the scaling or positioning the correct size icon.
my problem is that the replaced image is slightly blurry and it's edges are not crisp on close examination. the lack of edge makes it appear to be 'moving' slightly when the mouseEntered happens and the image is replaced.
i've tried a number of drawing techniques that doen't use lockFocus on an NSImage (drawing in CGBitmapContext, or using CIFilter compositing), and they produce the same results.
i'm using NSTableView's preparedCellAtColumn as it seems that drawing in willDisplayCell is unpredictable -- i read somewhere but can't remember where.
here is my preparedCellAtColumn method:
- (NSCell *)preparedCellAtColumn:(NSInteger)column row:(NSInteger)row
{
NSCell *cell = [super preparedCellAtColumn:column row:row];
if ((self.mouseOverRow == row) && column == 0) {
NSCell * imageCell = [super preparedCellAtColumn:0 row:row];
NSImage *sourceImage = [[imageCell image] copy];
NSRect cellRect = [self frameOfCellAtColumn:0 row:row];
NSSize cellSize = cellRect.size;
NSSize scaledSize = [sourceImage proportionalSizeForTargetSize:cellSize];
NSImage *outputImage = [[NSImage alloc] initWithSize:cellSize];
[outputImage setBackgroundColor:[NSColor clearColor]];
NSPoint drawPoint = NSZeroPoint;
drawPoint.x = (cellSize.width - scaledSize.width) * 0.5;
drawPoint.y = (cellSize.height - scaledSize.height) * 0.5;
NSRect drawRect = NSMakeRect(drawPoint.x, drawPoint.y, scaledSize.width, scaledSize.height);
NSPoint infoPoint = drawPoint;
infoPoint.x += NSWidth(drawRect) - self.infoSize.width;
[outputImage lockFocus];
[sourceImage drawInRect:drawRect fromRect:NSZeroRect operation:NSCompositeSourceOver fraction:1.0];
[self.infoImage drawAtPoint:infoPoint fromRect:NSZeroRect operation:NSCompositeSourceOver fraction:1.0];
[outputImage unlockFocus];
[cell setImage:outputImage];
}
return cell;
}
[this is the enclosed scaling method from scott stevenson]
- (NSSize)proportionalSizeForTargetSize:(NSSize)targetSize
{
NSSize imageSize = [self size];
CGFloat width = imageSize.width;
CGFloat height = imageSize.height;
CGFloat targetWidth = targetSize.width;
CGFloat targetHeight = targetSize.height;
CGFloat scaleFactor = 0.0;
CGFloat scaledWidth = targetWidth;
CGFloat scaledHeight = targetHeight;
if ( NSEqualSizes( imageSize, targetSize ) == NO )
{
CGFloat widthFactor;
CGFloat heightFactor;
widthFactor = targetWidth / width;
heightFactor = targetHeight / height;
if ( widthFactor < heightFactor )
scaleFactor = widthFactor;
else
scaleFactor = heightFactor;
scaledWidth = width * scaleFactor;
scaledHeight = height * scaleFactor;
}
return NSMakeSize(scaledWidth,scaledHeight);
}
i need to support 10.6, so can't use new groovy lion methods.
thanks for your consideration...
Your code is setting the origin of the image to non-integral coordinates. That means that the edge of the image will not be pixel-aligned, producing a fuzzy result.
You just need to do this:
NSPoint drawPoint = NSZeroPoint;
drawPoint.x = round((cellSize.width - scaledSize.width) * 0.5);
drawPoint.y = round((cellSize.height - scaledSize.height) * 0.5);
That will ensure the image origin has no fractional component.

Resources