I am currently making a game in sprite kit and i have 8 methods, I have written all the timing code E.T.C so it calls a method every 1 second, but i want it to call a random one of the eight methods, I have been trying to get this working for weeks, any help would be muchly appreciated, Here is my timing code -
- (void)updateWithTimeSinceLastUpdate:(CFTimeInterval)timeSinceLast {
self.lastSpawnTimeInterval += timeSinceLast;
if (self.lastSpawnTimeInterval > 5) {
self.lastSpawnTimeInterval = 0;
[self shoot1];
}
}
- (void)update:(NSTimeInterval)currentTime {
// Handle time delta.
// If we drop below 60fps, we still want everything to move the same distance.
CFTimeInterval timeSinceLast = currentTime - self.lastUpdateTimeInterval;
self.lastUpdateTimeInterval = currentTime;
if (timeSinceLast > 1) { // more than a second since last update
timeSinceLast = 1.0 / 60.0;
self.lastUpdateTimeInterval = currentTime;
}
[self updateWithTimeSinceLastUpdate:timeSinceLast];
}
As you can see instead of [self shoot1]i want it to randomly call one of the eight methods, Also all the methods are named Shoot1, Shoot2, all the way to Shoot8. Thankyou
I can think of two options...
Option 1
Just pick a random number between 1 and 8, and use a switch statement:
- (void)updateWithTimeSinceLastUpdate:(CFTimeInterval)timeSinceLast {
self.lastSpawnTimeInterval += timeSinceLast;
if (self.lastSpawnTimeInterval > 5) {
self.lastSpawnTimeInterval = 0;
int randomNumber = arc4random_uniform(8);
switch(randomNumber) {
case 0:
[self shoot1];
break;
case 1:
[self shoot2];
break;
// ... cases 2-6
case 7:
[self shoot8];
break;
}
}
}
Option 2
Rewrite your shootN methods so that you only have one method that takes an integer as a parameter:
- (void)shoot:(int)index;
Then, you can just do the following:
[self shoot:arc4random_uniform(8)];
You could also live dangerously...
int random = arc4random() % 8;
NSString *selectorName = [NSString stringWithFormat:#"shoot%i", random];
SEL selector = NSSelectorFromString(selectorName);
if ([self respondsToSelector:selector]) {
[self performSelector:selector];
}
This will, by the way, generate a warning when using ARC.
Related
i am using an UIslider first time.
first i want to know how to gat value of slider positon if the range of value is 0 to 10:
second i want my slider just set at 5 different values .
like 1, 2, 3, 4, 5
slider should not set between the labeled value
first u set textfiled and add this function into code
-(IBAction)changeSlider:(id)sender
{
text_field .text= [[NSString alloc] initWithFormat:#" Value %d ", (int)slider.value];
}
I followed this tutorial for mine and it was very helpful there are variables you can set in the code such as max number and how much the slider increases each time. Link: http://www.xprogress.com/post-35-uislider-tutorial-example-how-to-use-slider-in-iphone-sdk-xcode/
In this case I set the slider in XCode to have values of: 0-3. But the slider value is float: 0.000 - 3.000.
// **** Cylinder Volume Slider ****
- (NSInteger) normalizeValueCylinderVolumeSlider:(float) value
{
NSInteger normalizedValue = 0;
if (value>1.5)
{
if (value>2.5)
normalizedValue = 3;
else
normalizedValue = 2;
}
else if (value>0.5)
normalizedValue = 1;
return normalizedValue;
}
- (IBAction)valueChangedCylinderVolumeSlider:(UISlider *)sender
{
float value = [sender value];
NSInteger normalizedValue;
// Step 1:
normalizedValue = [self normalizeValueCylinderVolumeSlider:value];
// Step 2:
if (normalizedValue>value)
{
if ((normalizedValue-value)<0.3)
sender.value = normalizedValue;
}
else if ((value-normalizedValue)<0.3)
sender.value = normalizedValue;
}
- (IBAction)touchUpInsideCylinderVolumeSlider:(UISlider *)sender
{
float normalizedValue = 0;
normalizedValue = [self normalizeValueCylinderVolumeSlider:[sender value]];
sender.value = normalizedValue;
}
- (IBAction)touchUpOutsideCylinderVolumeSlider:(UISlider *)sender
{
float normalizedValue = 0;
normalizedValue = [self normalizeValueCylinderVolumeSlider:[sender value]];
sender.value = normalizedValue;
}
On valueChanged action, (step 1) I set the value to rigid values: 0, 1, 2, 3. And (step 2) I stick the slider thumb to the rigid values if it get close by 0.3 from the rigid value.
On touchUpInside & touchUpOutside I repeat 'step 1' code from valueChanged action to fix the slider value for the case that the drag action end outside the stick range ('step 2').
The best is to put all this code in a sub-class of Slider. But this is my only first week / attempt on iOS development.
While doing tutorial work, it took me forever to implement a decimal point, and now i have one, that works in the formula, but the issue is it reverses the input - e.g.. enter 1.4, the calculator screen shows it as 4.1 - i know its something to do with my housekeeping of the variables.. planning to use BOOL's instead of a float..but..any takers?
The code:
- (IBAction) pressedDecimal: (id) sender
{
pressedDec = 1;
}
- (IBAction) pressedDigit: (id) sender
{
if (pressedDec == 1)
{currentNumber = .1 * currentNumber + (double)[sender tag];
calculatorScreen.text = [NSString stringWithFormat:#"%g",currentNumber];
}
else
{
currentNumber = currentNumber * 10 + (double)[sender tag];
calculatorScreen.text = [NSString stringWithFormat:#"%g",currentNumber];
pressedDec = 0;
}
}
- (IBAction) pressedOperation: (id) sender
{
if (currentOperation == 0) result = currentNumber;
else {
switch (currentOperation) {
case 1:
result = result + currentNumber;
break;
case 2:
result = result - currentNumber;
break;
case 3:
result = result * currentNumber;
break;
case 4:
result = result / currentNumber;
break;
case 5:
currentOperation = 0;
break;
}
}
currentNumber = 0;
calculatorScreen.text = [NSString stringWithFormat:#"%g",result];
if ([sender tag] == 0) result = 0;
currentOperation = [sender tag];
}
Consider more carefully what this extract from your code does:
currentNumber = .1 * currentNumber + (double)[sender tag];
(I'm not being very explicit because if I've understood the question right you're doing this in order to learn, and the more you have to think the better you'll learn :-).)
Lesson number 2 here: Stanford iTunes U tutorial covers building a simple calculator. Might be helpful. Either way it's a great tutorial series.
I have the following method in my app :
- (void) loadModel {
// Runs in a seperate thread so we need to create an additional NSAutoreleasePool
pool = [[NSAutoreleasePool alloc] init];
NSData *getData = [activeModelInfo getFileData];
if (getData) {
if ([activeModel loadFromFileData:daeData]) {
[activeModel reset];
[mainViewController performSelectorOnMainThread:#selector(showModelView) withObject:nil waitUntilDone:NO];
}
else {
}
}
else {
}
[pool release];
}
The loadFromFileData method calls the following code which loads data. :
- (void) loadVerticesFromSource:(NSString*)verticesSourceId meshNode:(TBXMLElement*)meshNode intoMesh: (Mesh3D*) mesh {
NSLog(#"Getting Vertices for Source %#",verticesSourceId);
FloatArray *floatArray = [self getFloatArrayFromSource: verticesSourceId meshNode: meshNode];
if (floatArray) {
[daeFloatArray addObject:floatArray];
}
if (floatArray) {
if ([floatArray.array count] % 3 != 0) {
NSLog(#"Float array length not divisible by 3!");
}
else {
mesh->verticesCount = [floatArray.array count] / 3;
mesh->vertices = malloc(sizeof(Vector3D) * mesh->verticesCount);
for (int i=0; i<mesh->verticesCount; i++) {
mesh->vertices[i].x = [[floatArray.array objectAtIndex:(i*3)] floatValue];
mesh->vertices[i].y = [[floatArray.array objectAtIndex:(i*3)+1] floatValue];
mesh->vertices[i].z = [[floatArray.array objectAtIndex:(i*3)+2] floatValue];
// update extents information
if (!extents.pointDefined || mesh->vertices[i].x < extents.minX) extents.minX = mesh->vertices[i].x;
else if (!extents.pointDefined || mesh->vertices[i].x > extents.maxX) extents.maxX = mesh->vertices[i].x;
if (!extents.pointDefined || mesh->vertices[i].y < extents.minY) extents.minY = mesh->vertices[i].y;
else if (!extents.pointDefined || mesh->vertices[i].y > extents.maxY) extents.maxY = mesh->vertices[i].y;
if (!extents.pointDefined || mesh->vertices[i].z < extents.minZ) extents.minZ = mesh->vertices[i].z;
else if (!extents.pointDefined || mesh->vertices[i].z > extents.maxZ) extents.maxZ = mesh->vertices[i].z;
if (!extents.pointDefined) extents.pointDefined = YES;
[pointerStorageArray addObject:[NSValue valueWithPointer:mesh->vertices]];
}
}
}
}
Since this method is called several times while the data loads, each time mallocing memory for the mesh->vertices struct, I have created a pointerStorage array where I store the pointer to the malloced memory.
The app then displays a 3D object using OpenGL ES. When the user presses a Main Menu button, I then free up the pointerStorageArray as follows :
- (void) freeUpMallocedMemory
for (NSValue * value in pointerStorageArray) {
free(value);
}
The problem is that the app then crashes during this process. All I get is the EXC_BAD_ACCESSS error message and a pointer to the following line of code in the loadModel method above :
[pool release];
Nothing in the stack trace. I have also tried turning on NSZombie, NSAutoreleaseTrackFreedObjectCheck and NSDebugEnabled, but I still don't get any additional information.
The odd thing is that if I put a delay on the button of 2 seconds (i.e only trigger the freeUpMallocedMemory method after 2 seconds), the app no longer crashes and works fine.
Can anyone suggest what might be causing this - really confused and have already spent a few days troubleshooting.
Thank you !
You are over-releasing... the values in pointerStorageArray are created via a convenience method and as such don't need releasing, simply removing them from the array will dispose of them.
I would like to call from a method 'method1' another method 'method2'. The problem is that there is a CADisplayLink on 'method1' and when I want to call 'method2' from 'method1' it call it at 6Ofps so 60 times per second, but I just want that it call it one time. I know that I have to use BOOL variable but I don't know how to use them . Can anyone help me ? sorry for my english I'm french :/
//EDIT:
there is a CADisplayLink on method1:
-(void)method1{
if(
if ( leScore % 20000 == 0) {
[self method2];
}
-(void)method2{
etatJeu = arc4random() / (UINT_MAX/3);
switch(etatJeu) {
case 0: /* top */
etatJeu=kEtatJeu2;
break;
case 1: /* bottom */
etatJeu=kEtatJeu3;
break;
case 2: /* bottom */
etatJeu=kEtatJeu4;
break;
default:
break;
}
so every time 'leScore % 20000 == 0' call one time method2.
If you want to make the method call happen only once, then use a bool this way:
#interface SomeClass {
BOOL method2RunFlag; // set to NO in init
}
#end
// ... in your method1
if( method2RunFlag == NO ) {
// call your method2
method2RunFlag = YES;
}
Based on your edited code above:
-(void)method1{
if( method2RunFlag == NO ) {
method2RunFlag = YES;
if ( leScore % 20000 == 0) {
[self method2];
}
// wait 1 second before able to call again
[NSTimer scheduledTimerWithTimeInterval:1.0 target:self selector:#selector(resetMethod2RunFlag:) userInfo:nil repeats:NO];
}
- (void)resetMethod2RunFlag:(NSTimer *)timer {
method2RunFlag = NO;
}
Still not entirely sure what you're after but this is my best guess. =)
You probably want to create 2 variations of method1, one to use with CADisplayLink, the other elsewhere, perhaps calling all the common code in a helper method1A, but with a flag parameter saying whether to call method2 or not.
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