I am trying to create an app in which one of a few objects is randomly placed on the screen wherever you touch. I have my objects a, b, and c and I have them in an array.
(NSArray *) gamePieces {
NSArray *things = [NSArray arrayWithObjects: #"a", #"b", #"c", nil];
return things;
}
And then my touch method.
(void)touchesBegan:(NSArray *)touches withEvent:(UIEvent *)event {
/* Called when a touch begins */
for (UITouch *touch in touches) {
CGPoint location = [touch locationInNode:self];
// code that chooses random object from array
}
}
Normally I would put in an SKSpriteNode and it would make just that one appear on the screen, but I am looking to randomly select one of many. I'm new to programming and I'm not sure if I'm on the right path. If I am, what needs to go in the touch method? If not, what am I doing wrong?
You can get a random item by getting a random index based on the number of elements in the array :
int randomIndex = arc4Random() % things.count;
NSString *thing = things[randomIndex];
// do something with thing
Related
I'm working a little game for iOS (spritekit/swift).
I've an array of SKSpriteNode in my scene defined like this:
var spritesTree = [SKSpriteNode]()
then I fill the array with a function and add them to the scene like this:
spritesTree = spritesCollectionTree(count: numTrees)
for sprite in spritesTree {
addChild(sprite)
}
After that, depending the situation the process adds some more trees into the array. I Know how to remove elements from the scene and the array if I Know the index
spritesTree[i].removeFromParent()
spritesTree.removeAtIndex(i)
but my problem is to remove an especific node in this array when I don't Know the index. For exemple when one of the the sprite was touched
override func touchesBegan(touches: Set<NSObject>, withEvent event: UIEvent) {
/* Called when a touch begins */
for touch in (touches as! Set<UITouch>) {
let location = touch.locationInNode(self)
let positionInScene = touch.locationInNode(self)
let touchedNode = self.nodeAtPoint(positionInScene)
In this case, ¿How can I remove the touchedNode from my array spritesTree of SKSpriteNode if I don't know the index? I read something about indexOf to find the index previoustly but it doesn't work with my SKSpriteNode array. Could you help me please?
Bests,
You can create a name for each SKSpriteNode :
spritesTree[index].name = String(index)
After when you check node touched you convert name to Int
let location = touch.locationInNode(self)
let positionInScene = touch.locationInNode(self)
let touchedNode = self.nodeAtPoint(positionInScene)
var index = Int(touchedNode.name)
touchedNode.removeFromParent()
spritesTree.removeAtIndex(index)
I'm attempting to customize the "Page-Based Application" template and am new to Swift (and all programming for that matter). In my ModelController.swift I've created a 2D array to use as the primary datasource.
However, when I go to print it or use it as label.text it is including the parenthesis. How do I get just the strings of the array element I'm calling for?
class ModelController: NSObject, UIPageViewControllerDataSource {
var pageData: NSArray = [[String]]()
override init() {
super.init()
// Create the data model.
pageData = [["right", "wrong"], ["left", "right"]]
println(pageData[1]) //For
}
I'm not sure what else from this file is relevant but here's another bit.
func indexOfViewController(viewController: DataViewController) -> Int {
// Return the index of the given data view controller.
// For simplicity, this implementation uses a static array of model objects and the view controller stores the model object; you can therefore use the model object to identify the index.
if let dataObject: AnyObject = viewController.dataObject {
return self.pageData.indexOfObject(dataObject)
} else {
return NSNotFound
}
}
If you just want left, right
println("\(pageData[1][0]), \(pageData[1][1])")
If you literally want "left, right" with the double quotes included it's
println("\"\(pageData[1][0]), \(pageData[1][1])\"")
The reason you got the results you did is because pageData[1] isn't a String it's an NSArray. Because NSArray conforms to the Printable protocol it supplies its .description when used in println.
I am trying to search through the contents of my attributed UITextView with the following code:
NSRange range = NSMakeRange(0, haystack.length);
range = [haystack rangeOfString:searchText options:NSCaseInsensitiveSearch range:range];
while (range.location != NSNotFound)
{
[_attrString addAttribute:NSBackgroundColorAttributeName value:[UIColor yellowColor] range:NSMakeRange(range.location, range.length)];
range = NSMakeRange(range.location+range.length, haystack.length-(range.location+range.length));
range = [haystack rangeOfString:searchText options:NSCaseInsensitiveSearch range:range locale:nil];
}
...
_textView.attributedText = _attrString;
_attrString is of course a NSMutableAttributedString
This works fine except it is very slow with large texts. With a UITextView containing 156,000 characters it takes a couple of seconds for the changes to become visible. If I NSLog the single steps of the loop I can see that the code executes fast. It takes a couple of seconds for the changes to become visible in the UITextView.
Does it just take a while for the attributed UITextview to redraw? Is do anything to speed up the process? I tried searching through the text with regular expressions, but that didn't seem to change anything.
Thanks
Use NSPredicate
UITextField *txtFld=(UITextField *)sender;
// if (![txtFld.text isEqualToString:#""]) {
//[self getSearchResult:txtFld.text];
// }else{
// [self makeViewSmall];
// }
// For string kind of values:
NSPredicate *predicate = [NSPredicate predicateWithFormat:#"SELF contains[cd] %#", txtFld.text];
NSArray *results = [[sortedDic valueForKey:#"locations"] filteredArrayUsingPredicate:predicate];
NSLog(#"Result=%#",results);*/
Let's say I have an array, each item in the array has a corresponding library item.
I'd like to do something like :
var rando = Math.round(Math.random()*3)
var myArray = new Array ["ball", "wall", "fall"]
var i:myArray[rando] = myArray[rando] new myArray[rando]()
addChild(i)
But, this doesn't work. What's the secret?
Thank You,
Victor Hugo
Surprised no one mentioned getDefinitionByName() here.
Here's some complete code to get your example working:
var myArray = ["ball", "wall", "fall"];
/**
* Creates a random instance based on an input array containing class names as Strings.
* #param The input array containing aforementioned Strings.
* #return The newly created instance.
*/
function createRandom(typeArray:Array):*
{
// Select random String from typeArray.
var selection:String = typeArray[ int(Math.random() * typeArray.length) ];
// Create instance of relevant class.
var Type:Class = getDefinitionByName(selection) as Class;
// Return created instance.
return new Type();
}
// Randomly create and add instance.
var instance:DisplayObject = createRandom(myArray);
addChild(instance);
Ok so there are a bunch of problems with this.
A large one being var i:myArray[rando] = myArray[rando] new myArray[rando]() not really too sure what you're trying to do here.
Anyway I'm going to assume ball, wall and fall are instance names of MovieClips you have in your library. I think you're going to want something like this
var rando:int = Math.floor(Math.random()*3); //As the comments point out this should give you a random
//int between 0 and 2, arrays are 0 indexed so this is what we want if we have 3 items
Now for your array, you're current putting strings in there. Flash has no idea what "ball", etc are.
Try something like this
var myArray:Array = new Array [new ball(), new wall(), new fall()]; //this creates a new instance of your library object and stores it in your array
Now to add one of these to your stage:
addChild(myArray[rando]); //this uses the random number to pull one of the items out of your array
What you're trying to do with var i:myArray[rando] doesn't really make sense. There is no type of myArray[rando] this slot should be holding a MovieClip
If you only have a few choices, it's easier to use a switch-case.
switch (rando) {
case 0:
i = new ball();
break;
case 1:
i = new wall();
break;
case 2:
i = new fall();
break;
}
addChild(i);
I suggest you define the variable i as a MovieClip, in which case it can be instantiated as both ball, wall, fall.
Given that ball, wall and fall are in the library exported to actionscript.
Just guessing off your limited information but give this a shot.
private function myFunction():void{
var rando = Math.round(Math.random()*3);
var myArray= new Array ["ball", "wall", "fall"];
}
private function generateItem(item:String):void{
switch(item){
case "ball" : generateBall(); break;
case "wall" : generateWall(); break;
case "fall" : generateFall(); break;
}
private function generateBall():void{
//code to generate ball
addChild(ball);
}
private function generateFall():void{
//code to generate fall
addChild(fall);
}
private function generateWall():void{
//code to generate wall
addChild(wall);
}
Change your arrary line to:
var myArray = new Array [ball, wall, fall];
This should work. :)
Marty Wallace gets big praise for steering me down the path of getDefinitionByName(). The example he posted was good, but this example does exactly what I was going for.
http://www.emanueleferonato.com/2011/03/31/understanding-as3-getdefinitionbyname-for-all-eval-maniacs/
I'm writing a game with Flash CS5/AS 3.0 that tries to simulate depth of field by drawing all the relevant Movie Clips based on their Y position in ascending order, i.e. things lower on the stage overlap things higher on the stage. A MovieClip with a Y position of 10 would therefore need to have a lower index compared to a MovieClip with a Y position of 20, so the second one gets drawn on top of the first.
I wrote a quick and dirty function just to test this. During the trace, I've noticed that the truck's index hits 0 when I go near the top of the stage, but if I go too far up it will completely disappear from the stage. Trace then starts generating this error:
ArgumentError: Error #2025: The supplied DisplayObject must be a child of the caller.
at flash.display::DisplayObjectContainer/getChildIndex()
at EICT::Game/ReorganizeDisplayIndexes()
at EICT::Game/loop()
theTruck is a MovieClip of the player controlled vehicle
Enemies, Cones, Rocks are all arrays which contain MovieClips
None of them have event listeners.
private function ReorganizeDisplayIndexes(): void
{
var drawableObjects:Array = new Array();
drawableObjects.push(theTruck);
drawableObjects = drawableObjects.concat(Enemies, Rocks, Bushes);
drawableObjects.sortOn("y", Array.DESCENDING | Array.NUMERIC);
drawableObjects.reverse();
trace(collisionLayer.getChildIndex(theTruck));
for (var a:int = collisionLayer.numChildren - 1; a >= 0; a--)
{
collisionLayer.removeChildAt(a);
}
for (var i:int = 0; i < drawableObjects.length; i++)
{
collisionLayer.addChild(drawableObjects[i]);
}
}
Hint: You don't need to remove the child first. When you use addChild() on an object, it is automatically re-added to the next highest depth.
That said, you'll just need to do something like this:
drawableObjects.sortOn("y");
for each(var i:DisplayObject in drawableObjects)
{
if(i.parent)
i.parent.addChild(i);
}
Use setChildIndex instead of removing and re-adding:
for (var a:int = collisionLayer.numChildren - 1; i >= 0; i--)
{
collisionLayer.setChildIndex(drawableObjects[i], i);
}
Also, it's a bit wasteful to first order the sort in descending and then reversing the array. Sort it ascending to begin with!