SpriteKit Block positioning - sprite-kit

I am trying to make a jump game in Xcode 5 with SpriteKit.
First I want to spawn Blocks in a random position, but reachable for the 'human' in the game that is jumping.
I got a 1. Block, that spawn at a set position. From this position, there should spawn a 2. Block, that can be + or - 80 higher or lower, and < 80 away. Now here is the problem, I don`t know how to code it in Xcode. My code so far :
SKTexture * BlockTexture1 = [SKTexture textureWithImageNamed:#"Block"];
BlockTexture1.filteringMode = SKTextureFilteringNearest;
SKTexture * BlockTexture2 = [SKTexture textureWithImageNamed:#"Block"];
BlockTexture2.filteringMode = SKTextureFilteringNearest;
SKSpriteNode * Block1 = [SKSpriteNode spriteNodeWithTexture:BlockTexture1];
[Block1 setScale:1];
Block1.position = CGPointMake( 100 , 150 );
Block1.physicsBody = [SKPhysicsBody bodyWithRectangleOfSize:Block1.size];
Block1.physicsBody.dynamic = NO;
Block1.physicsBody.usesPreciseCollisionDetection = YES;
Block1.zPosition = 3;
[self addChild:Block1];
SKSpriteNode * Block2 = [SKSpriteNode spriteNodeWithTexture:BlockTexture2];
[Block2 setScale:1];
Block2.position = CGPointMake( **Block1 + or - 80, Block 1 < 80** );
Block2.physicsBody = [SKPhysicsBody bodyWithRectangleOfSize:Block2.size];
Block2.physicsBody.dynamic = NO;
Block2.physicsBody.usesPreciseCollisionDetection = YES;
Block2.zPosition = 3;
[self addChild:Block2];

To get your started, something like this perhaps:
int block1x = 100;
int block1y = 150;
Block1.position = CGPointMake(block1x, block1y);
int block2x = 0;
int block2y = 0;
int r1 = arc4random() % 2; // produces random numbers between 0 and 1
if(r1 == 0)
block2x = block1x + 80;
if(r1 == 1)
block2x = block1x - 80;
int r2 = arc4random() % 2;
if(r2 == 0)
block2y = block1y + 80;
if(r2 == 1)
block2y = block1y - 80;
Block2.position = CGPointMake(block2x, block2y);

Related

moving a ball in a grid xcode

I am trying to build an iphone app which has a grid of 5 columns up and down and 8 rows back and forth. I want to have a ball be able to traverse on these continuously. I'm sure there must be some way to do this that is already figured out and if someone knows of one let me know. I am currently using a ball for each column and each row with if statements that hide/show the various balls. So I can have the ball go across on row one and when it comes to a column it stops is hidden and the ball in that column is shown and moves up and down. The same with the ball in column one. As it moves up and down when it comes to a row it is hidden and the ball in that row is shown and moves across. When it gets back to row one it is hidden and the ball in row one starts moving up and down again. My problem is having the balls show/hide on the interior intersections i.e. row two column two, row two column three etc.
Any suggestions. On how to accomplish this.
I am using accelerometer motion.gravity to move the ball images vertical and horizontally.
this is some code I use to move the balls
if (ball.hidden == NO) {
self.ball.center = CGPointMake(self.ball.center.x + n, 9);
}
//ROW ONE START
if (ball.center.x < 9) {
ball.center = CGPointMake(9, 9);
}
if (ball.center.x > 311) {
ball.center = CGPointMake(311, 9);
}
if(self.ball.center.x > 9){
self.balla.hidden = YES;
balla.center = CGPointMake(9, 9);
}
if (ball.center.x ==9) {
//balla
CGPoint a = CGPointMake(9, 9);
if (CGPointEqualToPoint(ball.center,a)) {
balla.hidden = NO;
self.balla.center = CGPointMake(9, (self.balla.center.y)- y);
if (balla.center.y > 9) {
ball.center = CGPointMake(9,9);
ball.hidden = YES;
balla.hidden = NO;
self.balla.center = CGPointMake(9 , (self.balla.center.y)- y);
}
if (balla.center.y < 9) {
balla.center = CGPointMake(9,9);
ball.hidden = NO;
}
if (balla.center.y > 559) {
balla.center = CGPointMake(9, 559);
}
}
this is for the first row and the first column (there are additional columns here)
I also do additional rows
I have gotten the last column to move into the seventh and eighth rows with this code.
CGPoint e = CGPointMake(311, 9);
if (CGPointEqualToPoint(ball.center,e)) {
ball5a.hidden = YES;
self.ball5a.center = CGPointMake(311, (self.ball5a.center.y)- y);
if(self.ball.center.x < 311){
self.ball5a.hidden = YES;
}
if (ball5a.center.y < 9) {
ball5a.center = CGPointMake(311,9);
ball.hidden = NO;
ball5a.hidden = YES;
}
if (ball5a.center.y > 9) {
ball.center = CGPointMake(311,9);
ball5a.hidden = NO;
ball.hidden = YES;
self.ball5a.center = CGPointMake(311, (self.ball5a.center.y)- y);
}
if (self.ball5a.center.y> 480 && self.ball5a.center.y< 482) {
ball7.hidden = NO;
balla.center = CGPointMake(9, 481);
ball7.center = CGPointMake(311 , 481);
ball.center = CGPointMake(9, 9);
}
if (ball5a.center.y > 559) {
ball5a.center = CGPointMake(311, 559);
ball8.center = CGPointMake(311, 559);
ball.center = CGPointMake(9, 9);
}
if (ball5a.center.y <559) {
ball8.center =CGPointMake(9, 559);
ball.center = CGPointMake(311, 9);
ball8.hidden = YES;
}
and I can get the last row to move onto the last column with this
//ROW EIGHT START
CGPoint l = CGPointMake(9, 559);
if (CGPointEqualToPoint(balla.center,l)) {
balla.hidden = YES;
balla.center = CGPointMake(9, 559);
self.ball8.center = CGPointMake(self.ball8.center.x + n, 559);
ball8.hidden = NO;
}
if (ball8.center.x > 9) {
self.ball8.center = CGPointMake(self.ball8.center.x + n, 559);
balla.hidden = YES;
balla.center = CGPointMake(9, 559);
}
if (ball8.center.x < 10) {
ball8.center = CGPointMake(9, 559);
ball8.hidden = YES;
balla.hidden = NO;
}
if (ball8.center.x > 311) {
ball8.center = CGPointMake(311, 559);
ball5a.center = CGPointMake(311, 559);
ball5a.hidden = YES;
ball.center = CGPointMake(311, 9);
ball8.hidden = NO;
}
if (ball8.center.x < 311) {
ball5a.center = CGPointMake(311, 9);
ball5a.hidden = YES;
}
}
However when I try to move row seven onto column 5 I can get it to transfer but the ball in column 5 always ends up at coordinate (311,9) instead of the coordinate (311,481) that I specify in multiple places.
//ROW SEVEN START
CGPoint k = CGPointMake(9, 481);
if (CGPointEqualToPoint(balla.center,k)) {
ball5a.center = CGPointMake(311, 481);
balla.hidden = YES;
balla.center = CGPointMake(9, 481);
self.ball7.center = CGPointMake(self.ball7.center.x + n, 481);
ball7.hidden = NO;
}
if (ball7.center.x > 9) {
self.ball7.center = CGPointMake(self.ball7.center.x + n, 481);
balla.hidden = YES;
balla.center = CGPointMake(9, 481);
}
if (ball7.center.x < 10) {
ball7.center = CGPointMake(9, 481);
ball5a.center = CGPointMake(311, 481);
ball7.hidden = YES;
balla.hidden = NO;
}
if (ball7.center.x > 310) {
ball.center = CGPointMake(311, 9);
ball5a.center = CGPointMake(311, 481);
ball7.center = CGPointMake(311, 481);
ball5a.hidden = YES;
balla.center = CGPointMake(9, 481);
ball7.hidden = NO;
}
if (ball7.center.x < 310) {
ball5a.center = CGPointMake(311, 481);
ball5a.hidden = YES;
}
any ideas why this in not working right?
You could use double arrays, or a matrix (the same thing here, just another name) where an entry could either be null or your ball.
When you draw you will traverse the array and look at each entry, if the entry is null; you draw nothing. If the entry is not-null i.e. it is something, namely your ball, then draw it in that position the entry denotes.
We can use the double array to describe a coordinate system, or a grid, with columns and rows.
Consider an entry (i,j) to be column i and row j in your grid. So if the ball is in entry (2,4) it means that the ball is currently in column 2 and row 4, if we want to move the ball to another column or row, we simply set the entry (2,4) to be null and the set the desired entry, for instance (2,5) to be our ball.
And another thing, we can simply let null = 0 and the ball = 1 in our arrays, since the ball can be kept as a global variable somehow.
int matrix[20][20];
The above line will create an matrix/double-array of type int with the size of 20 columns and 20 rows.
Note that it would be good practice to run through every entry and set them to some init value, 0 in our case, I will not show that here. Consider it as an exercise ;)
Now we can position the ball somewhere:
matrix[2][4] = 1;
Now our ball is in column 2 and row 4.
If we want to move it to column 10 and row 15:
matrix[2][4] = 0; // Remember to remove the ball from its last position
matrix[10][15] = 1;
When you want to draw the ball you can run through the matrix/array and look at each entry and only draw the ball if the entry contains the number 1.
Even after you posted your code I was still slightly confused of what your exact problem/question was, but I hope this makes sense and helps!

Sprites are disappear after some time

Here some code for Add sprite for Enemies.....
_robbers = [[CCArray alloc] initWithCapacity:kNumAstroids];
for (int i = 0; i < kNumAstroids; ++i) {
CCSprite *asteroid = [CCSprite spriteWithSpriteFrameName:#"robber.png"];
asteroid.visible = NO;
[_batchNode addChild:asteroid];
[_robbers addObject:asteroid];
}
And in Update method ........
double curTime = CACurrentMediaTime();
if (curTime > _nextRunemanSpawn) {
float randSecs = [self randomValueBetween:0.20 andValue:1.0];
_nextRunemanSpawn = randSecs + curTime;
float randY = [self randomValueBetween:80 andValue:80];
float randDuration = [self randomValueBetween:4.5 andValue:4.5];
float randDuration1 = [self randomValueBetween:1.0 andValue:1.0];
CCSprite *asteroid = [_robbers objectAtIndex:_nextRobber];
_nextRobber++;
if (_nextRobber >= _robbers.count) {
_nextRobber = 1;
}
[asteroid stopAllActions];
asteroid.position = ccp(winSize.width +asteroid.contentSize.width / 2 , randY);
asteroid.visible = YES;
[asteroid runAction:[CCSequence actions:[CCMoveBy actionWithDuration:randDuration position:ccp(-winSize.width-asteroid.contentSize.width, 0)],
[CCCallFuncN actionWithTarget:self selector:#selector(setInvisible:)],nil]];
All Sprites are Move from right to left in screen
when Sprite crosses the middle of the screen it automatically disappear
what is the reason for this problem ??
I agree with the previously mentioned statement from LearnCocos2D. It is also possible that you are adding multiple objects and reaching the end of the capacity in the line
_robbers = [[CCArray alloc] initWithCapacity:kNumAstroids];
If you try to spawn more objects than whatever number you have specified for kNumAsteroids it will remove the oldest object and use the new one in its place. I.e. if kNumAsteroids is 5, you have 5 on the screen and then add a sixth, 1 will become 6 and its position will be whatever you set it to.

Show UIImageView in a random position on the screen

I am developing a game that uses the gyroscope to keep enemies in relatively the same place, with the following code:
if([motionManager isGyroAvailable])
{
[motionManager setGyroUpdateInterval:0.05];
[motionManager startGyroUpdatesToQueue:[NSOperationQueue mainQueue]
withHandler:^(CMGyroData *gyroData, NSError *error)
{
valueX3 = gyroData.rotationRate.y* 50;
valueY3 = gyroData.rotationRate.x* 50;
int newX3 = (int)(enemyufoG.center.x +valueY3);
int newY3 = (int)(enemyufoG.center.y -valueX3);
CGPoint newCenter2 = CGPointMake(newX3, newY3);
enemyufoG.center = newCenter2;
valueX2 = gyroData.rotationRate.y* 50;
valueY2 = gyroData.rotationRate.x* 50;
int newX2 = (int)(enemyufoR.center.x +valueY2);
int newY2 = (int)(enemyufoR.center.y -valueX2);
CGPoint newCenter = CGPointMake(newX2, newY2);
enemyufoR.center = newCenter;
valueX = gyroData.rotationRate.y* 50;
valueY = gyroData.rotationRate.x* 50;
int newX = (int)(enemyAlien.center.x +valueY);
int newY = (int)(enemyAlien.center.y -valueX);
CGPoint newCenter3 = CGPointMake(newX, newY);
enemyAlien.center = newCenter3;
}];
}
Once you shoot an enemy that is in the crosshairs of the gun, it hides the UIImageView, then uses NSTimer to call a different method that shows it again. I would like to have the enemies reappear in random positions on the screen.
CGPoint pos = enemyAlien.center;
if ((pos.x > 254) && (pos.x < 304) && (pos.y > 140) && (pos.y < 160 && _ammoCount != 0))
{
enemyAlien.hidden = YES;
[dangerBar setProgress:dangerBar.progress-0.10];
_killCount = _killCount+3;
[killCountField setText: [NSString stringWithFormat:#"%d", _killCount]];
timer = [NSTimer scheduledTimerWithTimeInterval: 4.0
target: self
selector: #selector(showAlien)
userInfo: nil
repeats: NO];
}
- (void) showAlien {
enemyAlien.hidden = NO;
}
When I try and use enemyAlien.center = enemyAlien.center + arc4random()%100; above enemyAlien.hidden = NO, I get the following error:
'Invalid operands to binary expression ('CGPoint (aka 'struct CGPoint') and 'unsigned int').
You're trying to add an integer to a cgpoint.
try this.
enemyAlien.center = CGPointMake(enemyAlien.center.x + (arc4random()%100),enemyAlien.center.y + (arc4random()%100));
although this will only move the alien in a diagonal direction. You should probably change it to the following for a better experience.
enemyAlien.center = CGPointMake((arc4random()%SCREEN_WIDTH),(arc4random()%SCREEN_HEIGHT));
where SCREEN_WIDTH and SCREEN_HEIGHT are the dimensions of your playing field.

iPhone:How can I shuffle buttons in view

I have many no. of buttons on my view and I want to shuffle the buttons(change in position) then how can I shuffle the button in my view.
use arc4random()
and change position of your buttons
In your .h file : UIButton *buttonsarray[10];
In your .m file :
// Make array of button using following way.I used this method to creates button and you can use yours.
- (void)viewDidLoad {
[super viewDidLoad];
float y = 5;
int x = 0;
int count = 0;
for (int i = 0 ; i < 10; i++)
{
count ++;
buttonsarray[i] = [UIButton buttonWithType:UIButtonTypeRoundedRect];
buttonsarray[i].frame = CGRectMake(x, y, 100, 100);
[buttonsarray[i] setTitle:[NSString stringWithFormat:#"%d",i+1] forState:UIControlStateNormal];
x = x + 105;
[self.view addSubview:b[i]];
if(count == 3)
{
count = 0;
x = 0;
y = y+ 105;
}
}
}
// This function will soufflé your buttons
- (IBAction)btnClicked:(id)sender
{
int n = 10;
int swaper;
for (int i = 0 ; i < 10 ; i++)
{
int r = arc4random()%n;
if(r != swaper){
swaper = r;
CGRect r1 = buttonsarray[i].frame;
buttonsarray[i].frame = buttonsarray[swaper].frame;
buttonsarray[swaper].frame = r1;
n--;
}
}
}
Hope,this will help you..
You can do this
Make an Array with a group of CGPoints you will need to store the points as strings.
In the layoutSubViews method set something like this:
-(void)layoutSubViews{
[self.subviews enumerateObjectsUsingBlock:^(id object, NSUInteger idx, BOOL *stop) {
CGPoint newPoint = CGPointFromString([positionsArray objectAtIndex:idx]);
object.frame = CGRectMake(newPoint.x,newPoint.y,object.frame.size.width,object.frame.size.height);
}];
}
Then you will need to shuffle the positions in the positions array, you can see an example method here :How to Shuffle an Array
Now every time you need to Shuffle the positions you can call -(void)setNeedsLayout on your view.
There are more options but that was the first I thought of.
Good Luck

How to implement powerUps and other game altering objects in objective-C or cocos2d

Ok, so I have these powerups that I want to slow/speed up the movement of the other objects in the game for a few seconds.
I have an array of objects that I have a variable called spawnInterval that gets faster and faster as the game progresses, making the ame get harder after a few mins.
But I can't really grasp how to make it so the character in the game will react differently to different objects as in when the fastPowerUp is hit by the character sprite, the spawn interval doesn't change.
And vice versa with the slowPowerUp.
the code I have at the moment is this in a move sequence method that gets called in an update method:
-
(void) updateObstacles:(ccTime)delta{
for (int i = 0; i < 20; i++) {
//int randomizer = CCRANDOM_0_1() * [obstacles count];
//NSLog(#"randomizer: %i",randomizer);
CCSprite* randomObject = [obstacles randomObject];
currentObject = [obstacles indexOfObject:randomObject];
if ([randomObject numberOfRunningActions] == 0) {
[self runObstacleMoveSequence:randomObject withTimer:delta];
break;
}
}
}
-(void) runObstacleMoveSequence:(CCSprite *)object withTimer:(ccTime)delta{
static int time;
//Slowly increase object speed
numObstaclesMoved++;
if (!slowPowerUp && !fastPowerUp) {
time += delta;
if (numObstaclesMoved % 17 == 0 && obstacleMoveDuration > 2.0f) {
obstacleMoveDuration -= 0.2f;
if (spawnInterval > 0.1f) {
[self unschedule:#selector(updateObstacles:)];
[self schedule:#selector(updateObstacles:) interval:spawnInterval];
spawnInterval-=0.1f;
NSLog(#"interval: %f",spawnInterval);
}
}
}else if (slowPowerUp && !fastPowerUp) {
if (numObstaclesMoved % 17 == 0 && obstacleMoveDuration > 2.0f) {
obstacleMoveDuration += 3.0f;
if (spawnInterval > 0.1f) {
[self unschedule:#selector(updateObstacles:)];
[self schedule:#selector(updateObstacles:) interval:spawnInterval];
spawnInterval-=0.1f;
NSLog(#"interval: %f",spawnInterval);
if (time >= (delta + 3)) {
slowPowerUp = NO;
obstacleMoveDuration -= 3.0f;
}
}
}
}else if (!slowPowerUp && fastPowerUp) {
if (numObstaclesMoved % 17 == 0 && obstacleMoveDuration > 2.0f) {
obstacleMoveDuration -= 3.0f;
if (spawnInterval > 0.1f) {
[self unschedule:#selector(updateObstacles:)];
[self schedule:#selector(updateObstacles:) interval:spawnInterval];
spawnInterval-=0.1f;
NSLog(#"interval: %f",spawnInterval);
if (time >= (delta + 3)) {
fastPowerUp = NO;
obstacleMoveDuration += 3.0f;
}
}
}
}
CGSize screenSize = [[CCDirector sharedDirector]winSize];
CGPoint aboveScreenPosition = CGPointMake(object.position.x, screenSize.height - object.position.y);
int rotations = (CCRANDOM_0_1()*3) * 360;
float duration = (CCRANDOM_0_1()*5.0f) + 8.0f;
CCMoveTo* move = [CCMoveTo actionWithDuration:obstacleMoveDuration position:aboveScreenPosition];
CCRotateTo* rotate = [CCRotateBy actionWithDuration:duration angle:rotations];
CCSpawn* moveRotate = [CCSpawn actions: move, rotate, nil];
CCCallFuncN* call = [CCCallFuncN actionWithTarget:self selector:#selector(objectAboveScreen:)];
CCSequence* sequence = [CCSequence actions:moveRotate, call, nil];
[object runAction:sequence];
if (time >= (delta + 3)) {
fastPowerUp = NO;
}
}
-(void) objectAboveScreen:(id) sender{
//make sure sender is actually of the right class
NSAssert([sender isKindOfClass:[CCSprite class]], #"sender is not a CCSprite!");
CCSprite* obstacle = (CCSprite*)sender;
//move the back to the bottom of the screen
CGPoint pos = obstacle.position;
CGSize screenSize = [[CCDirector sharedDirector]winSize];
pos.y = (-screenSize.height - [obstacle texture].contentSize.height);
pos.x = CCRANDOM_0_1() * screenSize.width;
obstacle.position = pos;
}
I really just don't know where to go from here... Should I make the powerUps a different class? If so, how would I implement something like this? I really hate trying to ask for someone to solve my question, but I really just can't rack my brain around this and I'm rather new... if it were explained to me, then I know I would be able to implement it in future games on my own...
Thanks in advance, and let me know if more information is needed...
I'd do something like
in the .h file
float speedModifier;
-(void)resetPowerUp;
in the .m
-(void)resetPowerUp
{
speedModifier = 1;
}
wherever you are initializing the level
[self resetPowerUp];
upon collision with powerup:
speedModifier = 2;
[self performSelector:#selector(resetPowerUp) withObject:nil afterDelay:5];
then wherever you are moving whatever it is which speed should be effected by the powerup mode, multiply the speed of the animation (or divide the duration it takes for it to get wherever it's going) by speedModified
hope that helps