SKTileMapNode: Create an infinitely sized tile map - ios

Over on the Apple Documents It claimes you can make an infinitely sized SKTileMap
Generating procedural game-world maps resembling natural terrain. You can create game world of infinite size by using procedural noise as its underlying representation, and manage storage and memory efficiently by creating noise maps (and their visual representations) only for the area around a player’s current position. (See the SKTileMap class.)
I can generate realistic terrain with GKNoise like the Apple Documents claim you can.
I cannot, however, make 1 giant infinitely sized SKTileMapNode it would be to intense to run on a device
The Apple Documents say to make an SKTileMapNode only around the players current position (like chunks in minecraft)
how can I achieve this in swift? my RPG needs to be infinitely sized to achieve everything I want to do with this game.
I need the "chunks" to be SKTileMapNodes because I need trees, stone, water, etc. to be added to the map so the player can interact with it.

The solution to your problem begins in making the GKNoise tileable.
You are probably using GKNoiseMap to generate them.
When you use the initializer:
let map = GKNoiseMap(_ noise: GKNoise, size: vector_double2,
origin: vector_double2, sampleCount: vector_int2, seamless: Bool)
Important: Don't forget to set the "seamless" variable to true.
That way you get a tileable map.
It looks better when you make them larger than the screen.
Let's say that a part (tileable) of the map that is your realistic terrain is going to be 2048 by 2048
One map may cover 128x128 tiles, for example. In this case each SKTile would be 16x16 pixels
You make a SKTileMap with 128x128 tiles.
Now the SKTileMap needs a background image, or the tile definitions (in this case, it is the GKNoiseMap, that you generated)
Now you can just use the same GKNoiseMap map, and place next to the first map, in any direction, containing another tile map of 128x128 tiles.
Your map is now 256x128 tiles. When the user scrolls, they can't tell where one image ends and another begins so the whole size of the map can be as large as you want, by repeating the same exercise.
It works well when you generate GKNoiseMap bigger than the screen, when you have to scroll a couple of times before the next GKNoiseMap starts. That way it doesn't get visually repetitive.
The area around "the player's position" can be one map, and then when you scroll, the map can repeat itself, saving you from loading anything else besides the map you already generated. That answers the " and manage storage and memory efficiently by creating noise maps" part of your question.
You should also be careful with Data Storage. If every SKTile needs to store variables different than what the GKNoiseMap will give you, infinite maps can be expensive.

Related

Isometric Depth Sorting With SpriteKit

I am making a relatively simple isometric map using SpriteKit. I've tried both using the editor as well as creating it through code, and each time, it seems to have some "weighting" between the various tiles even though they should overlap gracefully given that I'm just setting the styling of a tile.
Here is an example of me using the tiles from https://kenney.nl. The green is just a standard grass patch and the road is the same exact size as it.
When I create this map in the XCode UI or if i iterate through in code and paint them, this continues to occur.
However, if I was to do something like flip the tiles around and paint it all with roads with grass in the middle, it then seems to sort whichever tile there are "more of" like in this example:
If i go and make more of one tile group over another, it seems to overpower it.
So my question is, how can I keep them from using this behavior? I've tried different tilemaps together, nested them inside of eachother etc... But at the end of the day, I cant get different tiles to exist at the same "plane". I've tried with code, the UI, etc. I'd like to use the SKTileMap if possible to use the downstream features as opposed to doing all of the math myself, like in the approach in this article (http://bigspritegames.com/isometric-tile-based-game-part-1/)

Interact with complex figure in iOS

I need to be able to interact with a representation of a cilinder that has many different parts in it. When the users taps over on of the small rectangles, I need to display a popover related to the specific piece (form).
The next image demonstrates a realistic 3d approach. But, I repeat, I need to solve the problem, the 3d is NOT required (would be really cool though). A representation that complies the functional needs will suffice.
The info about the parts to make the drawing comes from an API (size, position, etc)
I dont need it to be realistic really. The simplest aproximation would be to show a cilinder in a 2d representation, like a rectangle made out of interactable small rectangles.
So, as I mentioned, I think there are (as I see it) two opposite approaches: Realistic or Simplified
Is there a way to achieve a nice solution in the middle? What libraries, components, frameworks that I should look into?
My research has led me to SceneKit, but I still dont know if I will be able to interact with it. Interaction is a very important part as I need to display a popover when the user taps on any small rectangle over the cylinder.
Thanks
You don't need any special frameworks to achieve an interaction like this. This effect can be achieved with standard UIKit and UIView and a little trigonometry. You can actually draw exactly your example image using 2D math and drawing. My answer is not an exact formula but involves thinking about how the shapes are defined and break the problem down into manageable steps.
A cylinder can be defined by two offset circles representing the end pieces, connected at their radii. I will use an orthographic projection meaning the cylinder doesn't appear smaller as the depth extends into the background (but you could adapt to perspective if needed). You could draw this with CoreGraphics in a UIView drawRect.
A square slice represents an angle piece of the circle, offset by an amount smaller than the length of the cylinder, but in the same direction, as in the following diagram (sorry for imprecise drawing).
This square slice you are interested in is the area outlined in solid red, outside the radius of the first circle, and inside the radius of the imaginary second circle (which is just offset from the first circle by whatever length you want the slice).
To draw this area you simply need to draw a path of the outline of each arc and connect the endpoints.
To check if a touch is inside one of these square slices:
Check if the touch point is between angle a from the origin at a.
Check if the touch point is outside the radius of the inside circle.
Check if the touch point is inside the radius of the outside circle. (Note what this means if the circles are more than a radius apart.)
To find a point to display the popover you could average the end points on the slice or find the middle angle between the two edges and offset by half the distance.
Theoretically, doing this in Scene Kit with either SpriteKit or UIKit Popovers is ideal.
However Scene Kit (and Sprite Kit) seem to be in a state of flux wherein nobody from Apple is communicating with users about the raft of issues folks are currently having with both. From relatively stable and performant Sprite Kit in iOS 8.4 to a lot of lost performance in iOS 9 seems common. Scene Kit simply doesn't seem finished, and the documentation and community are both nearly non-existent as a result.
That being said... the theory is this:
Material IDs are what's used in traditional 3D apps to define areas of an object that have different materials. Somehow these Material IDs are called "elements" in SceneKit. I haven't been able to find much more about this.
It should be possible to detect the "element" that's underneath a touch on an object, and respond accordingly. You should even be able to change the state/nature of the material on that element to indicate it's the currently selected.
When wanting a smooth, well rounded cylinder as per your example, start with a cylinder that's made of only enough segments to describe/define the material IDs you need for your "rectangular" sections to be touched.
Later you can add a smoothing operation to the cylinder to make it round, and all the extra smoothing geometry in each quadrant of unique material ID should be responsive, regardless of how you add this extra detail to smooth the presentation of the cylinder.
Idea for the "Simplified" version:
if this representation is okey, you can use a UICollectionView.
Each cell can have a defined size thanks to
collectionView:layout:sizeForItemAtIndexPath:
Then each cell of the collection could be a small rectangle representing a
touchable part of the cylinder.
and using
collectionView:(UICollectionView *)collectionView
didSelectItemAtIndexPath:(NSIndexPath *)indexPath
To get the touch.
This will help you to display the popover at the right place:
CGRect rect = [collectionView layoutAttributesForItemAtIndexPath:indexPath].frame;
Finally, you can choose the appropriate popover (if the app has to work on iPhone) here:
https://www.cocoacontrols.com/search?q=popover
Not perfect, but i think this is efficient!
Yes, SceneKit.
When user perform a touch event, that mean you knew the 2D coordinate on screen, so your only decision is to popover a view or not, even a 3D model is not exist.
First, we can logically split the requirement into two pieces, determine the touching segment, showing right "color" in each segment.
I think the use of 3D model is to determine which piece of data to show in your case if I don't get you wrong. In that case, the SCNView's hit test method will do most of work for you. What you should do is to perform a hit test, take out the hit node and the hit's local 3D coordinate of this node, you can then calculate which segment is hit by this touch and do the decision.
Now how to draw the surface of the cylinder would be the only left question, right? There are various ways to do, for example simply paint each image you need and programmatically and attach it to the cylinder's material or have your image files on disk and use as material for the cylinder ...
I think the problem would be basically solved.

Is it wise to export a Tiled layer into 1 big png file to save memory?

I just made the background layer in Tiled for my map for Sprite Kit. The main layer is the background layer where the grass, dirt, water & the lot is drawn - this what the player character "walks on". This map is consisted of tiles that are 16x16 (keeping them this small for having better control over the little details during design of the map). The map it self is 100x100. So it's pretty decent size wise. I have roughly between 757-778 nodes just because of these background tiles. That's too much and I haven't even added a single tree to the second layer. Since I'm using Tiled as the map editor with JSTileMap to display it, can I just somehow export the ready background layer from Tiled into a .png file and load that into the game as 1 big picture to drop the node count to 1. Wouldn't this drastically help performance and memory? The others layers have their images spread across & there's a layer that's responsible for the boundaries. Is this a clever way of going about making the game or am I missing something? If it is, does anyone know how to export the layer into a .png file? I checked Tiled & couldn't find anything like that.
You are most definitely better off having a single PNG/node as your background. There are some benefits of doing this:
You have just one node.
You can add the node to self and place it behind the rest of the action. This way it will always be there regardless of you moving any other nodes.
In the picture below I added a background to the view and have 3 other tile layers plus 1 object layer. My node count is still substantially less than 700.
As for exporting what you already have, I don't think there's a way to save an entire tile layer as one PNG. As a hack you could take a screenshot, crop the background part and work with that.

Advice for library with GeoSpatial Mapping that allows users to place moving objects on a 2D map

I'm looking for a library/framework/toolkit that will allow me to render a 2D map from real GeoSpatial data and draw objects on the 2D map.
Requirements:
Map Tiling (when I zoom into the map, i want a more detailed image)
Pan (ability to use the mouse to move around the map)
Read various Geospatial images (satellite, street, etc)
Ability to draw objects onto the map (based on lat/longs) and have them move. For example, I want to be able to put an image of a bird on the map and have it move and rotate correctly.
Primitive shapes. It would be nice if it had built in ability to draw lines, circles, etc.
Complex drawing. For example, I want to draw a compass and have it show the heading of the current heading of the bird.
Mouse input. I want to be able to right click on the map and have a context menu appear. I want to click and hold an shape I draw on the map and drag it easily.
What I have looked at:
OpenSceneGraph with osgEarth. It's great, and fulfills my reqs, but is really slow and I had to do a lot of weird things to get things to work (especially with dragging objects on the map).
Cesium: looks promising, but somewhat slow, and I need it to work as a desktop application. I've seen online that some have managed to use Cesium inside Qt's Webkit, but I'm not sure I would want to take that risk.
EDIT:
I really want to stay away from a web-based framework if possible.
http://imgur.com/52DaJtQ
Here is a primitive picture of what I'm want to achieve. The aircraft icon should move and the degree circle along with it. I want to be able to drag the green waypoints and have the lines redraw as I move a waypoint. The red sensor footprint should adjust to what the aircraft can see.
http://imgur.com/52DaJtQ
Google Maps, Open Street Map, Bing Maps.
I use OpenSceneGraph/osgEarth extensively and am not dissatisfied with its performance.
What kind of weird things did you need to do?
If you want, you can contact me privately to troubleshoot your situation. Me website is AlphaPixel.com and there's a contact form there.

Tiled 2d World Map Size Issue

Hey all, I am creating a 2D tile based XNA game. Basically the character can move any direction one tile at a time. I am using the Tiled map editor: http://www.mapeditor.org/ to create my map. I have not found any good tutorials or documentation on this yet.
Here is my issue:
I am attempting to load a very large world map into my game. Each gridspace is 32x32 pixels. The map itself is 1000x1000 gridspaces. At a first glimpse, this seems bad because of the size. When I loaded this WorldMap into my game XNA threw an out of memory error because the image was too large. I feel like I am approaching this from the wrong angle. Does anyone know a better way to handle a large world map? It would be nice to only load in what the character can see, that would be way more efficient however, that does not solve my problem of loading this huge image. Another idea would be a smaller image for each area but I am not sure how to do that since it's a world. Any ideas, tips, tutorials, I am sure this is a common issue that has been solved several times using several different solutions. Thank you!
When I was creating 2d XNA game I did:
My own format of binary map file. This file contains map name, map width and height in tiles etc and map array. It was simply byte array (byte[]) where each value corresponds to tile type.
Tile type. It's just simple class with some properties: movement cost (-1 if player can't move over this tile), which types of creatures can live in this tile, tile images etc.
Tile types db. It's just xml file contains tile types.
So, when game loads a level:
Load map and find in tile type db tiles which used in this map.
Load appropriate images for this tiles. Only once. It can be reused for different tiles with same type.
Draw only visible (for player) tiles with some reserve. As example draw only screen_width/tile_size_y*2 in width and screen_height/tile_size_y*2 in height. When player moves recalc visible tiles.

Resources