Ralph Barbagallo's Self Indulgent Blog

I'm from the future.

App Engine Geospatial Datastore Search: A New Way!

One of my pet peeves with Google App Engine is its horrible support for geospatial indexes. Although you can store a GeoPt in the Datastore, you can’t really query it. You can use various hacks such as Geomodel, but they end up being slow and potentially expensive.

Last year Google released the beta API for Google App Engine search. This lets you search documents for text, HTML, numbers, dates, and location. However, it searches documents instead of datastore entities.

If documents are separate from your datastore, how do you use the new search API to do geospatial queries on your database? Simply store the location for each entity inside a document instead. To do this, make a document with a GeoField with the location and a string that contains the id of the associated datastore entity’s key (this code is based on Google’s own location example):

key = str(entity.key())
geopoint = search.GeoPoint(lat, lng)
index = search.Index(_INDEX_NAME)
document = search.Document( fields=[search.TextField(name='key', value=str(key)),
                                                    search.GeoField(name='loc', value=geopoint)])
search.Index(name=_INDEX_NAME).put(document)

Note that you have to store the key’s id as a string since you can’t store a long in a document.

Now, when you perform a geolocation search like this:

index = search.Index(_INDEX_NAME)
query = "distance(loc, geopoint(" + str(lat) + "," + str(lng) + ")) < 1000"
     
try:
     results = index.search(query)
     for doc in results:
         logging.info('Document! ' + str(doc.field("key")))
except search.Error:
     logging.exception('Error!')

You can grab the id field from the document and query the datastore for it to get the rest of your data.

There are several problems with this method. First, it doesn’t work on the local dev_app_server. Currently, GeoField searches only work on the appspot production servers. Also, because the API is in beta you are restricted to the free quotas which don’t allow for very many operations. Finally, when Google reveals pricing changes, it can have disastrous results. It’s very risky to build an app using this method when you have no idea how much it costs.

At least it works! It’s still a mystery to me why they can’t add this feature to the datastore itself.

Lost Classic: Sega’s Panzer Dragoon Saga

As we come to the conclusion of the longest hardware generation in console history, no doubt some great games will get lost in the shuffle. At this point in the cycle developers have mastered the technology of current platforms. Some of the greatest games of a generation will be released only to be overlooked for a set of shiny new launch titles on the next boxes. It’s a tragedy.

One such game is Sega’s lost masterpiece, Panzer Dragoon Saga for the Saturn. Released in 1998–mere months away from the Japanese launch of the ill-fated Dreamcast–PDS is an excellent RPG most Saturn owners never played. Very few copies of this highly rated game were produced in the West–driving up eBay prices beyond $400 in some cases.

Panzer Dragoon Saga’s combat system

A few years back I was able to callously take advantage of a friend in need when he had to sell his game collection during a move. I picked up his set of rare Saturn games (including Burning Rangers and Shining Force III) for a steal. For years these games sat in a box on my shelf until in a fit of total boredom I decided to play through Panzer Dragoon Saga.

For those who don’t know, Panzer Dragoon was a launch title for the Saturn in 1995. It was the last great original fantasy universe in games, featuring a hybrid of modern technology and fantastic monsters exquisitely detailed by famed French artist, Moebius. It’s really amazing how his awesome concept art comes through in the low-res textures and primitive rendering technology of the time.

A total of five Panzer Dragoon games were produced, with the third one being Panzer Dragoon Saga. PDS was a diversion from the original games, mixing the world exploration and character development of a JRPG with the series’ signature rail shooting action.

Plenty of blogs and reviews have waxed nostalgic about this game, so I’ll keep it short. The overworld exploration elements are very basic with simplistic puzzles and low-detail landscapes. The storyline is derivative and delivered with pixelated full motion video–remember, this is back when Cinepak was hot. Where the game really shines is in the combat system.

Combat in PDS consists of a flying shooter sequence similar to the original Panzer Dragoon. Your dragon is engaged in an endless flying combat encounter for the duration of the sequence. You can wait while charging your meter (leaving you vulnerable) to unleash powerful attacks or strategically choose to strike, using a combination of guns, lasers, and special skills. Positioning is important, as some monsters have weak spots only visible from certain perspectives.

Another interesting wrinkle is how your dragon evolves through the course of the game depending on how you treat it. This evolution provides you with new combat skills and lets you decide which form to use before encounters. If you get wiped out in battle, try it again with a different form and set of skills. Granted, this is rarely used as the game is kind of easy.

It’s kind of amusing to read about the “massive” development of PDS. At the time, the game’s 2 year development cycle and 40 member team seemed immense. Today, AAA games can sometimes have staff numbering in the thousands, development times of well over 5 years, and pre-marketing budgets of over $100m. Sadly, PDS ended up being Team Andromeda‘s swan song. They were later folded into Sega Sports Japan which currently makes forgettable sports games featuring Mario and Sonic. A true atrocity.

Although some parts of the game would have to be fleshed out to keep up with modern JRPG standards, Sega would be doing this generation of gamers a favor by producing a 3DS remake. Until this unlikely event, you owe it to yourself as a true nerd to play through Panzer Dragoon Saga–If you can find a copy at a reasonable price.

DIY 3D Printing Is Not Ready For Prime Time

For the past few months I’ve been working on a project that involves creating a series of plastic miniatures that work with an Augmented Reality app. Creating toys from 3D models built for a game seemed a natural application for 3D printing. The idea being I make a positive out of a game model with a 3D printer, then use that to create a silicone mold for resin copies (a very old school process). To figure out how this all works, I’ve spent a few months immersed in additive manufacturing.

My first stop along this journey was to my local 3D printer store. I visited DeezMaker in Pasadena to see their BukoBot in action. This is a hobbyist printer that uses the same sort of filament printing technology the pioneering MakerBot does. The staff at DeezMaker gave me a good crash course in the different models, usually ranging from $600-1500. The software used to run the machine, Slic3r and Repeiter Host, are free and open-source.

A friend of mine has a BukoBot and was willing to do a test print of a figure. The first step was to ready the in-game model for printing. 3D printers need a model in STL format, which is a simple conversion process from most 3D programs. However, the model itself must be completely solid. You can’t have any holes, floating one-sided polygons, and other non manifold edges. Slic3r (the software used to ‘slice’ the model into vertical chunks used for printing) detected these problems in the STL file and spit out a series unhelpful error messages. The artist that built the model was able to fix these problems in Maya while running it through the slicer to check for errors.

With a cleaned up model file in hand, I visited my friend’s house and we began the print. It took a few hours to slice the model and set up the print area properly. This involved scaling down the model a bit to fit on the printer’s bed and messing around with the machine to get it aligned properly. Soon, the print began, and we waited with giddy excitement.

Some 20 hours later, my print was finished and the end results were…..well not that great.

A BukoBot print of a 3D model

In the BukoBot’s defense, this was a single material print. For complicated objects such as this figure, you need to use a support material. This is a water-soluble substance that is printed underneath overhangs and other floating features. When the print is done, you submerge the object in a bucket of water and wait for the support material to dissolve. Otherwise, it’s going to print ‘fluff’ material to support the model and you’ll have to break it off by hand.

In reality, these kit printers kind of suck. The engineering tolerances are pretty loose–especially in the BukoBot’s case as the printer is built, in part, by 3D printers. A lot of the pieces such as those that guide the printer head aren’t very precise and result in skewed prints. The printer is also prone to erroneously burping up large blobs of material, throwing off the accuracy of the print. Finally, the object lies on an open bed and cools rapidly to room temperature which warps the material. The end result is kind of a disaster, even on the most simple of objects.

My next step was to see what options were available for high-end 3D printing. I considered services like Shapeways, but their turnaround time was too long and they have draconian limits on file size and triangle count. I talked to a few different places that had professional-quality printers, and eventually printed my model using a uPrint SE by Stratasys at TekPro Group in Woodland Hills.

Sure, the printer costs nearly ten times what the BukoBuot does, but you get what you pay for. The end result is simply amazing. The uPrint uses the same FDM process as the BukoBot but is much more precise. It still took over 20 hours to print, but in this case it’s worth it.

Side by side comparison of uPrint and Buko Bot print

If you look closely you can still see some roughness to the surface. I gave the printed model back to the (elated) artist and he’s working on smoothing it using acetone and sanding. Before we do a resin cast it may be necessary to carve more detail into the figure as well as use putty to fix a few errors we didn’t catch in the modeling phase.

A closer look

Low-end kit 3D printers may be disruptive to the high-end machines. Certainly the quality and fussiness of printer kits reminds me of personal computers from the Homebrew Computer Club era which disrupted mainframes. At the surface, the war between professional and kit printers seems to be torn from the pages of The Innovator’s Dilemma.

As it stands now, kit printers just aren’t ready for prime time–by far. Newer models have shown dramatic increases in performance, but we are still probably a generation or two away from approaching the quality of high-end machines like uPrint or Objet. Meanwhile, the search is still on for a consumer application for 3D printers that will make an audience beyond hobbyists and manufacturing actually want them.

How To Know If You Are Suffering From Dunning-Kruger

The Dunning-Kruger effect is a plague that strangles the progress of humanity. It is the fact that those who suck overestimate their ability, while those who don’t underestimate their ability.

Dunning-Kruger is what keeps money flowing to the confident and inept, only for these funds to be set ablaze in a bonfire of incompetence. Once the fire is out, a new flame burns as the cycle repeats. Those who possess true skill often do not have the self confidence to start their own fire. Perhaps this is why we don’t have our flying car.

How do you know if you suffer from Dunning-Kruger? By definition, nobody really knows; both parties are oblivious. The key is in the second element of the hypothesis: those who lack skill fail to recognize it in others.

If you’ve been responsible for a direct hire, how did that person turn out? If you’ve recommended people for jobs, how have they performed? Perhaps the only way to recognize if you are a Dunning-Kruger sufferer is to use this test to see whether you can identify true skill in others.

How do I fare? After a cursory assessment of candidates I’ve interviewed and people I’ve recommended for positions, I think I’ve got a pretty good track record. The majority of the individuals and firms I’ve recommended to others have done exceedingly well at their jobs. Also, my reservations about those I’ve interviewed have been largely proven true–At least when dealing with my own area of expertise.

I like to say that I’m just smart enough to know I’m a complete idiot. But, when it comes to Dunning-Kruger, It’s not enough to be humble. You could be faking it.

Donut Vision: Google App Engine Experiments 2

Some (well, very few) of you may remember my previous post on Google App Engine. Developing a GAE app using JSP was a trip down memory lane, using a technology that has seemingly been left unchanged since 2001.

I recently began a project that involves using Vine and Twitter to sort through video clips. I decided to build on Google App Engine again. This time I’m using Python. My initial hacking has resulted in Donut Vision–a search portal for donut videos on Vine. Hey, don’t laugh. These guys are trying to build an actual business off of the same type of sites–Presumably with cokehead money.

Using Python (GAE’s original language) has been an absolute pleasure. On GAE, it really does seem much faster than using Java. GAE’s built in webapp2 framework and Django templates make building sites and APIs a breeze. I swear not having to type brackets has given me some kind of minor productivity boost–Or not. But placebo is a real thing.

My general “get off my lawn” nitpicks with Python are mostly due to it being a weird hybrid of a dynamic language, yet strongly typed. This gives PyDev in Eclipse a problem performing autocomplete since it really doesn’t know what type you’re referring to in most cases. PyDev and Eclipse is a decent combination due to the convenience of deploying to GAE within the IDE. I’d switch to something else with better autocomplete support, though.

As for the details of how this works, it’s really pretty simple. There’s no Vine API yet, so I simply use the Twitter API to search for Vines with relevant hashtags and pull the URLs out of them. Originally I was using Vine’s new embed code to display videos, but I eventually resorted to grabbing the URL of the MP4 file in the S3 bucket it’s stored in to have more control over the video when playing it with video-js. I expect Vine to shut down this method since I’m just running up their AWS bill with no benefit to them–not even a link back to the Vine app. Hey, if Vine provides a proper API, I’d use it.

Oh also, in my earlier post I stated that Google App Engine is not available in China. This is only partially true. The default appspot domain is indeed blocked in China. Yet, when putting my custom domain, donuts.pw, through GreatFirewallOfChina.org I get nothing but green status. Yes, I’m boldly sparking a democratic revolution one French Cruller at a time. So, if you want to serve Chinese customers via GAE, just map a custom domain to it.

I’m seriously considering using Google App Engine as a backend for a new game. The only problem is cost estimation. I have constant paranoia of real-world usage patterns running up my bill. Especially with improperly indexed datastores, you can rack up charges pretty fast. Still, simply writing an app and uploading it to Google’s cloud is significantly easier than fiddling with Amazon Web Services and Beanstalk. If you haven’t checked it out since the early days, GAE is worth another look.

Oh, also the latest version of GAE has sockets support. It’s still experimental, but this may lead to GAE being suitable for real-time applications such as multiplayer game servers.

National Caramel Popcorn Day

Tech has become rather boring lately. It’s quiet. Too quiet. We’re ripe for disruption at some point. Until that happens, let’s focus on something important: like caramel corn.

Did you know April 6th is National Caramel Popcorn day here in the US?

Those who follow me on Instagram may have noticed my penchant for Japanese snacks. Whenever I visit Japan I try to stop in as many kombinis as possible to experience the latest in snackery. In fact, one of my most popular YouTube videos is a mere walk-through inside Japanese FamilyMart.

To mark this important event, I figured I’d write an ode to my favorite Japanese snack, Tohato’s Caramel Corn.

Tohato is a rather hip Japanese snack company with a small array of products. Although, they do have a few other treats that I like, their Caramel Corn product seems to be the flagship.

The original Caramel Corn flavor is just that: caramel flavored corn snacks with peanuts. Keep in mind this isn’t caramel corn as we are used to in the West; caramel coated popcorn. No, these are U-shaped corn formations saturated with some kind of artificial caramel substance.

A piece of Caramel Corn

A piece of Caramel Corn

Much like Japanese Kit-Kats, the amazing minds at Tohato have produced a number of weird and wacky flavors, including limited edition exclusives. Despite the fact that these flavor breakthroughs aren’t based on caramel and the corn merely exists as a vehicle for artificial flavoring, they are still marketed under the “Caramel Corn” banner.

I often reminisce about the Summer of 2010 when Tohato released Ramune flavor Caramel Corn. Ramune is a Japanese soft drink similar in flavor to Sprite. Ramune Caramel Corn came in an unearthly glowing blue hue and tasted like a mutant Froot Loop. It was glorious.

Here’s a photo of my latest haul during a recent trip to Nijiya Market in West Los Angeles. I can’t read Japanese, so the fun of discovery involves trying to guess what the flavor is from the packaging and then tasting it.

Glory.

Glory.

For those less adventurous, you can Google Translate Tohato’s Caramel Corn page. Looks like they have a limited edition boiled egg flavor! I need to track that down. Unless one of my Japanese readers might want to send me a pack. You never know, Brick Buddies is big in Japan.

A Few Quick Notes: GDC2013 Edition

Before we get started, vote for evolve.la

Blatant plug!–please vote for evolve.la in the My LA2050 grant contest. I’m in the running to build a social gaming experiment that will attempt to analyze social media activities of Los Angelenos to determine how they want the future of Los Angeles to look. I need your votes to get evolve.la off the ground! We now continue with your irregularly scheduled blog post.

GDC 2013 Rundown

GDC has become increasingly irrelevant over the past 5 years or so as influence has moved away from the realm of cloistered AAA console game teams and to so-called “indie” developers and the disruptive platforms of mobile and social. Because of this, you can get much better information having conversations with other developers. I spent most of GDC talking to people–you can always watch the good presentations on the GDC Vault.

The trend for 2013 is an industry wide panic over free2play. Presentations and panels worried over whether f2p games are ethical and how the game industry is supposed to survive through this disruption. Considering this is a conversation game developers have been having since 2009, it just goes to show how long it takes for GDC to catch on to major trends.

“Indie” developers were the big celebrities this year. So much so that formerly closed platforms from Nintendo and Sony bent over backwards to encourage garage developers to create content. Nintendo greatly loosened requirements for their development program and even revealed HTML5 support for the Wii U. Sony eliminated concept approval. This shows there are some radical changes ahead for the next generation–Changes I suggested years ago on this blog.

The biggest star of the show was Oculus VR. The wait time to try the Oculus Rift headset grew to over 2 and a half hours by the final day of GDC. I got in to see it and came away hopeful, but unimpressed. The current prototype headset is uncomfortable, but I didn’t spent much time adjusting it. The display resolution is low, causing a screen door effect. When I turned my head, the screen smeared to the point where I couldn’t see anything.

These problems are being addressed. They showed me the physical part for the new screen–the retail version of Oculus will fix the resolution and latency issues. The current kit is strictly for developers and mega-nerdy early adopters. It’s pretty neat for a $300 prototype, but far from a finished product.

I was more impressed with Infinite Z’s zSpace virtual holography system that was on display at Unity3D’s booth. It costs over 10X what Oculus does for no apparent reason. Still, being able to draw 3D splines in thin air and look around them was really cool.

Overall, GDC had a lot of opportunity on display as far as new devices, markets, and tools–but a lot of uncertainty on how to actually make money producing games.

Favorite Quotes of GDC

  • “Cokeheads are better than publishers.”

  • “They said they’d publish my game if I turn it into a Skinner-box.”

  • “The reason why you won’t close the deal is because you’re too competent.”

Stop Hiring Advertising Agencies to Write Software

Advertising agencies traditionally build “creative” campaigns such as commercials and print ads that fly out into the world with an unmeasurable impact on a client’s brand. The first disruption to this model came with performance advertising. Instead of seeing if sales of soda increased after a barrage of 30 second TV spots, advertisers could see who clicked on ads and which ones followed through to purchases. Advertising dollars could be efficiently spent by directly measuring the impact of advertising campaigns. Increasingly desperate advertising agencies managed to grab a piece of this pie–either by creating and managing pay-per-click campaigns for clients or creating the landing pages that these ads lead to.

Mobile is the new disruption. Although mobile ads operate in much the same way as pay-per-click ads, there is a new generation of advertising that is delivered as a mobile app. Many brands have dedicated apps such as Chipotle and Starbucks, while others have created advertising campaigns built around mobile games and location-based experiences. This is real software.

Most advertising agencies are not software developers. Yet many brands make the mistake of hiring agencies to build mobile apps. I’ve seen this many times, as companies that know how to make web pages and 30 second commercial spots scramble to understand software development on behalf of a client. This is an expensive and failure-prone strategy. The software development process is completely different from Photoshopping banner ads or shooting TV commercials. There is no way for a traditional advertising agency to transform themselves into a software company. Large ships are slow to turn.

The reality is mobile advertising is more dependent on software developers and data scientists than video editors and account managers. Some brands are catching on and eliminating the middleman. In fact, others have started incubators and are smartly creating startups around this new era of software-based advertising.

This is a much smarter use of advertising dollars. Advertising campaign budgets can easily rival a series-A for a hungry startup. A startup filed with smart engineers and designers that are far more capable of promoting your brand in a measurable way than a traditional agency. Agencies might consider the same approach. Instead of trying to do it all in-house either hire an actual software developer to build and manage the project externally or spin up a disruptive advertising software startup.

The Winner-Take-All Game Economy

Last week Sony announced the PS4–the first real salvo in the belated next generation console wars. It all seems so familiar; a new box, mind-blowing new graphics, and an array of launch titles we’ve kind of seen before (Killzone, again?). Also, much like every console transition from the NES to the PlayStation 3, we’ve seen the wholesale destruction of development studios not able to make the transition.

This is evidenced by thousands of layoffs in the traditional game sector, including the implosion of at least one long-running publisher. The standard reasons of not being able to compete with increasing production values as well as the inescapable trap of publisher work-for-hire certainly are partially responsible. Not to mention the mobile disruption that has been detailed on this blog for a few years. However, is something else at play here?

There are two precious resources in the ecosystem of games: money and attention. In previous generations games cost a fixed amount of both–You give me $60 and I give you 10 hours of fun in a box. If a gamer had $500 a year to spend on games, 8-10 games would get that person’s cash–spreading the wealth. In this era, there was a healthy market for mid-range titles in addition to blockbuster hits.

Now, many games are “free” and monetize users by charging for consumable in-game items. Games built on this model are designed to string the player along forever, allowing him to spend a theoretically endless amount of money and time in a single title. One game can consume all of the player’s cash and attention at the expense of most others on the market. The winner takes all.

The finite resources of gamers’ time and money are under increasing pressure from a deluge of free content. How do developers survive in this economy? One way is to build shorter, more intense experiences. Games such as FTL deliver hours of fun in 15 minute chunks. This is bite-sized entertainment gamers can snack on while primarily strung out on an infinite f2p hamster wheel. For many developers it may be futile to compete head on with vastly over-funded startups producing endless time sinks for an increasingly fickle audience. Instead, fit in between the cracks and lure players into your wider ecosystem once you get them hooked.

Displaying Maps in Unity3D

There have been a few recent examples of real-world maps displayed in Unity3D apps. The first one I noticed was the playfield in the infamous Halo 4 iPhone app that came out late last year. For unknown reasons, I was really into this game for a few months. I hung around my local 7-11 scanning bags of Doritos so much that I thought I was going to get arrested for shoplifting. Eventually this obsession led to me wanting to duplicate the map display used in the game. Here’s how I did it.

Google Maps Plug-In

Naturally the first place I looked was the Asset Store. It turns out there is a free Google Maps plug-in available. The only catch is that it requires UniWeb to work. UniWeb lets you call REST APIs and generally have more control over HTTP requests than Unity’s own WWW class allows. It can be a necessity if you’re using REST API calls but it restricts your code stripping options. This will bump up your binary size.

This asset’s sample scene works flawlessly. It downloads a map from the Google Static Map API and textures it on a cube. The code is clean and well documented, featuring the ability to request paths and markers to be added to the static map. Most attributes can be tweaked through the inspector–such as map resolution, location, etc.

I made a lot of changes to this package. I really wish it was open source. Free code assets really should be in most cases. I will try to isolate my changes into another C# file and post a Gist.

The first change I made was to add support for themed Static Maps. If you look at this wizard, you can see that there are a lot of styling options. This appears to be the same technique used in the Halo 4 app because with the right set of options you can get something that looks really close. Supporting styling in Unity3D is just a simple act of appending the style parameters to the end of the URL used by the Google Maps plug-in.

Displaying Markers in 3D

The next thing I wanted to do is display the markers as 3D objects on top of the map instead of having them inside the texture itself. This requires 3 steps:

  1. Determine where the markers are in pixel coordinates in the static map texture.
  2. Calculate the UV coordinate of the pixel coordinate.
  3. Calculate the world coordinate of the texel the UV coordinate resides at.

Step 1 can be tricky. You have to project the latitude and longitude of the marker with the Mercator projection Google Maps uses to get the pixel coordinate. Luckily, this guy already did it in PHP to create image maps from static maps. I adapted this code to C# and it works perfectly. You can grab the Google Maps utility functions here. (All this great free code on the net is making me lazy–but I digress)

Step 2 is easy. This code snippet does the trick. The only catch is that you have to flip the V so that it matches with how Unity uses UV coordinates.

Step 3 is also tricky. However, someone with much better math skills than I wrote a JavaScript method to compute the world coordinate from a UV coordinate. It searches through each triangle in the mesh and sees if the UV coordinate is contained inside it. If so, it then calculates the resultant world coordinate. The key to using this is to put the static map on a plane (the default scene in the plug-in uses a cube) and use the C# version of this function I wrote here.

3D objects floating over marker locations on a Google Static Map.

3D objects floating over marker locations on a Google Static Map.

Here’s the end result–in this case it’s a display for the Donut Dazzler prototype. 3D donuts are floating over real-world donut shops and cupcakes over cupcake bakeries. I got the locations from the Foursquare API. This is quite easy to do using UniWeb.

Slippy Maps

The aforementioned technique works great if you just want a static map to display stuff around the user’s current location. What if you want to be able to scroll around and see more map tiles, just like Google Maps when you move around with your mouse? This is called a Slippy Map. Slippy Maps are much more elaborate–they require dynamically downloading map tiles and stitching them together as the user moves around the world.

Thankfully Jonathan Derrough wrote an amazing free Slippy Map implementation for Unity3D. It really is fantastic. It displays markers in 3D and pulls map tiles from multiple sources–including OpenStreetMap and Bing/VirtualEarth. It doesn’t use Google Maps because of possible TOS violations.

I couldn’t find a way to style map tiles like Google Static Maps can. So the end result was impressive but kind of ugly. It is possible with OpenStreetMap to run your own tile server and run a custom renderer to draw styled tiles. I suspect that’s how Rescue Rush styles their OpenStreetMap tiles–unless they are doing some image processing on the client.

Either Or

For my prototype I ended up using Google Static Maps because Slippy Maps were overkill. Also, pulling tiles down from the servers seemed much slower than grabbing a single static map. I suppose I could add some tile caching, but in the end static maps worked fine for my purposes.

Keep in mind that Google Maps has some pretty fierce API usage costs. If your app goes viral, you will likely be on the hook for a huge bill. Which is why it might be worth figuring out how to style free OpenStreetMap tiles.

Post Navigation

Follow

Get every new post delivered to your Inbox.

Join 1,596 other followers

%d bloggers like this: