making sure that every new position is different from previous two positions - ios

Below is a method I wrote that takes a random number and makes sure that a sprite does repeat consecutively at the same position. I want to change it so that every new sprite takes a different position of the other two. I am not really getting it right. Please help.
- (float)randomlyChooseXValue {
CGSize s = [[CCDirector sharedDirector] winSize];
int randX = arc4random() % 3;
if (oldRandX != randX) {
if (randX == 0) {
xPos = xPos1*(s.width/480.0);
} else if (randX == 1) {
xPos = xPos2*(s.width/480.0);
} else {
xPos = xPos3*(s.width/480.0);
}
oldRandX = randX;
} else {
[self randomlyChooseXValue];
}
return xPos;
}

If I understand this correctly you need to find 3 random values and the 3rd one should be different then the 1st 2. If this is true you need to store last 2 random values and compare them in the 1st if statement:
- (float)randomlyChooseXValue {
CGSize s = [[CCDirector sharedDirector] winSize];
int randX = arc4random() % 3;
if ((oldRandX1 != randX) && (oldRandX2 != randX)) { //check for 2 values
if (randX == 0) {
xPos = xPos1*(s.width/480.0);
} else if (randX == 1) {
xPos = xPos2*(s.width/480.0);
} else {
xPos = xPos3*(s.width/480.0);
}
oldRandX2 = oldRandX1; //store 1st value to 2nd place
oldRandX1 = randX; //store new value to 1st place
} else {
[self randomlyChooseXValue];
}
return xPos;
}

Since you explained that you are okay with the sequence repeating, then you only need to really make two random choices: the first position, and the direction.
// somewhere, initialize global oldRandX = -1, dir = -1
- (float)randomlyChooseXValue {
CGSize s = [[CCDirector sharedDirector] winSize];
if (oldRandX < 0) {
oldRandX = arc4random() % 3;
dir = arc4random() % 2;
} else if (dir) {
oldRandX = (oldRandX + 1) % 3;
} else {
oldRandX = (oldRandX + 2) % 3;
}
if (randX == 0) {
xPos = xPos1*(s.width/480.0);
} else if (randX == 1) {
xPos = xPos2*(s.width/480.0);
} else {
xPos = xPos3*(s.width/480.0);
}
return xPos;
}
This can generate every possible sequence of the three positions:
0, 1, 2
0, 2, 1
1, 2, 0
1, 0, 2
2, 0, 1
2, 1, 0
and repeat them.
The other answer will achieve the same results, but like your original method, it might take several tries to get it. Your random function can keep choosing the wrong value an unbounded number of times; it becomes a worse problem when there's only one right number to pick.

Related

Can you resize images that are passed to UIPrintInteractionController.PrintingItems?

I'm trying to print multiple labels using UIPrintInteractionController.PrintingItems but when the image is loaded it fills the page, is it possible to have multiple images on one page using this method or is there another method that would offer me a better solution? Thanks.
void Print()
{
var printInfo = UIPrintInfo.PrintInfo;
printInfo.OutputType = UIPrintInfoOutputType.General;
printInfo.JobName = "Label Printing";
//UIPrintFormatter formatter = new UIPrintFormatter()
//{
// StartPage = 0,
// ContentInsets = new UIEdgeInsets(72, 72, 72, 72),
// MaximumContentWidth = 6 * 72,
//};
int labelAmount = 10;
int x;
NSObject[] labelItems = new NSObject[labelAmount];
for (x = 0; x < labelAmount; x++)
{
labelItems[x] = UIImage.FromFile("Images/BMcAzurri.png");
}
UIPrintInteractionController printer = UIPrintInteractionController.SharedPrintController;
printer.PrintInfo = printInfo;
//printer.PrintFormatter = formatter;
printer.PrintingItems = labelItems;
printer.ShowsPageRange = true;
printer.Present(true, (handler, completed, err) => {
if (!completed && err != null)
{
Console.WriteLine("error");
}
});
}
There are a few ways to do what you are asking, here is just one using a graphics context to do your print page rendering.
Load your image into a UIImage instance
You might want to pre-scale/re-scale that image
Create a UIView that is large enough to contain all your rows and columns of that image
Create a UIImageView that contains your image for each row/column on your "printed page" and place it at the correct location in this view
Using an Image render context, convert the UIView that contains your images to a UIImage and queue and print as many of those as you need...
Example:
var printInfo = UIPrintInfo.PrintInfo;
printInfo.OutputType = UIPrintInfoOutputType.General;
printInfo.JobName = "Label Printing";
var uiImage = UIImage.FromFile("BingWallpaper-2017-05-04.jpg");
var noColumns = 2;
var noRows = 2;
var gapBetweenImages = 25;
int noOfPages = 2;
NSObject[] labelItems = new NSObject[noOfPages];
for (int x = 0; x < noOfPages; x++)
{
var aPrintView = new UIView
{
Frame = new CGRect(0, 0, (uiImage.Size.Width * noColumns) + ((noColumns + 1) * gapBetweenImages), (uiImage.Size.Height) * noRows + ((noRows + 1) * gapBetweenImages))
};
for (int column = 0; column < noColumns; column++)
{
for (int row = 0; row < noRows; row++)
{
var printImage = new UIImageView(uiImage)
{
Frame = new CGRect((column * gapBetweenImages) + (column * uiImage.Size.Width), (row * gapBetweenImages) + (row * uiImage.Size.Height), uiImage.Size.Width, uiImage.Size.Height)
};
aPrintView.Add(printImage);
}
}
UIGraphics.BeginImageContext(aPrintView.Bounds.Size);
aPrintView.Layer.RenderInContext(UIGraphics.GetCurrentContext());
var aPageImage = UIGraphics.GetImageFromCurrentImageContext();
UIGraphics.EndImageContext();
labelItems[x] = aPageImage;
}
UIPrintInteractionController printer = UIPrintInteractionController.SharedPrintController;
printer.PrintInfo = printInfo;
printer.PrintingItems = labelItems;
printer.ShowsPageRange = true;
printer.Present(true, (handler, completed, err) =>
{
if (!completed && err != null)
{
Console.WriteLine("error");
}
});
Note: !!! This is not handling the clean up, make sure you Dispose of everything after you are done...
Note: This is just a quick example does not handle the aspect ratio of the image to the paper size, you would need to consider that depending upon what you are printing and to what type of printer/paper...
Note: If you were renderering a number of text fields vs. images, you might want to render to a PDF vs a UIImage and print that instead.

here map iOS distanceToDestination

I wonder if someone can help me get total route distance in Heremap iOS sdk. According to the document, the following should do it, but I only ever get back values that borders on infinity, and that' just evil. Can someone please provide a working example? I am running this in the simulator but that shouldn't really matter.
unsigned long long distance_ul = [NMANavigationManager sharedNavigationManager].distanceToDestination;
NMAUint64 distance_i64 = [NMANavigationManager sharedNavigationManager].distanceToDestination;
Your second usage NMAUint64 distance = [NMANavigationManager sharedNavigationManager].distanceToDestination; is ok. Then you should calculate your distance by yourself. Below is an example for the metric system
- (NSString *)distanceToMetricStringFromLongValue:(NMAUint64)value {
NSString *distanceText = #"";
if (value < 250) {
NMAUint64 distance = (NMAUint64)round(value / 5.0) * 5;
if (showZeroDistance || distance > 0) {
distanceText = [NSString stringWithFormat:#"%lld m", distance];
}
} else if (value < 500) {
NMAUint64 distance = (NMAUint64)round(value / 10.0) * 10;
if (showZeroDistance || distance > 0) {
distanceText = [NSString stringWithFormat:#"%lld m", distance];
}
} else if (value < 1000) {
NMAUint64 distance = (NMAUint64)round(value / 50.0) * 50;
distanceText = [NSString stringWithFormat:#"%lld m", distance];
} else {
double distance = value / 1000.0;
if (distance >= 10.0) {
distanceText = [NSString stringWithFormat:#"%0.0f km", round(distance)];
} else {
distanceText = [NSString stringWithFormat:#"%0.1f km", distance];
}
}
}
When you create route on map with below method
- (nullable NSProgress *)calculateRouteWithStops:(nonnull NSArray *)stops
routingMode:(nonnull NMARoutingMode *)mode
completionBlock:(nullable NMACalculateResultBlock)completion
Find route length from NMARoute object
NMARoute* route = routeResult.routes[m];
NSLog(#"Route Length is :----- %lu",(unsigned long)route.length);
Official document link

SceneKit : Extract data from SCNGeometryElement

I am using SceneKit, and I have an issue:
How can I extract the data from a SCNGeometryElement object ?
I use this method :
- (void)geometryElements:(SCNNode *)node {
for (int indexElement = 0; indexElement < node.geometry.geometryElementCount; indexElement++) {
SCNGeometryElement *currentElement = [node.geometry geometryElementAtIndex:indexElement];
NSLog(#"\n");
NSLog(#"bytes per index : %d", currentElement.bytesPerIndex);
NSLog(#"number element : %d", currentElement.primitiveCount);
NSLog(#"data lenght : %d", currentElement.data.length);
for (int indexPrimitive = 0; indexPrimitive < currentElement.primitiveCount; indexPrimitive++) {
int array[3];
memset(array, 0, 3);
[currentElement.data getBytes:&array range:NSMakeRange(indexPrimitive * 3, (currentElement.bytesPerIndex * 3))];
NSLog(#"currentelement : %d %d %d", array[0], array[1], array[3]);
}
}
The result is not good :
2015-04-10 15:10:25.183 IKTest[1234:244778] currentelement : 14539995 -1068223968 -379286778
2015-04-10 15:10:25.183 IKTest[1234:244778] currentelement : 14737374 -1068223968 -379286778
2015-04-10 15:10:25.183 IKTest[1234:244778] currentelement : 14934753 -1068223968 -379286778
Thanks in advance.
a few notes:
you should rely on geometryElement.primitiveType instead of hard coding 3 (unless you are sure that you're always dealing with SCNGeometryPrimitiveTypeTriangles)
it seems that the range's location does not take geometryElement.bytesPerIndex into account
your buffer is of size 3 * sizeof(int) but should be of size numberOfIndicesPerPrimitive * geometryElement.bytesPerIndex
As mnuages said, you should confirm primtive type and data type of index first.
Your code only work if index type is int.
Here is some code work for me. I only deals that geometry consisted of triangles.
void extractInfoFromGeoElement(NSString* scenePath){
NSURL *url = [NSURL fileURLWithPath:scenePath];
SCNScene *scene = [SCNScene sceneWithURL:url options:nil error:nil];
SCNGeometry *geo = scene.rootNode.childNodes.firstObject.geometry;
SCNGeometryElement *elem = geo.geometryElements.firstObject;
NSInteger componentOfPrimitive = (elem.primitiveType == SCNGeometryPrimitiveTypeTriangles) ? 3 : 0;
if (!componentOfPrimitive) {//TODO: Code deals with triangle primitive only
return;
}
for (int i=0; i<elem.primitiveCount; i++) {
void *idxsPtr = NULL;
int stride = 3*i;
if (elem.bytesPerIndex == 2) {
short *idxsShort = malloc(sizeof(short)*3);
idxsPtr = idxsShort;
}else if (elem.bytesPerIndex == 4){
int *idxsInt = malloc(sizeof(int)*3);
idxsPtr = idxsInt;
}else{
NSLog(#"unknow index type");
return;
}
[elem.data getBytes:idxsPtr range:NSMakeRange(stride*elem.bytesPerIndex, elem.bytesPerIndex*3)];
if (elem.bytesPerIndex == 2) {
NSLog(#"triangle %d : %d, %d, %d\n",i,*(short*)idxsPtr,*((short*)idxsPtr+1),*((short*)idxsPtr+2));
}else{
NSLog(#"triangle %d : %d, %d, %d\n",i,*(int*)idxsPtr,*((int*)idxsPtr+1),*((int*)idxsPtr+2));
}
//Free
free(idxsPtr);
}
}
As the original question has a Swift tag, I am posting my solution in Swift 5.
extension SCNGeometryElement {
/// Gets the `Element` vertices
func getVertices() -> [SCNVector3] {
func vectorFromData<UInt: BinaryInteger>(_ float: UInt.Type, index: Int) -> SCNVector3 {
assert(bytesPerIndex == MemoryLayout<UInt>.size)
let vectorData = UnsafeMutablePointer<UInt>.allocate(capacity: bytesPerIndex)
let buffer = UnsafeMutableBufferPointer(start: vectorData, count: primitiveCount)
let stride = 3 * index
self.data.copyBytes(to: buffer, from: stride * bytesPerIndex..<(stride * bytesPerIndex) + 3)
return SCNVector3(
CGFloat.NativeType(vectorData[0]),
CGFloat.NativeType(vectorData[1]),
CGFloat.NativeType(vectorData[2])
)
}
let vectors = [SCNVector3](repeating: SCNVector3Zero, count: self.primitiveCount)
return vectors.indices.map { index -> SCNVector3 in
switch bytesPerIndex {
case 2:
return vectorFromData(Int16.self, index: index)
case 4:
return vectorFromData(Int.self, index: index)
case 8:
return SCNVector3Zero
default:
return SCNVector3Zero
}
}
}
}
There might be a bit of an indentation problem here, but yes, it is a function inside another one. The objective is the same as the other answers. Create a buffer, define what types of numbers the buffer is going to handle, build the SCNVector3 and return the array.

Using multiple else if statements for NSInteger

I have a section of code, in which I want a different accessoryView for the TableView cell, based off the number for that cell's entry. The code I have set up is:
NSInteger warriors = [entry.prayerWarriors intValue];
if (warriors == 0) {
//Do nothing
//NSLog(#"0");
}
else if (0 < warriors < 50) {
cell.accessoryView = firstLevel;
// NSLog(#"50");
}
else if (51 < warriors < 100) {
cell.accessoryView = secondLevel;
// NSLog(#"100");
}
else if (101 < warriors < 500) {
cell.accessoryView = thirdLevel;
// NSLog(#"500");
}
else {
cell.accessoryView = fourthLevel;
// NSLog(#"A Lot");
}
However, it always returns only the first entry for warriors == 0. What am I doing wrong?
Rather than doing this...
else if (0 < warriors < 50) {
cell.accessoryView = firstLevel;
// NSLog(#"50");
}
do this...
else if (0 < warriors && warriors < 50) {
cell.accessoryView = firstLevel;
// NSLog(#"50");
}
EDIT
To answer your comment...you probably mean to have some <= or >= in there, as it's going to the last else when warriors equals the border of your if conditionals (50, 100 or 500).
You probably want it to look like this...
NSInteger warriors = [entry.prayerWarriors intValue];
if (warriors == 0) {
//Do nothing
//NSLog(#"0");
}
else if (0 < warriors && warriors <= 50) {
cell.accessoryView = firstLevel;
// NSLog(#"50");
}
else if (50 < warriors && warriors <= 100) {
cell.accessoryView = secondLevel;
// NSLog(#"100");
}
else if (100 < warriors && warriors <= 500) {
cell.accessoryView = thirdLevel;
// NSLog(#"500");
}
else {
cell.accessoryView = fourthLevel;
// NSLog(#"A Lot");
}
The statement
if (0 < warriors < 50)
evaluates different than you might think. The first part
(0 < warriors)
evaluates as a boolean, and that boolean will be compared to 50.
So, you need to do: if (0 < warriors && warriors < 50)
The other answers make good points about the later cases needing a logical and but if you are getting stuck at if (warriors == 0) { most likely your object entry.prayerWarriors is nil. Put a break point and print it out. (and print out it's class to make sure its as expected)
Also minor but a good habit to be in your conversion of what I'm guessing is an NSNumber isn't using the same type as your variable. Since you are writing into a NSInteger you should replace intValue with integerValue
For clarity, I prefer to put the variable first in each condition and to encapsulate each part of the condition:
if (warriors == 0) {
//Do nothing
NSLog(#"0");
}
else if ((warriors > 0) && (warriors < 50))
{
cell.accessoryView = firstLevel;
NSLog(#"50");
}
else if ((warriors > 51) && (warriors < 100)) {
cell.accessoryView = secondLevel;
NSLog(#"100");
}
else if ((warriors > 101) && (warriors < 500)) {
cell.accessoryView = thirdLevel;
NSLog(#"500");
}
else {
cell.accessoryView = fourthLevel;
NSLog(#"A Lot");
}
Just be sure you've have enough parens around the conditions.
You do not need an if cascade for this:
You can store the levels one time anywhere
NSArray *levels = #[firstLevel, secondLevel, thirdLevel, fourthLevel];
And use it indexed:
if( warriors > 0) {
cell.accessoryView = levels[(warriors-1) / 50]
}
But if you want to have an if cascade, you do not have to double check:
NSInteger warriors = [entry.prayerWarriors intValue];
if (warriors == 0) {
//Do nothing
//NSLog(#"0");
}
else if (warriors <= 50) {
cell.accessoryView = firstLevel;
// NSLog(#"50");
}
else if (warriors <= 100) {
cell.accessoryView = secondLevel;
// NSLog(#"100");
}
else if (warriors <= 500) {
cell.accessoryView = thirdLevel;
// NSLog(#"500");
}
else {
cell.accessoryView = fourthLevel;
// NSLog(#"A Lot");
}
If you are in an else, it is already tested that the preceding condition failed.(That's the meaning of else.)

Change an integer value after a time interval ios

I am making a game with powerups. I have 3 powerups. When a powerup is active, I use an integer to identify which one it is, 1, 2, or 3, with 0 representing no active powerups. Once I activate a powerup, I want it to expire after a time interval, say 10 seconds. How do I reset the identifier integer back to 0?
For example, one powerup speeds up the ship. Here is my update method.
-(void) update:(ccTime)dt
{
if (powerupIdentifier == 0)
{
shipSpeed = 100;
}
if (powerupIdentifier == 1)
{
shipSpeed = 200;
}
CCArray* touches = [KKInput sharedInput].touches;
if ([touches count] == 1)
{
//MAKES SHIP MOVE TO TAP LOCATION
KKInput * input = [KKInput sharedInput];
CGPoint tap = [input locationOfAnyTouchInPhase:KKTouchPhaseBegan];
ship.position = ccp( ship.position.x, ship.position.y);
if (tap.x != 0 && tap.y != 0)
{
[ship stopAllActions]; // Nullifies previous actions
int addedx = tap.x - ship.position.x;
int addedy = tap.y - ship.position.y;
int squaredx = pow(addedx, 2);
int squaredy = pow(addedy, 2);
int addedSquares = squaredx + squaredy;
int distance = pow(addedSquares, 0.5);
[ship runAction: [CCMoveTo actionWithDuration:distance/shipSpeed position:tap]];//makes ship move at a constant speed
}
}
}
First, use an enum rather than an int.
typedef NS_ENUM(unsigned short, PowerUp) {
PowerUp_Level0,
PowerUp_Level1,
PowerUp_Level2,
PowerUp_Level3
};
Enum is far more readable, and is a lot more self-documenting then random integers.
Now, say we have a property:
#property (nonatomic, assign) PowerUp powerUp;
We can write a method to reset the power up:
- (void)resetPowerUp {
self.powerUp = PowerUp_Level0;
}
Now, when we've set it to some non-zero value and need to reset it (after 10 seconds), it's as simple as this:
self.powerUp = PowerUp_Level2;
[self performSelector:#selector(resetPowerUp) withObject:nil afterDelay:10.0f];

Resources