I've found code for making a rope in my Sprite Kit game. I'll post it below. Problem is, the method header is very long & has a syntax that I'm unable to call upon in my initWithSize method. I tried writing [self addRopeJointItems]; but to no avail. Yes. I am new to objective-c. Hope someone can help out.
Code:
+(void)addRopeJointItems:(CGPoint)leftStartPosition countJointElements:(int)countJointElements game:(SKScene*)game
{
int itemJointWidth = 25;
//Left Physics Anchor
SKSpriteNode * leftAnchor = [SKSpriteNode spriteNodeWithColor:[SKColor clearColor] size:CGSizeMake(1, 1)];
leftAnchor.position = CGPointMake(leftStartPosition.x, leftStartPosition.y);
//leftAnchor.size = CGSizeMake(1, 1);
leftAnchor.zPosition = 2;
leftAnchor.physicsBody = [SKPhysicsBody
bodyWithRectangleOfSize:
leftAnchor.size];
leftAnchor.physicsBody.affectedByGravity = false;
leftAnchor.physicsBody.mass = 99999999999;
[game addChild:leftAnchor];
//add RopeElements
for (int i=0; i<countJointElements; i++)
{
SKSpriteNode * item = [SKSpriteNode spriteNodeWithImageNamed:#"rope_ring.png"];
item.name = [NSString stringWithFormat:#"ropeitem_%d", i];
item.position = CGPointMake(leftStartPosition.x + (i*itemJointWidth) + itemJointWidth/2, leftStartPosition.y+60);
item.size = CGSizeMake(itemJointWidth + 5, 5);
item.zPosition = 2;
item.physicsBody = [SKPhysicsBody
bodyWithRectangleOfSize:
item.size];
item.physicsBody.categoryBitMask = kNilOptions;
[game addChild:item];
//Add Joint to the element before
SKPhysicsBody* bodyA;
if (i == 0)
{
bodyA = leftAnchor.physicsBody;
}
else
{
bodyA = [game childNodeWithName:[NSString stringWithFormat:#"ropeitem_%d", i-1]].physicsBody;
}
SKPhysicsJointPin* joint = [SKPhysicsJointPin jointWithBodyA:bodyA bodyB:item.physicsBody anchor:CGPointMake((item.position.x - item.size.width/2) + 5, item.position.y)];
[game.physicsWorld addJoint:joint];
}
//Right Physics Anchor
SKSpriteNode * rightAnchor = [SKSpriteNode spriteNodeWithColor:[SKColor clearColor] size:CGSizeMake(1, 1)];
rightAnchor.position = CGPointMake((leftStartPosition.x + (countJointElements*itemJointWidth)),
leftStartPosition.y+60);
//rightAnchor.size = CGSizeMake(1, 1);
rightAnchor.zPosition = 2;
rightAnchor.physicsBody = [SKPhysicsBody
bodyWithRectangleOfSize:
rightAnchor.size];
rightAnchor.physicsBody.affectedByGravity = false;
rightAnchor.physicsBody.mass = 99999999999;
[game addChild:rightAnchor];
//Add the Last Joint
SKPhysicsJointPin* jointLast = [SKPhysicsJointPin jointWithBodyA:[game childNodeWithName:[NSString stringWithFormat:#"ropeitem_%d", countJointElements - 1]].physicsBody
bodyB:rightAnchor.physicsBody
anchor:rightAnchor.position];
[game.physicsWorld addJoint:jointLast];
}
You can do two things here:-
1) Either change your method to instance method with prefix (-). If you want call as instance method with self
-(void)addRopeJointItems:(CGPoint)leftStartPosition countJointElements:(int)countJointElements game:(SKScene*)game
2)Or follow #Andrey Chernukha comments as
[ClassName addRopeJointItems:leftStartPosition countJointElements:elements game:game];
Related
CAEmitterCell contents picCAEmitterLayer emits multiple CAEmitterCells with specified trajectories. When the trajectory CAEmitterCells fly to the end of time, it will become a particle graph displayed by CAEmitterCells, and then the particle graph will be scattered 360 °. However, only one trajectory particle can be animated completely, but more than two particles will appear. The trajectory particle graph will turn white
Adding a boomEmitterCell will cause the contents of CAEmitterCell in getDogLeftDownEmitterWithImageName and getRedLeftEmitterWithImageName to not display the picture and white blocks
CAEmitterLayer *emitterLayer = [[CAEmitterLayer alloc] init];
emitterLayer.emitterPosition = CGPointMake(self.view.layer.bounds.size.width -100, self.view.layer.bounds.size.height - 100);
emitterLayer.emitterSize = CGSizeMake(50, 100.f);
emitterLayer.emitterShape = kCAEmitterLayerLine;
emitterLayer.emitterMode = kCAEmitterLayerOutline;
emitterLayer.renderMode = kCAEmitterLayerOldestLast;
CAEmitterCell *dogleftEmitterCell = [self getRedLeftEmitterWithImageName:[imageArray objectAtIndex:0]];
CAEmitterCell *redLeftEmitterCell = [self getRedLeftEmitterWithImageName:[imageArray objectAtIndex:0]];
emitterLayer.emitterCells = #[dogleftEmitterCell,redLeftEmitterCell];
[self.view.layer addSublayer:emitterLayer];
//狗头左下
- (CAEmitterCell *)getDogLeftDownEmitterWithImageName:(NSString *)imageName {
CAEmitterCell *emitterCell = [[CAEmitterCell alloc] init];
emitterCell.name = #"左下狗头";
emitterCell.contents = (__bridge id _Nullable)[UIImage imageNamed:#"emoji_6"].CGImage;
//产生频率
emitterCell.birthRate = 1;
//存活时长
emitterCell.lifetime = 0.6;
//速度
emitterCell.velocity = 100;
emitterCell.xAcceleration = -1000.f; // 模拟重力影响
emitterCell.scale = 0.2;
emitterCell.scaleSpeed = 0.25;
emitterCell.emissionLongitude = M_PI_2;
// emitterCell.emissionRange = M_PI_4;
emitterCell.emitterCells = #[[self boomEmitterCell]];
return emitterCell;
}
//红包左上
- (CAEmitterCell *)getRedLeftEmitterWithImageName:(NSString *)imageName {
CAEmitterCell *emitterCell = [[CAEmitterCell alloc] init];
emitterCell.name = #"红包";
emitterCell.contents = (__bridge id _Nullable)[UIImage imageNamed:#"emoji_7"].CGImage;
//产生频率
emitterCell.birthRate = 10;
//存活时长
emitterCell.lifetime = 0.6;
// emitterCell.beginTime = self.beginTime;
//速度
emitterCell.velocity = 100;
emitterCell.yAcceleration = -1000.f; // 模拟重力影响
emitterCell.scale = 0.2;
// emitterCell.scaleRange = 0.06;
emitterCell.scaleSpeed = 0.25;
emitterCell.emissionLongitude = M_PI;
// CAEmitterCell *emitterCell = [self boomEmitterCell];
emitterCell.emitterCells = #[[self boomEmitterCell]];
return emitterCell;
}
- (CAEmitterCell *)boomEmitterCell {
// 爆炸
CAEmitterCell * explodeCell = [CAEmitterCell emitterCell];
explodeCell.name = #"explodeCell";
explodeCell.birthRate = 2.f;
explodeCell.lifetime = 0.6f;
// explodeCell.velocity = 0.f;
// explodeCell.scale = 1.0;
// explodeCell.redSpeed = -1.5; //爆炸的时候变化颜色
// explodeCell.blueRange = 1.5; //爆炸的时候变化颜色
// explodeCell.greenRange = 1.f; //爆炸的时候变化颜色
// explodeCell.birthRate = 1.0;
// explodeCell.velocity = 0;
// explodeCell.scale = 2.5;
// explodeCell.redSpeed =-1.5;
// explodeCell.blueSpeed =+1.5;
// explodeCell.greenSpeed =+1.0;
// explodeCell.lifetime = 0.35;
explodeCell.contents = (__bridge id _Nullable)[[UIImage imageNamed:#"allStart"] CGImage];
// 火花
// CAEmitterCell * sparkCell = [CAEmitterCell emitterCell];
// sparkCell.name = #"sparkCell";
//
// sparkCell.birthRate = 3.f;
// sparkCell.lifetime = 3.f;
// sparkCell.velocity = 125.f;
//// sparkCell.yAcceleration = 75.f; // 模拟重力影响
// sparkCell.emissionRange = M_PI * 2; // 360度
//
// sparkCell.scale = 1.2f;
// sparkCell.contents = (id)[[UIImage imageNamed:#"star_white_stroke"] CGImage];
// sparkCell.redSpeed = 0.4;
// sparkCell.greenSpeed = -0.1;
// sparkCell.blueSpeed = -0.1;
// sparkCell.alphaSpeed = -0.25;
// explodeCell.emitterCells = #[sparkCell];
return explodeCell;
}
I've created three sprites that works as walls in my scene. Then I have a sprite and a score. I want the sprite to set the score to 0 only when it touches the floor(one of the three sprites). So that's what I have for the contact.
- (void)didBeginContact:(SKPhysicsContact *)contact
{
SKPhysicsBody *firstBody, *secondBody;
if (contact.bodyA.categoryBitMask < contact.bodyB.categoryBitMask)
{
firstBody = contact.bodyA;
secondBody = contact.bodyB;
}
else
{
firstBody = contact.bodyB;
secondBody = contact.bodyA;
}
if ((firstBody.categoryBitMask & shipCategory) != 0 &&
(secondBody.categoryBitMask & obstacleCategory) != 0)
{
score = 0;
myLabel.text = [NSString stringWithFormat:#"%i", score];
}
}
Here are the categoryBitMask
static const uint32_t shipCategory = 0x1 << 1;
static const uint32_t obstacleCategory = 0x1 << 1;
static const uint32_t wallCategory = 0x1 << 1;
Theese are the codes for the sprite, the floor and the walls
-(SKSpriteNode *)floorNode
{
floorNode = [SKSpriteNode spriteNodeWithImageNamed:#"rectangle.png"];
floorNode.position = CGPointMake(160,100);
floorNode.physicsBody = [SKPhysicsBody bodyWithRectangleOfSize:floorNode.size];
floorNode.physicsBody.categoryBitMask = obstacleCategory;
floorNode.physicsBody.contactTestBitMask = shipCategory;
fireNode.physicsBody.usesPreciseCollisionDetection = YES;
fireNode.physicsBody.collisionBitMask = 2;
floorNode.physicsBody.dynamic = NO;
floorNode.zPosition = 1.0;
return floorNode;
}
-(SKSpriteNode *)walldxNode
{
walldxNode = [SKSpriteNode spriteNodeWithImageNamed:#"wall.png"];
walldxNode.position = CGPointMake(30, 568);
walldxNode.physicsBody = [SKPhysicsBody bodyWithRectangleOfSize:walldxNode.size];
walldxNode.physicsBody.categoryBitMask = wallCategory;
walldxNode.physicsBody.dynamic = NO;
return walldxNode;
}
-(SKSpriteNode *)wallsxNode
{
wallsxNode = [SKSpriteNode spriteNodeWithImageNamed:#"wall.png"];
wallsxNode.position = CGPointMake(290, 568);
wallsxNode.physicsBody = [SKPhysicsBody bodyWithRectangleOfSize:wallsxNode.size];
wallsxNode.physicsBody.categoryBitMask = wallCategory;
wallsxNode.physicsBody.dynamic = NO;
return wallsxNode;
}
-(SKSpriteNode *)fireButtonNode
{
fireNode = [SKSpriteNode spriteNodeWithImageNamed:#"Spaceship.png"];
fireNode.position = CGPointMake(160,450);
fireNode.xScale = 0.32;
fireNode.yScale = 0.32;
fireNode.physicsBody = [SKPhysicsBody bodyWithCircleOfRadius: fireNode.size.height/2];
fireNode.physicsBody.categoryBitMask = shipCategory;
fireNode.physicsBody.dynamic = YES;
fireNode.physicsBody.contactTestBitMask = obstacleCategory;
fireNode.physicsBody.collisionBitMask = 2;
fireNode.physicsBody.usesPreciseCollisionDetection = YES;
fireNode.name = #"fireButtonNode";//how the node is identified later
fireNode.zPosition = 2.0;
return fireNode;
}
The problem is that the sprite sets the score to 0 also when collides with the others two walls, which have differents categoryBitMask. I don't know what to do.
Your category bitmasks all have the same values. Make them differ like this:
static const uint32_t shipCategory = 0x1 << 1; // this equals 2
static const uint32_t obstacleCategory = 0x1 << 2; // this equals 4
static const uint32_t wallCategory = 0x1 << 3; // this equals 8
Batalia is correct, but these days you should probably use an enum rather than some crusty old static const. I did it in some code like this and then filed a bug against the sample code for not using Apple's own current best practices:
// These constans are used to define the physics interactions between physics bodies in the scene.
typedef NS_OPTIONS(NSUInteger, RockBusterCollionsMask) {
RBCmissileCategory = 1 << 0,
RBCasteroidCategory = 1 << 1,
RBCshipCategory = 1 << 2
};
I am trying to display multiple chart's on one screen but i am not able to get it to work. I am trying to get to a point where i have 3 x pieGraphs and 1 x scattered graph on this display.
I have tried: Unable to have two CorePlot graphs show simultaneously but not been able to solve this. I am using the example app from Core-Plot as a base for the design of the code. I see no difference when i try to emulate the solution to that problem in my code.
I am able to display the first pie chart: "matchPieChart" but not the second one "questionsPieChart". It does not look like it even process the second chart.
Without consideration of the other similar problem solution (above) the result is:
The legend on the right side is the one that is associated with the pie that is displayed to the left, i guess it hook up to the second pie that i try to display. It is displayed where the second pie chart should be displayed.
Here is the code execution, see the NSLog in the code:
iPad_matchPieChartConfiguration
numberOfRecordsForPlot:
numberOfRecordsForPlot:
numberForPlot:
numberForPlot:
numberOfRecordsForPlot:
numberOfRecordsForPlot:
legendTitleForPieChart: matchPieChart
legendTitleForPieChart: matchPieChart
iPad_questionsPieChartConfiguration
legendTitleForPieChart: matchPieChart
legendTitleForPieChart: matchPieChart
legendTitleForPieChart: matchPieChart
legendTitleForPieChart: matchPieChart
dataLabelForPlot:
dataLabelForPlot: matchPieChart
dataLabelForPlot:
dataLabelForPlot: matchPieChart
legendTitleForPieChart: matchPieChart
legendTitleForPieChart: matchPieChart
legendTitleForPieChart: matchPieChart
legendTitleForPieChart: matchPieChart
And here is the actual code:
-(void)iPad_matchPieChartConfiguration {
NSLog(#"iPad_matchPieChartConfiguration");
// Set titles
playerName_label.text = playerName;
myString = [[NSString alloc]initWithFormat:#"Total number of Games played: %.0f", nrGamesPlayed];
title_Matches_label.text = myString;
//Create host view
matchChartView = [[CPTGraphHostingView alloc] initWithFrame:[[UIScreen mainScreen]bounds]];
[self.view addSubview:matchChartView];
matchPieGraph = [[CPTXYGraph alloc] initWithFrame:CGRectZero];
matchChartView.hostedGraph = matchPieGraph;
matchPieGraph.plotAreaFrame.masksToBorder = NO;
matchPieGraph.paddingLeft = 10.0;
matchPieGraph.paddingTop = 120.0;
matchPieGraph.paddingRight = 350.0;
matchPieGraph.paddingBottom = 360.0;
matchPieGraph.axisSet = nil;
//====ADD MATCH PIE CHART====//
matchPiePlot = [[CPTPieChart alloc]init];
matchPiePlot.dataSource = self;
matchPiePlot.pieRadius = 100.0;
matchPiePlot.identifier = #"matchPieChart";
matchPiePlot.startAngle = M_PI_4;
matchPiePlot.sliceDirection = CPTPieDirectionCounterClockwise;
matchPiePlot.borderLineStyle = [CPTLineStyle lineStyle];
matchPiePlot.labelOffset = 5.0;
matchPieGraph.titleTextStyle = whiteText;
[matchPieGraph addPlot:matchPiePlot];
// 1 - Get graph instance
CPTGraph *matchGraph = matchChartView.hostedGraph;
// 2 - Create legend
CPTLegend *theMatchLegend = [CPTLegend legendWithGraph:matchGraph];
// 3 - Configure legen
CPTMutableTextStyle *legendMatchTextStyle = [CPTTextStyle textStyle];
legendMatchTextStyle.fontSize = 12.0f;
legendMatchTextStyle.fontName = #"Noteworthy-Bold";
legendMatchTextStyle.color = [CPTColor whiteColor];
theMatchLegend.numberOfColumns = 2;
theMatchLegend.fill = nil;
theMatchLegend.borderLineStyle = nil;
theMatchLegend.cornerRadius = 5.0;
theMatchLegend.textStyle = legendMatchTextStyle;
// 4 - Add legend to graph
matchGraph.legend = theMatchLegend;
matchGraph.legendAnchor = CPTRectAnchorRight;
matchGraph.legendDisplacement = CGPointMake(-460.0, -10.0);
}
-(void)iPad_questionsPieChartConfiguration {
NSLog(#"iPad_questionsPieChartConfiguration");
// Set titles
playerName_label.text = playerName;
myString = [[NSString alloc]initWithFormat:#"Total number of Questions answered: %.0f", nrQuestionsAnswered];
title_Questions_label.text = myString;
//Create host view
questionsChartView = [[CPTGraphHostingView alloc] initWithFrame:[[UIScreen mainScreen]bounds]];
[self.view addSubview:questionsChartView];
questionsPieGraph = [[CPTXYGraph alloc] initWithFrame:CGRectZero];
questionsChartView.hostedGraph = matchPieGraph;
questionsPieGraph.plotAreaFrame.masksToBorder = NO;
questionsPieGraph.paddingLeft = 10.0;
questionsPieGraph.paddingTop = 120.0;
questionsPieGraph.paddingRight = 150.0;
questionsPieGraph.paddingBottom = 360.0;
questionsPieGraph.axisSet = nil;
//====ADD MATCH PIE CHART====//
questionsPiePlot = [[CPTPieChart alloc]init];
questionsPiePlot.dataSource = self;
questionsPiePlot.pieRadius = 100.0;
questionsPiePlot.identifier = #"questionsPieChart";
questionsPiePlot.startAngle = M_PI_4;
questionsPiePlot.sliceDirection = CPTPieDirectionCounterClockwise;
questionsPiePlot.borderLineStyle = [CPTLineStyle lineStyle];
questionsPiePlot.labelOffset = 5.0;
questionsPieGraph.titleTextStyle = whiteText;
[questionsPieGraph addPlot:questionsPiePlot];
// 1 - Get graph instance
CPTGraph *questionsGraph = questionsChartView.hostedGraph;
// 2 - Create legend
CPTLegend *theQuestionsLegend = [CPTLegend legendWithGraph:questionsGraph];
// 3 - Configure legen
CPTMutableTextStyle *legendQuestionsTextStyle = [CPTTextStyle textStyle];
legendQuestionsTextStyle.fontSize = 12.0f;
legendQuestionsTextStyle.fontName = #"Noteworthy-Bold";
legendQuestionsTextStyle.color = [CPTColor whiteColor];
theQuestionsLegend.numberOfColumns = 2;
theQuestionsLegend.fill = nil;
theQuestionsLegend.borderLineStyle = nil;
theQuestionsLegend.cornerRadius = 5.0;
theQuestionsLegend.textStyle = legendQuestionsTextStyle;
// 4 - Add legend to graph
questionsGraph.legend = theQuestionsLegend;
questionsGraph.legendAnchor = CPTRectAnchorRight;
questionsGraph.legendDisplacement = CGPointMake(-160.0, -10.0);
}
- (void)viewDidLoad {
[super viewDidLoad];
playerName_label.text = playerName;
AccessPlayerData *checkPlayerDiffFunction = [AccessPlayerData new];
int diffLevel = [checkPlayerDiffFunction checkPlayersDifficultyLevel:playerName];
switch (diffLevel) {
case 1:
playerDifficulty_label.text = #"Difficuly Level: Children / Easy";
break;
case 2:
playerDifficulty_label.text = #"Difficuly Level : Teenager / Medium";
break;
case 3:
playerDifficulty_label.text = #"Difficuly Level: Adult / Hard";
break;
default:
break;
}
nrGamesPlayed_label.text = [NSString stringWithFormat:#"Total number of games played: %.0f", nrGamesPlayed];
//====IF THIS IS IPAD PROCESS ALL GRAPHS====//
if (UI_USER_INTERFACE_IDIOM() == UIUserInterfaceIdiomPad) {
double nrOfSingleGames = nrGamesPlayed -(nrGamesWon + nrGamesLost);
double nrOfTotalGames = nrGamesPlayed;
double percentageNrOfSingleGames = (nrOfSingleGames / nrOfTotalGames) * 100;
double percentageNrOfMatchGames = ((nrOfTotalGames - nrOfSingleGames) / nrOfTotalGames) * 100;
NSString *singleGames = [[NSString alloc]initWithFormat:#"%.0f (%.0f%%)", nrOfSingleGames, percentageNrOfSingleGames];
NSString *matchesGames = [[NSString alloc]initWithFormat:#"%.0f (%.0f%%)", (nrOfTotalGames - nrOfSingleGames), percentageNrOfMatchGames];
//=========ADD DATA FOR MATCHES PIE GRAPH==========//
NSMutableArray *contentMatchArray = [NSMutableArray arrayWithObjects:[NSNumber numberWithDouble:nrOfSingleGames], [NSNumber numberWithDouble:(nrOfTotalGames - nrOfSingleGames)], nil];
labelMatchOrder = [[NSArray alloc]initWithObjects:singleGames, matchesGames, nil];
legendMatchOrder = [[NSArray alloc] initWithObjects:#"Single Games", #"Matches", nil];
self.dataForMatchChart = contentMatchArray;
//=========ADD DATA FOR QUESTIONS PIE GRAPH==========//
nrQuestionsWrongAnswers = nrQuestionsAnswered - nrQuestionsCorrectAnswered;
double percentageCorrectAnswers = (nrQuestionsCorrectAnswered / nrQuestionsAnswered) * 100;
double percentageWrongAnswers = (nrQuestionsWrongAnswers / nrQuestionsAnswered) * 100;
NSString *answerCorrect = [[NSString alloc]initWithFormat:#"%.0f (%.0f%%)", nrQuestionsCorrectAnswered, percentageCorrectAnswers];
NSString *answerWrong = [[NSString alloc]initWithFormat:#"%.0f (%.0f%%)", nrQuestionsWrongAnswers, percentageWrongAnswers];
playerName_label.text = playerName;
myString = [[NSString alloc]initWithFormat:#"Total number of questions answered: %.0f",nrQuestionsAnswered];
title_Questions_label.text = myString;
NSMutableArray *contentQuestionsArray = [NSMutableArray arrayWithObjects:[NSNumber numberWithDouble:nrQuestionsWrongAnswers], [NSNumber numberWithDouble:nrQuestionsCorrectAnswered], nil];
labelQuestionsOrder = [[NSArray alloc]initWithObjects:answerWrong, answerCorrect, nil];
legendQuestionsOrder = [[NSArray alloc] initWithObjects:#"Correct answers", #"Wrong answers", nil];
self.dataForQuestionsChart = contentQuestionsArray;
NSLog(#"ContentQuestionsArray: %#", contentQuestionsArray);
//====SET GLOBAL PARAMETERS FOR THE GRAPHs====//
whiteText = [CPTMutableTextStyle textStyle];
whiteText.color = [CPTColor whiteColor];
whiteText.fontSize = 14;
whiteText.fontName = #"Noteworthy-Bold";
[self iPad_matchPieChartConfiguration];
[self iPad_questionsPieChartConfiguration];
}
}
#pragma mark -
#pragma mark Plot Data Source Methods
-(NSString *)legendTitleForPieChart:(CPTPieChart *)pieChart recordIndex:(NSUInteger)index {
if ( [matchPiePlot.identifier isEqual:[NSString stringWithFormat:#"matchPieChart"]] ) {
NSLog(#"legendTitleForPieChart: matchPieChart");
if (index < [legendMatchOrder count]) {
return [legendMatchOrder objectAtIndex:index];
}
}
else if ( [matchPiePlot.identifier isEqual:[NSString stringWithFormat:#"questionsPieChart"]] ) {
NSLog(#"legendTitleForPieChart: questionsPieChart");
}
return #"N/A";
}
-(NSUInteger)numberOfRecordsForPlot:(CPTPlot *)plot {
NSLog(#"numberOfRecordsForPlot:");
if ([plot isKindOfClass:[CPTPieChart class]]) {
return [dataForMatchChart count];
}
else {
return 10; //>>>dummy
}
}
-(NSNumber *)numberForPlot:(CPTPlot *)plot field:(NSUInteger)fieldEnum recordIndex:(NSUInteger)index {
NSLog(#"numberForPlot:");
NSDecimalNumber *num = nil;
if ([plot isKindOfClass:[CPTPieChart class]]) {
if (index >= [dataForMatchChart count]) {
return nil;
}
if (fieldEnum == CPTPieChartFieldSliceWidth) {
num = [dataForMatchChart objectAtIndex:index];
}
else {
num = (NSDecimalNumber *) [NSDecimalNumber numberWithUnsignedInteger:index];
}
}
return num;
}
-(CPTLayer *)dataLabelForPlot:(CPTPlot *)plot recordIndex:(NSUInteger)index {
NSLog(#"dataLabelForPlot:");
CPTTextLayer *label = nil;
if ( [plot.identifier isEqual:[NSString stringWithFormat:#"matchPieChart"]] ) {
NSLog(#"dataLabelForPlot: matchPieChart");
label = [[CPTTextLayer alloc] initWithText:[labelMatchOrder objectAtIndex:index]];
CPTMutableTextStyle *textStyle = [label.textStyle mutableCopy];
matchPiePlot.labelOffset = -80;
textStyle.fontName = #"Noteworthy-Bold";
textStyle.color = [CPTColor whiteColor];
textStyle.fontSize = 16;
label.textStyle = textStyle;
return label;
}
else if ( [plot.identifier isEqual:[NSString stringWithFormat:#"matchPieChart"]] ) {
NSLog(#"dataLabelForPlot: MATCH");
}
return label;
}
//====SET COLOR FOR SLICES IN PIE GRAPH====//
-(CPTFill *)sliceFillForPieChart:(CPTPieChart *)pieChart recordIndex:(NSUInteger)index {
// For index = 0
double red1 = 222.0;
double green1 = 184.0;
double blue1 = 135.0;
float alpha1 = 0.5f;
double red2 = 155.0;
double green2 = 00.0;
double blue2 = 0.0;
float alpha2 = 0.3f;
if (index == 0) {
CPTFill *fill = [CPTFill fillWithColor:[CPTColor colorWithComponentRed:red1 green:green1 blue:blue1 alpha:alpha1]];
return fill;
}
if (index == 1) {
CPTFill *fill = [CPTFill fillWithColor:[CPTColor colorWithComponentRed:red2 green:green2 blue:blue2 alpha:alpha2]];
return fill;
}
return 0;
}
I am really struggling with this and would appreciate help :-)
Change this line
questionsChartView.hostedGraph = matchPieGraph;
to
questionsChartView.hostedGraph = questionsPieGraph;
Also, check how the two hosting views are laid out within their superview (self.view). Make sure both are visible and positioned correctly.
I am a beginner in cocos2d and im facing a problem with detecting collision for my coins.
Sometimes it works sometimes it doesn't.
So basically, im creating a game which the user (ship) have to avoid the obstacles and collect coins on the way. The collision of the obstacle works well but not for the coins.
I was thinking maybe the loops for creating many coins is the problem but im not sure.
Can anyone help?
My codes:
- (void)update:(ccTime)dt{
double curTime = CACurrentMediaTime();
if (curTime > _nextBridgeSpawn) {
float randSecs = [self randomValueBetween:3.0 andValue:5.0];
_nextBridgeSpawn = randSecs + curTime;
float randX = [self randomValueBetween:50 andValue:500];
float randDuration = [self randomValueBetween:8.0 andValue:10.0];
CCSprite *bridge = [_bridge objectAtIndex:_nextBridge];
_nextBridge++;
if (_nextBridge >= _bridge.count) _nextBridge = 0;
[bridge stopAllActions];
bridge.position = ccp(winSize.width/2, winSize.height);
bridge.visible = YES;
[bridge runAction:[CCSequence actions:
[CCMoveBy actionWithDuration:randDuration position:ccp(0, -winSize.height)],
[CCCallFuncN actionWithTarget:self selector:#selector(setInvisible:)],
nil]];
this is where i declare my coins (continued from the update method)
int randCoin = [self randomValueBetween:0 andValue:5];
_coin = [[CCArray alloc] initWithCapacity:randCoin];
for(int i = 0; i < randCoin; ++i) {
coin = [CCSprite spriteWithFile:#"coin.png"];
coin.visible = NO;
[self addChild:coin];
[_coin addObject:coin];
}
float randCoinX = [self randomValueBetween:winSize.width/5 andValue:winSize.width - (border.contentSize.width *2)];
float randCoinY = [self randomValueBetween:100 andValue:700];
float randCoinPlace = [self randomValueBetween:30 andValue:60];
for (int i = 0; i < _coin.count; ++i) {
CCSprite *coin2 = [_coin objectAtIndex:i];
coin2.position = ccp(randCoinX, (bridge.position.y + randCoinY) + (randCoinPlace *i));
coin2.visible = YES;
[coin2 runAction:[CCSequence actions:
[CCMoveBy actionWithDuration:randDuration position:ccp(0, -winSize.height-2000)],
[CCCallFuncN actionWithTarget:self selector:#selector(setInvisible:)],
nil]];
}
}
this is to check for collision (also in the update method)
for (CCSprite *bridge in _bridge) {
if (!bridge.visible) continue;
if (CGRectIntersectsRect(ship.boundingBox, bridge.boundingBox)){
bridge.visible = NO;
[ship runAction:[CCBlink actionWithDuration:1.0 blinks:5]];
}
}
}
//this is the collision for coins which only work at times
for (CCSprite *coin2 in _coin) {
if (!coin2.visible) continue;
if (CGRectIntersectsRect(ship.boundingBox, coin2.boundingBox)) {
NSLog(#"Coin collected");
coin2.visible = NO;
}
}
}
Thank you.
Why you just don't check distances?
float dist = ccpDistance(ship.position, coin2.position);
float allowedDist = ship.contentSize.width*0.5 + coin2.contentSize.width*0.5;
if (dist<allowedDist){
NSLog(#"Collision detected");
}
If your sprites are not on the same layer, these layers should have at least same positions.
what is phone in the last piece of code? you check there if it's boundingBox intersects coins one, but I cannot see it anywhere else. Another one, boundingBox will work only if your objects have the same parent, because it returns "local" rect, relatieve to it's parent
another one point is that in case of too fast movement speed of your objects it is possible, that they will pass throw each other during tick time. I mean, that one update will be called before collision, so it will not detect it and the next one will be called after collision was finished, so it will not detect it either.
I've solved my problem by creating a timer in init and call it every 10 secs to create my coins.
My codes:
-(void) createCoins:(ccTime)delta{
CGSize winSize = [CCDirector sharedDirector].winSize;
int randCoin = [self randomValueBetween:0 andValue:10];
_coin = [[CCArray alloc] initWithCapacity:randCoin];
for(int i = 0; i < randCoin; i++) {
coin = [CCSprite spriteWithFile:#"coin30p.png"];
coin.visible = NO;
[self addChild:coin];
[_coin addObject:coin];
}
float randCoinX = [self randomValueBetween:winSize.width/5 andValue:winSize.width - (border.contentSize.width *2)];
float randCoinY = [self randomValueBetween:100 andValue:700];
float randCoinPlace = [self randomValueBetween:30 andValue:60];
for (int i = 0; i < _coin.count; i++) {
CCSprite *coin2 = [_coin objectAtIndex:i];
coin2.position = ccp(randCoinX, (winSize.height + randCoinY) + (randCoinPlace *i));
coin2.visible = YES;
[coin2 runAction:[CCSequence actions:
[CCMoveBy actionWithDuration:8 position:ccp(0, -winSize.height-2000)],
[CCCallFuncN actionWithTarget:self selector:#selector(setInvisible:)],
nil]];
}
}
in the update method:
for (CCSprite *coins in _coin){
if (!coins.visible) continue;
if (CGRectIntersectsRect(phone.boundingBox, coins.boundingBox)) {
NSLog(#"Coin collected");
coins.visible = NO;
}
}
Thank you everyone for the help(:
i'm programming a little game. you can shoot little bullets which should disappear when hitting an object. the problem is when i destroy the bodies (directly or first storing them into an array) i get errors within the CreateFixture() function for creating new bullets.
The code:
-(void)tick:(ccTime)deltaTime {
if(canShoot)
[self performPistol];
[self updatePositions:deltaTime];
[self collisionDetection];
}
-(void)updatePositions:(ccTime)deltaTime {
int32 velocityIterations = 8;
int32 positionIterations = 1;
world->Step(deltaTime, velocityIterations, positionIterations);
for(id object in _objectsToDelete) {
b2Body *body = (b2Body*)[object pointerValue];
[self removeChild:((CCSprite*)body->GetUserData()) cleanup:YES];
world->DestroyBody((b2Body*)[object pointerValue]);
}
[_objectsToDelete removeAllObjects];
}
-(void)collisionDetection {
for (b2Contact* c = world->GetContactList(); c; c = c->GetNext()) {
b2Body *a = c->GetFixtureA()->GetBody();
b2Body *b = c->GetFixtureB()->GetBody();
CCSprite *aSprite = (CCSprite*)a->GetUserData();
CCSprite *bSprite = (CCSprite*)b->GetUserData();
if([[aSprite class] isSubclassOfClass:[Bullet class]]) {
if([[bSprite class] isSubclassOfClass:[Zombie class]]) {
Zombie *myZombie = (Zombie*)bSprite;
myZombie.hp -= [(Bullet*)aSprite strength];
if(myZombie.hp <= 0) {
[_objectsToDelete addObject:[NSValue valueWithPointer:b]];
}
}
[_objectsToDelete addObject:[NSValue valueWithPointer:a]];
} else if([[bSprite class] isSubclassOfClass:[Bullet class]]) {
if([[aSprite class] isSubclassOfClass:[Zombie class]]) {
Zombie *myZombie = (Zombie*)aSprite;
myZombie.hp -= [(Bullet*)bSprite strength];
if(myZombie.hp <= 0) {
[_objectsToDelete addObject:[NSValue valueWithPointer:a]];
}
}
[_objectsToDelete addObject:[NSValue valueWithPointer:b]];
}
}
}
-(void)performPistol {
float degreeRadians = _myRotation*(M_PI/180.0);
CGPoint normalVector = ccp(cosf(degreeRadians),sinf(degreeRadians));
Bullet *bullet = [[Bullet alloc] initWithFile:#"bullet_line.png"];
bullet.strength = 1;
bullet.position = ccp(_myPosition.x+(normalVector.x*25.0),_myPosition.y+(normalVector.y*25.0));
bullet.rotation = _myRotation*(-1);
b2BodyDef bodyDef;
bodyDef.type = b2_dynamicBody;
bodyDef.bullet = true;
bodyDef.position.Set(bullet.position.x/PTM_RATIO, bullet.position.y/PTM_RATIO);
bodyDef.userData = bullet;
b2Body *body = world->CreateBody(&bodyDef);
// Define another box shape for our dynamic body.
b2PolygonShape box;
box.SetAsBox(6.25/PTM_RATIO, 0.5/PTM_RATIO);
// Define the dynamic body fixture.
b2FixtureDef fixtureDef;
fixtureDef.shape = &box;
fixtureDef.density = 1.0f;
fixtureDef.friction = 0.3f;
fixtureDef.filter.categoryBits = MASK_PLAYER;
fixtureDef.filter.maskBits = MASK_ENEMY | MASK_WALL;
body->CreateFixture(&fixtureDef);
body->SetLinearVelocity(b2Vec2(normalVector.x*50.0,normalVector.y*50.0));
body->SetTransform(body->GetPosition(), CC_DEGREES_TO_RADIANS(-bullet.rotation));
[self addChild:bullet];
}
Why are there errors in the CreateFixture() function. end not always the same sometimes an assert error sometimes an exc_bad_access?
thanks