How to make objects spawn in a place at random times and move to a direction after spawning - swift

How can i make a rootnode of a scene spawn duplicates of itself in a position (For example: x: 10,y: 10,z: 10)
then move in a direction until they are completely off screen and then dissappear.
I'm not asking for code, but i am asking for how to do this(For example what do i use for duplicating a rootnode?
How do i make that node disappear?
How do i generate a random number between 1 and 10 that will determine when to spawn the duplicate?)
And How do i make my post meet the quality standards?

You'll want to use a generalized class of nodes and spawn instances randomly.
Here's an answer on how to make random numbers in Swift. Use that to make three different random numbers between 1 and 10, and use the node class constructor with the three random numbers as input.
Finally, to move the node in a random direction, you need to have some movement function in the node class and feed it random numbers.
This is how you ask a good question.

Here is an answer:
You could:
First copy the rootnode using "node.clone" or "node.copy".
Clone duplicates the whole node tree (the node and children) whereas copy duplicates just that node.
Next assign the copy to a variable (so you can access it).
Then add any actions if you need to (refer below).
Then in your spawning loop or whatever you use to spawn objects, make a clone of the clone (the variable we made in step 2) and set it's position, with a random number.
To generate a random number that can be positive or negative use something like:
((((Float(arc4random()) / Float(UINT32_MAX))*2)-1)*5)//five is the important
//number here because it means you will get a number ranging from
// -5 to 5
Then add any actions you need to (refer below).
Finaly call scene.rootNode.addChildNode(theNodeYouJustPositioned)
To remove a node call node.removeFromParentNode.
Actions:
Alternitavely, to deleting the node yourself, and positioning the node yourself in a loop or such, and moving the node yourself, you could use SCNAction.
To use SCNAction simply call node.runAction(SCNAction).
There are many different ways of using SCNAction so please visit the docs for a whole list.
To make your node position itself (sort of) try running a runblock:^node:SCNNode{} and setting the node's position to a random number in there.
The node now positions it self so you can skip step 4.
Now if you want to move the node by a fixed direction (I mean "not random") you could just add a moveBy:xyz action in step 3.
But if it had to be a random direction you could do this action in step 5 and feed random numbers into it.
To delete you nodes using a time delay you could use a sequence: action and feed in an array containing, first, a waitForDuration:Seconds action, and last, a removeFromParentNode action.
Please visit the docs for SCNAction and any other class I mentioned that you may not have understood.
I don't know swift (at all) so I am sure there are a few syntax errors in the code. (sorry)
Post comments below if your confused.
Thanks!

Related

Adding and removing multiple nodes efficiently, without any lag

In my game, at specific intervals, a function is called that adds multiple nodes to the scene (between 2 and 6 nodes). These individual nodes are all the same - they consist of the same blender model, same SCNCone, same spotlight and same physics bodies - (The blender model is low-poly, nothing extreme).
When it's time to call the next interval of nodes, the nodes that were called previously are removed (including their actions). This process repeats until the player has died. Now when the nodes are removed and new ones are added, it creates noticeable lag for roughly a second, and doesn't appear smooth.
I'm wondering whether there is a more efficient way to add and remove these nodes that could possibly eliminate lag? Since these nodes are all visibly the same, would cloning a node multiple times be better than re-creating the same node over and over within a for loop?
Any advice on efficiency or better practises would be greatly appreciated too.
Thanks!
Edit: Just a thought, should I have a node at every required position, and basically un-hide and give them actions when needed, and once they've done their job, fade out, put back at initial position, remove actions and hide?
This would mean I would need about 20 nodes in the scene at all times, but at least there would be no need to add any more, or remove any.
Start by turning ON statistics.
scnView.showStatistics = YES;
Click on the + at the bottom left of the screen to the stats screen.
What could be causing the lag? Quick things to check are:
1. Is the geometry too complex?
2. Are the textures too large?
3. Are there too many draw calls?
Cloning is better.
Yes, I think your idea at the end will avoid the lag. If the nodes being added are the same as the nodes being removed it will be more efficient just to hide and reset them.
If you are creating the nodes each time it is likely that is causing the lag, and you could even remove and add them from the scene but instead of creating them when needed store them in an array ready to be reused.

Scrolling Clone Sprites

I'm attempting to make a code in which I have a sprite act as the main terrain sprite (aka a tile) and have clones of that sprite stack on to the end of it, while maintaining the scroll code, which allows the x positions of the main sprite and the clones to change as the player pushes down on the "a" and "d" Key, While maintaining their proper positions in line. The issue I am having is that for some reason the third costume in my terrain doesn't seem to appear when its clone is created to act as the last tile in line.
I think the issue is that it's already created all the clones, but the first terrain block it clones off of spawns at the same time as the new ones.
By the way, Scrollnum determines the position in the line.
When your clone starts, it goes to the next costume, but since the base spirte's costume is always the first, the clones' will always be the second. You need to set the costume according to the clone ID. That variable (scrollnum) should be "for this sprite only", by the way.
I have had a similar problem, and it's possible that you are not using the right costume number. Try going one costume number down.
I completely forgot about this question but I did manage to figure it out in the and I thought I should post the answer considering that it may be of help to others.
Let me explain this code a bit, as shown in the image this uses a block instead of the repeat loop I attempted to use mainly due to the ability to use it more often as well as condense my code. The CloneX variable is refers to the tiles X positioning as a multiple in reference to the screen size. The equation when used looks like this: (CloneX * 480) + ScrollX. The TileX variable refers to the amount in which you want cloned.
This is how I ended up calling it. I ended up setting the costume to the one I needed for the level in order to start the generation of tiles. Then I initialized for the variables in the block]2

Half scenes with static elements, other with spawn

I have 2D game, where half scene with spawn enemies and (for example) other half scene, where I want use static enemies and other elements.
I thought to create sript that after some time (for example 10 seconds), will stop spawn scripts , and run the movement of other elements.
So. Maybe there is a reasonable solution to this problem.
[UPDATE]
I need the most sensible solution of such a problem, I do not mean to do this, but how to make it better.
1) Can make static elements, which will be a certain time, just stand behind the camera, and then move ... or programmatically create static elements, over time, in advance of known locations...Or download the entire stack of elements over time.
2) Or can completely abandon this idea. A striking example is the Subway Surf, there static scenes (layout) are created in random order.
P.s. I hope I have explained my problem
Just learn to use "Invoke", it's extremely simple.
Invoke( "YourOtherRoutine", 10f );
So after ten seconds it will run the other routine. That routine could easily stop one script running, start another script running, or, whatever it is you want to do. There are tens of thousands of examples of Invoke() and InvokeRepeating() on the usual Unity forums, etc.
From your reference to Subway Surf, I assume that you want to generate static elements like the path and static trains in subway surf and non-Static elements like some moving trains. If so then I have a possible solution.
You can create pre-defined sets of elements (let say 20 or 30 set with different combination of elements) and then spawn them randomly one after another. e.g. have a look at the two reference images below.
Now, note that you might see these scenes exactly as in the images multiple times while playing the game, this is because they are pre-created, The developers behind Subway surf have created these paths and saved them as prefabs and then spawn them at different locations during game play.
You might have noticed that sometime the path is the same but the position of trains is different. This can be achieved by further creating spawn points on your path and then at runtime randomly select points on which you want to spawn your static elements.
In many cases when there are more than one gates you can pass through (I am referring to the gate in the second image). the moving trains spawns on the path of the gate you cross. Spawning the moving train can be achieved as mentioned in step two with a movement script attached to it. Regarding the question of how to know on what path to spawn there are two possible ways (that I can think of right know).
You can keep track of your players current lane and then spawn the train on that lane.
You can place separate triggers on each lane and then detect which lane trigger was triggered and then spawn the train on that lane.
For other moving trains just use the method in step 2 to spawn them but with a movement script attached.

A specific PathFinding approach

I am working on Unity, using C# for a project that should be quite simple.
I am stuck to pathFinding .
I have Looked at Dikjstra's and A* for reference, but for some reason I still can't adopt them to work in my case. I guess my brain :=while(1);
Here is the Idea:
From a textfile I import a "map" where each "*" means Wall, and each " " walkarea. In the map there area randomly placed 2 objects: a bomb and an agent.
The agent must investigate the map (which forms a maze) and discover the bomb. The agent may move to his 8 neighbour tiles if they are NOT Wall. In my code , the agent class hold his own map. for every tile that he visits, he asks the "world map" for info, about his 8 neighbour tiles.
On his own map then he takes a note of the known tiles type(wall / walkpath) , and if it is a walkpath, he also notes, how many times he has visited it. The agent also has a "Prefered direction " list. This tells which tile to choose next to move to, if more than 1 have not been visited.
Up to this point, I have set it up all good and running, and if I let it run, he eventually finds the bomb. The Issue is that because he only runs on a Prefered direction according to the least visited tile , he has to re-visit some tiles too many times like a moron. So what
I must do is this:
If the agent reaches a tile for which, every nighbour is either wall or already visited, then he should investigate his own map, and the notes from the past to find an unvisited tile , and walk to there. Every walk direction has the same weight/cost, so we don't need to consider cost of path.
In my opinion, Dijkstra's is the closest to apply , but I still can't get it right .
Any Ideas or help would be much appreciated.
Thank You
Alex
Part of the issue is how much information you want to allow your agent. If you're willing to let him know where the target is, or at least its general direction in relation to himself, then you can use that to help influence the agent's decisions. This would allow you him to always favor moving in the direction that gets him closest to the goal while taking the least visited path.
Otherwise I'd keep track of each place he visited in a separate map, as well as the 8 neighboring tiles since he has "seen" them, with something like -1 indicating a wall that has been seen, -2 indicating an unseen location, and 0 indicating seen but unvisited. I'd then use A* or a variant on it that would move him to the closest unvisited point based on number of tiles traversed, breaking ties randomly. This would lead to a more trial and error rat in a maze approach.

iPhone pathfinding implementation

I am trying to create a Pacman AI for the iPhone, not the Ghost AI, but Pacman himself. I am using A* for pathfinding and I have a very simple app up and running which calculates the shortest path between 2 tiles on the game board avoiding walls.
So running 1 function to calculate a path between 2 points is easy. Once the function reaches the goalNode I can traverse the path backwards via each tiles 'parentNode' property and create the animations needed. But in the actual game, the state is constantly changing and thus the path and animations will have to too. I am new to game programming so I'm not really sure the best way to implement this.
Should I create a NSOperation that runs in the background and constantly calculates a goalNode and the best path to it given the current state of the game? This thread will also have to notify the main thread at certain points and give it information. The question is what?
At what points should I notify the main thread?
What data should I notify the main thread with?
...or am I way off all together?
Any guidance is much appreciated.
What I would suggest for a pacman AI is that you use a flood fill algorithm to calculate the shortest path and total distance to EVERY tile on the grid. This is a much simpler algorithm than A*, and actually has a better worst case than A* anyway, meaning that if you can afford A* every frame, you can afford a flood fill.
To explain the performance comparison in a in a little bit more detail, imagine the worst case in A*: due to dead ends you end up having to explore every tile on the grid before you reach your final destination. This theoretical case is possible if you have a lot of dead ends on the board, but unlikely in most real world pacman boards. The worst case for a flood fill is the same as the best case, you visit every tile on the map exactly once. The difference is that the iterative step is simpler for a flood fill than it is for an A* iteration (no heuristic, no node heap, etc), so visiting every node is faster with flood fill than with A*.
The implementation is pretty simple. If you imagine the grid as a graph, with each tile being a node and each edge with no wall between neighboring tiles as being an edge in the graph, you simply do a breadth first traversal of the graph, keeping track of which node you came from and how many nodes you've explored to get there. You mark a node as visited when you visit it, and never visit a node twice.
Here's some pseudo code to get you started:
openlist = [ start_node ]
do
node = openlist.remove_first()
for each edge in node.edges
child = node.follow_edge(edge)
if not child.has_been_visited
child.has_been_visited = true
child.cost = node.cost + 1
child.previous = node
openlist.add(child)
while openlist is not empty
To figure out how to get pacman to move somewhere, you start with the node you want and follow the .previous pointers all the way back to the start, and then reverse the list.
The nice thing about this is that you can make constant time queries about the cost to reach any tile on the map. For example, you can loop over each of the power pellets and calculate which one is closest, and how to get there.
You can even use this for the ghosts to know the fastest way to get back to pacman when they're in "attack" mode!
You might also consider flood fills from each of the ghosts, storing in each tile how far away the nearest ghost is. You could limit the maximum distance you explore, not adding nodes to the open list if they are greater than some maximum cost (8 squares?). Then, if you DID do A* later, you could bias the costs for each tile based on how close the ghosts are. But that's getting a little beyond what you were asking in the question.
It should be fast enough that you can do it inline every frame, or multithread it if you wish. I would recommend just doing it in your main game simulation thread (note, not the UI thread) for simplicity's sake, since it really should be pretty fast when all is said and done.
One performance tip: Rather than going through and clearing the "has_been_visited" flag every frame, you can simply have a search counter that you increment each frame. Something like so:
openlist = [ start_node ]
do
node = openlist.remove_first()
for each edge in node.edges
child = node.follow_edge(edge)
if child.last_search_visit != FRAME_NUMBER
child.last_search_visit = FRAME_NUMBER
child.cost = node.cost + 1
child.previous = node
openlist.add(child)
while openlist is not empty
And then you just increment FRAME_NUMBER every frame.
Good luck!
Slightly unrelated, but have you seen the ASIPathFinder framework? Might help if you have more advanced pathfinding needs.
I would recommend just pre-computing the distance between all pairs of points in the map. This takes n^2/2 space where there are n traversable points in the map. According to this link there are 240 pellets on the board which means there are about 57k combinations of points that you could query distances between. This is pretty small, and can be compressed (see here) to take less space.
Then, at run time you don't have to do any real computation except look at your possible moves and the distance to reach that location.