SpriteKit & Swift: How to create level "segments" that are randomly "stitched" together to create an endless game? - swift

The concept that I am talking about is similar to the style of game seen in many minimalistic, popular mobile games such as Color Switch, the Line Zen, Phases, or Bounce. These are endless games composed of a series of "levels" or "rooms" that are placed in a random order, and are one after another, creating the effect of an endless game. The key thing is that the challenges in each level are not random, they are drawn up before, and if that certain level is chosen randomly, it appears on the screen and the player moves through that level.
I think this concept might be called procedural generation, though I'm not positive.
How would I do this in SpriteKit using Swift? I'm not really sure where to start, maybe create a function for each level segment and, every few seconds, choose a random one to put on the screen?
Any help is appreciated!
Thanks so much!

Procedural generation is the name of the concept you are describing.
The approach will change a bit depending on the type of game you are trying to make but let's look at procedural generation in an infinite runner game. What you want to do is set up a buffer of level segments. The total size of the segments in your buffer should be at least twice the size of the screen. Every segment should be a child of the same segments node and they should be positioned so that each starts right after the previous one ends.
When a segment moves off screen (the player passed it):
remove that segment from the segments node
initialize a new segment (probably from a sks file)
add the new segment to the segments node
position it behind the last segment in the segments node.
The logic you use for choosing the next "random segment" is up to you. It can be truly random or you can fine tune it for the best user experience (avoid repeating segments, avoid segments that would ruin the flow, etc).
The key is to remove segments as they go offscreen and add a new one at the end of the buffer. This must be position based, not time based (time is less reliable even when the game scrolls at a constant speed).

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

How can I create larger worlds/levels in Unity without adding lag?

How can I scale up the size of my world/level to include more gameobjects without causing lag for the player?
I am creating an asset for the asset store. It is a random procedural world generator. There is only one major problem: world size.
I can't figure out how to scale up the worlds to have more objects/tiles.
I have generated worlds up to 2000x500 tiles, but it lags very badly.
The maximum sized world that will not affect the speed of the game is
around 500x200 tiles.
I have generated worlds of the same size with smaller blocks: 1/4th the size (it doesn't affect how many tiles you can spawn)
I would like to create a world at least the size of 4200x1200 blocks without lag spikes.
I have looked at object pooling (it doesn't seem like it can help me
that much)
I have looked at LoadLevelAsync (don't really know how to use this,
and rumor is that you need Unity Pro which I do not have)
I have tried setting chunks Active or Deactive based on player
position (This caused more lag than just leaving the blocks alone).
Additional Information:
The terrain is split up into chunks. It is 2d, and I have box colliders on all solid tiles/blocks. Players can dig/place blocks. I am not worried about the amount of time it takes for the level to load initially, but rather about the smoothness of the game while playing it -no lag spikes while playing.
question on Unity Forums
If you're storing each tile as an individual GameObject, don't. Use a texture atlas and 'tile data' to generate the look of each chunk whenever it is dug into or a tile placed on it.
Also make sure to disable, potentially even delete any chunks not within the visible range of the player. Object pooling will help significantly here if you can work out the maximum number of chunks that will ever be needed at once, and just recycle chunks as they go off the screen.
DETAILS:
There is a lot to talk about for the optimal generation, so I'm going to post this link (http://studentgamedev.blogspot.co.uk/2013/08/unity-voxel-tutorial-part-1-generating.html) It shows you how to do it in a 3D space, but the principales are essentially the same if not a little easier for 2D space. The following is just a rough outline of what might be involved, and going down this path will result in huge benefits, but will require a lot of work to get there. I've included all the benefits at the bottom of the answer.
Each tile can be made to be a simple struct with fields like int id, vector2d texturePos, bool visible in it's simplest form. You can then store these tiles in a 2 dimensional array within each chunk, though to make them even more memory efficient you could store the texturePos once elsewhere in the program and write a method to get a texturePos by id.
When you make changes to this 2 dimensional array which represents either the addition or removal of a tile, you update the chunk, which is the actual GameObject used to represent the tiles. By iterating over the tile data stored in the chunk, it will be possible to generate a mesh of vertices based on the position of each tile in the 2 dimensional array. If visible is false, simply don't generate any vertices for it.
This mesh alone could be used as a collider, but won't look like anything. It will also be necessary to generate UV co-ords which happen to be the texturePos. When Unity then displays the mesh, it will display specific points of the texture atlas as defined by the UV co-ords of the mesh.
This has the benefit of resulting in significantly fewer GameObjects, better texture batching for Unity, less memory usage, faster random access for any tile as it's not got any MonoBehaviour overhead, and a genuine plethora of additional benefits.

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.

How should I have my game entities knowledgeable of the things around them?

Every enemy type in my game is a different class, and the instances are stored in a C array. In the main game loop update() is run for each enemy/item instance, and draw() is run. Some of the update() commands require knowledge of where the main player is. What would be the best route to get that information to the instance? I don't think a global variable is the smart way to do it, since multiplayer options may be added later.
This is only an example of the bigger problem, which is how things in the game are supposed to know about each other. How would enemies know they're colliding with other enemies for example.
Your need to build a multi-branched tree type structure (not simple binary tree). The nodes are the locations in the game. Each node can contain multiple simple stuctures/objects pointers (depending on your programming language). As the player moves around the game you move your player position pointer to the tree node representing the location. When you start the game this tree type stucture is populated with things to pick up, monsters etc. A random seed can also be use to scatter monsters around.
This helps the speed of the game as you only have to search current node and nodes one step away from your current location/node. Any routines triggered that monsters advance or retreat just move the monsters pointer to the next node or nodes. If a med pack is used then its pointer is destroyed from the room/node that it is in.
Good luck
One way to make the search a bit more efficient is to split the entities being updated into a quad tree. The tree would get divided based on location on the screen or in the game world you have setup. This way you can set it up so only near by entities get updated. So for example if you're doing hit detection you can totally ignore large groups.
quad trees
hope that helps
A Controller entity?
You need to think carefully about using plain arrays, linear searches through large arrays can be very time consuming to search for things like collisions.
All entities in the game, including the player, should be in the same container. Your AI will loop through them every frame and call some function that executes all the goals of every entity.
Entities (like the player) have access to all other entities through the same container.
You'll have to get clever about the container to make the entity access to the container efficient, however.