Ships and Scurvy RPG GameDev Diary 1: How To Build An Ocean

Ships and Scurvy RPG GameDev Diary 1: How To Build An Ocean

Happy new year, game development friends!

For those who read my 2014 recap, last year was a great time for experimenting with different game genres and technologies. With a good chunk of 2015 sorted out for me with respects to client work, I’ve got the liberty to actually sit down and begin work on a larger game using a technology I want to work with. I’d like to document the dev process as much as I can, much the same as I did with Everyone Gets Treasure (currently on hold for now).

So, without further ado, in 2015 I’m going to be building a 2D RPG about pirates, sea monsters, explorers and islands – and I’ll be using Adobe AIR and Daniel Sperling’s awesome Starling Framework, for mine the easiest and best cross platform 2D game building tool I’ve ever used. The idea is to release the game both on PC ( via Steam etc ), on iOS and Android. Hence Adobe AIR. Build it once and deploy it to multiple platforms. I considered Unity but I still feel like personally Unity underwhelms for 2D development. I don’t like the animation or particle systems much and the UI stuff (even in 4.6) isn’t quite as good as one I could build myself. Anyway, AIR it is – 60 fps across multiple platforms. Don’t buy too much into the anti-Flash hype out there; Adobe AIR is its natural successor and Adobe’s engineering team have built an awesome tool in AIR and just quietly it does absolutely everything you can ask for in 2D game or app development.

 Ships and Scurvy is the working title for the game – I like the alliteration, I like the images it conjures up of rough sea voyages, dubious sailors and their many ailments. It kinda draws some inspiration from the classic old game “The Oregon Trail” where many journeys ended with “You have died of dysentery”.

The basic premise for the game is this: You control a ship and her crew, sailing the ocean in search of islands and interesting locations. On each island you can have adventures, find treasures, interact with natives and so on. As you sail between these islands, you must avoid the dangers of the oceans (sea monsters, storms, whirlpools, freak waves etc) and keep your crew healthy and in good spirits (sometimes literally, a good dose of rum does wonders).

Before I started on the game, I sat down with some pen and paper and sketched up a few game mockups so I could better visualise what I wanted the game to look like – where the UI might sit, what might appear when you reach and island. You can go into lots of detail here but usually I don’t do that until I’m a bit further into actual development. I’ve spent way too long on design docs for games that never got off the ground, so for now sketches are a happy compromise.

shipsAndScurvy1

The screen above shows the main game view, a battle screen and the closeup on an island – you’ll spend a lot of your time in these three screens. The screen below shows what happens when you’re in the main town hub – shops, hiring your crew, repairing and upgrading your boat and so on. Not all of these features will make it into the final version of the game, I’m sure.

shipsAndScurvy3

I’ve actually spent the last week or so getting started on the game. For me, the development process is done in my head and via code in equal measures. Sometimes I’ll start with a proper design document, at other times I’ll have a pretty good idea in my head already and I’ll start with a little tech demo first to see if things are feasible before I flesh out the details of the game.

In this case, the first thing I did after firing up my code editor (FlashDevelop) was load up my game template engine – I’ve built this up over the last year and it includes a bunch of core functionality for menu screens, loading and saving, particle systems etc , as well as a whole bunch of useful code snippets for finding the shortest distance between points, searching arrays, shaking the screen and so on. No need to re-invent the wheel here.

So, knowing a good chunk of the game was to be spent on the open waters, I realised the first thing I needed to work out was how big an ocean I could make whilst still retaining decent performance on tablets and phones. First thing I considered was using I considered a massive tilemap. Tilemaps are the most common way of storing large worlds and have the advantage of allowing you to visually create your world, you can map your coastlines with shoreline tiles, have other tiles for reefs and so on. However, I wanted a really big ocean, and it seemed to me that most tiles would contain no data ( as they are just empty ocean tiles ) , so the idea of a 100,000 x 100,000 tile array just didn’t seem that feasible to me.

What I decided to do was to break the ocean down into a grid of 100 squares (width and height) and have each square represent about a thousand pixels, or one screen width. This way I could determine approximately where the player was in the world and place unique items inside only the tiles that required them. 100 x 100 is a lot less memory usage than the alternative.

Once I had my ocean grid, I decided to populate it with a bunch of random floating images ( for water sparkles, debris etc ) that I didn’t really need to keep track of but would visually scroll when the player moved. The best way to do this in starling is using what’s called a QuadTreeSprite. It’s basically a huge QuadBatch image that can store thousands of items in it without affecting performance. As long as the images are flattened and don’t really interact with the player, you can safely have a great number of them in your world and not suffer any performance lag. The QuadTreeSprite turns on images they come within the game’s viewport and then turns them off again when they’re not needed.

Here’s a quick example of the QuadTreeSprite I set up for the game.

[code language=”actionscript3″]

//quadtreesprite ocean

var maxX:int = 100000;
var maxY:int = 100000;
var maxWaterItems:int  = 100;
var centerX:int = maxX * 0.5;
var centerY:int = maxY * 0.5;

var worldBounds:Rectangle= new Rectangle(0,0,maxX,maxY);
var oceanQTS:QuadTreeSprite = new QuadtreeSprite(worldBounds,true);
oceanQTS.visibleViewport = new Rectangle(0, 0,GlobalVars.fullScreenWidth,GlobalVars.fullScreenHeight);
this.addChild(oceanQTS)

var waterItemMC:flash.display.MovieClip = new WaterItemMC();
var maxWaterFrames=waterItemMC.totalFrames;

for (var i:int = 0; i < maxWaterItems; ++i){

var waterFrame:int=snippets.randomBetween(1, maxWaterFrames)
// add your texture here
var waterItem:Image = GameAssets.convertToImage(waterItemMC, waterFrame)

waterItem.x = snippets.randomBetween(1, maxX)
waterItem.y = snippets.randomBetween(1, maxY)
oceanQTS.addChild(waterItem)

}

[/code]

What the code above essentially does is create a massive empty QuadTreeSprite, then a movieClip with a bunch of frames in it – each frame contains an image such as a wave, some seaweed or whatever, and then pastes the image into the QuadTreeSprite. The end result is pretty cool, you can scroll across this quadtreesprite for quite some time, see all the waves, flotsam and jetsam etc,  and it runs very well even on mobile.

Now, scrolling this over a basic blue rectangle quad is great for an ocean background, but none of it is interactive. We’re going to need a lot more to make it an actual functioning world map. I’m thinking of adding a ScrollImage to give the water a bit of a scrolling texture, it might double up a bit with the QuadTreeSprite, but I’ll come back to this.

The ocean is empty at the moment. I created a class to store all the islands, ships, seamonsters, etc . Each of these is what I call a ‘seaItem‘ , and it will have a bunch of basic functions and properties that I can extend later. For example, each seaItem is a Sprite with an update() function that checks its position on the map, checks how close it is to the player and what to do if it collides with the player. These then get pushed into an array relative to whatever type of seaItem they are ( island, ship etc )

Each seaItem has an Object that I pull from the seaItems class, for example to create an island and add it to the islands array:

[code language=”actionscript3″]

 

//iNum is the island we’re after

var itemObject:Object = new Object()
itemObject.itemGroup = “island”
itemObject.spriteLayer=LAYER_SURFACE
itemObject.isSprite = true;
// ** islands
itemObject.islandName = “Terra Nullis”
itemObject.gridX = 54
itemObject.gridY = 32

itemObject.itemFrame = iNum;
itemObject.iNum=iNum
itemObject.xpos =itemObject.gridX*gridSize
itemObject.ypos =itemObject.gridY * gridSize

islands[iNum] =itemObject

[/code]

And then back in the Ocean class, I loop through the islands array and actually add the seaItem to the ocaen. In this case, Island extends seaItem and overrides the hitTest to make the ship stop when it collides. This kind of basic object inheritance and extension is great to create a variety of different properties and behaviours for the things in your game without having to write each one from scratch.

[code language=”actionscript3″]

public function createIslands() {
islandsArray = []
for (var i:int = 0; i < GlobalVars.oceanMap.islands.length; i++) {
island=new Island(GlobalVars.oceanMap.islands[i])
islandsArray[i] = island;
}
}

[/code]

Here’s a screenshot of the game with an island , some little waves from the QuadTreeSprite and also a boat ( I’ve already added the boat’s functionality but will talk about it next post ).

tinyBoat

 

Anyway, that’s just about it for development diary one. I hope it was a bit helpful for anyone thinking of starting their own similar game – keep reading as I develop the game and I’ll go into much more detail about the entire development process each week.

Cheers, happy journeys

Oliver Joyce
Whiskeybarrel Studios

 

By | 2015-05-08T04:46:56+00:00 January 4th, 2015|Ships and Scurvy: GameDev Diary|

About the Author: