├── .bowerrc
├── .editorconfig
├── .gitignore
├── .jshintrc
├── .tern-project
├── Gruntfile.js
├── README.md
├── assets
├── buildingTiles_sheet.png
├── buildingTiles_sheet.xml
├── cityTiles_sheet.png
├── cityTiles_sheet.xml
├── landscapeTiles_sheet.png
├── landscapeTiles_sheet.xml
└── preloader.gif
├── bower.json
├── config.json
├── css
├── rStats.css
└── styles.css
├── game
├── main.js
├── plugins
│ ├── Generate.js
│ ├── Roads.js
│ ├── WorldManager.js
│ ├── phaser-plugin-isometric.js
│ └── rStats.js
├── states
│ ├── boot.js
│ ├── gameover.js
│ ├── menu.js
│ ├── play.js
│ └── preload.js
└── tiles.json
├── index.html
├── package.json
└── templates
└── _main.js.tpl
/.bowerrc:
--------------------------------------------------------------------------------
1 | {
2 | "directory": "bower_components"
3 | }
--------------------------------------------------------------------------------
/.editorconfig:
--------------------------------------------------------------------------------
1 | # http://editorconfig.org
2 | root = true
3 |
4 | [*]
5 | indent_style = space
6 | indent_size = 2
7 | end_of_line = lf
8 | charset = utf-8
9 | trim_trailing_whitespace = true
10 | insert_final_newline = true
11 |
12 | [*.md]
13 | trim_trailing_whitespace = false
14 |
--------------------------------------------------------------------------------
/.gitignore:
--------------------------------------------------------------------------------
1 | node_modules
2 | *.log
3 | bower_components
4 | dist
5 | .grunt
6 |
--------------------------------------------------------------------------------
/.jshintrc:
--------------------------------------------------------------------------------
1 | {
2 | "node": true,
3 | "esnext": true,
4 | "bitwise": true,
5 | "camelcase": true,
6 | "curly": true,
7 | "eqeqeq": true,
8 | "immed": true,
9 | "indent": 2,
10 | "latedef": true,
11 | "newcap": true,
12 | "noarg": true,
13 | "quotmark": "single",
14 | "regexp": true,
15 | "undef": true,
16 | "unused": true,
17 | "strict": true,
18 | "trailing": true,
19 | "smarttabs": true,
20 | "white": true
21 | }
22 |
--------------------------------------------------------------------------------
/.tern-project:
--------------------------------------------------------------------------------
1 | {
2 | "libs": [
3 | "ecma5",
4 | "ecma6",
5 | "jquery"
6 | ],
7 | "loadEagerly": [
8 | "/game/**/*.js"
9 | ],
10 | "dontLoad": [
11 | "/dist/*.js"
12 | ],
13 | "plugins": {
14 | "complete_strings": {},
15 | "doc_comment": {
16 | "fullDocs": true
17 | }
18 | }
19 | }
20 |
--------------------------------------------------------------------------------
/Gruntfile.js:
--------------------------------------------------------------------------------
1 | // Generated on 2014-03-28 using generator-phaser-official 0.0.8-rc-2
2 | 'use strict';
3 | var config = require('./config.json');
4 | var _ = require('underscore');
5 | _.str = require('underscore.string');
6 |
7 | // Mix in non-conflict functions to Underscore namespace if you want
8 | _.mixin(_.str.exports());
9 |
10 | var LIVERELOAD_PORT = 35729;
11 | var lrSnippet = require('connect-livereload')({port: LIVERELOAD_PORT});
12 | var mountFolder = function (connect, dir) {
13 | return connect.static(require('path').resolve(dir));
14 | };
15 |
16 | module.exports = function (grunt) {
17 | // load all grunt tasks
18 | require('matchdep').filterDev('grunt-*').forEach(grunt.loadNpmTasks);
19 |
20 | grunt.initConfig({
21 | watch: {
22 | scripts: {
23 | files: [
24 | 'game/**/*.js',
25 | '!game/main.js'
26 | ],
27 | options: {
28 | spawn: false,
29 | livereload: LIVERELOAD_PORT
30 | },
31 | tasks: ['build']
32 | }
33 | },
34 | connect: {
35 | options: {
36 | port: 9000,
37 | // change this to '0.0.0.0' to access the server from outside
38 | hostname: 'localhost'
39 | },
40 | livereload: {
41 | options: {
42 | middleware: function (connect) {
43 | return [
44 | lrSnippet,
45 | mountFolder(connect, 'dist')
46 | ];
47 | }
48 | }
49 | }
50 | },
51 | copy: {
52 | dist: {
53 | files: [
54 | // includes files within path and its sub-directories
55 | { expand: true, src: ['assets/**'], dest: 'dist/' },
56 | { expand: true, flatten: true, src: ['game/plugins/*.js'], dest: 'dist/js/plugins/' },
57 | { expand: true, flatten: true, src: ['bower_components/**/build/*.js'], dest: 'dist/js/' },
58 | { expand: true, src: ['css/**'], dest: 'dist/' },
59 | { expand: true, src: ['index.html'], dest: 'dist/' }
60 | ]
61 | }
62 | },
63 | browserify: {
64 | build: {
65 | src: ['game/main.js'],
66 | dest: 'dist/js/game.js'
67 | }
68 | },
69 | 'gh-pages': {
70 | options: {
71 | base: 'dist'
72 | },
73 | src: ['**']
74 | }
75 | });
76 |
77 | grunt.registerTask('build', ['buildBootstrapper', 'browserify','copy']);
78 | grunt.registerTask('serve', ['build', 'connect:livereload', 'watch']);
79 | grunt.registerTask('default', ['serve']);
80 | grunt.registerTask('dev', ['buildBootstrapper', 'browserify','copy', 'build', 'gh-pages'])
81 | grunt.registerTask('prod', ['build', 'copy']);
82 |
83 | grunt.registerTask('buildBootstrapper', 'builds the bootstrapper file correctly', function() {
84 | var stateFiles = grunt.file.expand('game/states/*.js');
85 | var gameStates = [];
86 | var statePattern = new RegExp(/(\w+).js$/);
87 | stateFiles.forEach(function(file) {
88 | var state = file.match(statePattern)[1];
89 | if (!!state) {
90 | gameStates.push({shortName: state, stateName: _.capitalize(state) + 'State'});
91 | }
92 | });
93 | config.gameStates = gameStates;
94 | console.log(config);
95 | var bootstrapper = grunt.file.read('templates/_main.js.tpl');
96 | bootstrapper = grunt.template.process(bootstrapper,{data: config});
97 | grunt.file.write('game/main.js', bootstrapper);
98 | });
99 | };
100 |
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 | 
2 |
3 | # IsoCitySim
4 | A simulation of a city using isometric tiles
5 |
6 | ## Demo
7 | Be sure to check out the demo [here](http://snollygolly.github.io/IsoCitySim/). The demo shows off city/road/terrain generation, and it random each time. You can use the arrow keys to navigate around.
8 |
9 | ## How to use IsoCitySim for fun and for profit
10 |
11 | 1. Clone down the repository and navigate to it
12 |
13 | 2. `npm install`
14 |
15 | 3. `bower install`
16 |
17 | 4. `grunt`
18 |
19 | 5. Use MAMP or something similar to host the `dist` folder
20 |
21 | 6. That's it!
22 |
--------------------------------------------------------------------------------
/assets/buildingTiles_sheet.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/snollygolly/IsoCitySim/d230c8b44c63eff513e027ef023a05aa4526d4cb/assets/buildingTiles_sheet.png
--------------------------------------------------------------------------------
/assets/buildingTiles_sheet.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
14 |
15 |
16 |
17 |
18 |
19 |
20 |
21 |
22 |
23 |
24 |
25 |
26 |
27 |
28 |
29 |
30 |
31 |
32 |
33 |
34 |
35 |
36 |
37 |
38 |
39 |
40 |
41 |
42 |
43 |
44 |
45 |
46 |
47 |
48 |
49 |
50 |
51 |
52 |
53 |
54 |
55 |
56 |
57 |
58 |
59 |
60 |
61 |
62 |
63 |
64 |
65 |
66 |
67 |
68 |
69 |
70 |
71 |
72 |
73 |
74 |
75 |
76 |
77 |
78 |
79 |
80 |
81 |
82 |
83 |
84 |
85 |
86 |
87 |
88 |
89 |
90 |
91 |
92 |
93 |
94 |
95 |
96 |
97 |
98 |
99 |
100 |
101 |
102 |
103 |
104 |
105 |
106 |
107 |
108 |
109 |
110 |
111 |
112 |
113 |
114 |
115 |
116 |
117 |
118 |
119 |
120 |
121 |
122 |
123 |
124 |
125 |
126 |
127 |
128 |
129 |
130 |
131 |
132 |
133 |
134 |
135 |
--------------------------------------------------------------------------------
/assets/cityTiles_sheet.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/snollygolly/IsoCitySim/d230c8b44c63eff513e027ef023a05aa4526d4cb/assets/cityTiles_sheet.png
--------------------------------------------------------------------------------
/assets/cityTiles_sheet.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
14 |
15 |
16 |
17 |
18 |
19 |
20 |
21 |
22 |
23 |
24 |
25 |
26 |
27 |
28 |
29 |
30 |
31 |
32 |
33 |
34 |
35 |
36 |
37 |
38 |
39 |
40 |
41 |
42 |
43 |
44 |
45 |
46 |
47 |
48 |
49 |
50 |
51 |
52 |
53 |
54 |
55 |
56 |
57 |
58 |
59 |
60 |
61 |
62 |
63 |
64 |
65 |
66 |
67 |
68 |
69 |
70 |
71 |
72 |
73 |
74 |
75 |
76 |
77 |
78 |
79 |
80 |
81 |
82 |
83 |
84 |
85 |
86 |
87 |
88 |
89 |
90 |
91 |
92 |
93 |
94 |
95 |
96 |
97 |
98 |
99 |
100 |
101 |
102 |
103 |
104 |
105 |
106 |
107 |
108 |
109 |
110 |
111 |
112 |
113 |
114 |
115 |
116 |
117 |
118 |
119 |
120 |
121 |
122 |
123 |
124 |
125 |
126 |
127 |
128 |
129 |
130 |
131 |
132 |
133 |
--------------------------------------------------------------------------------
/assets/landscapeTiles_sheet.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/snollygolly/IsoCitySim/d230c8b44c63eff513e027ef023a05aa4526d4cb/assets/landscapeTiles_sheet.png
--------------------------------------------------------------------------------
/assets/landscapeTiles_sheet.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
14 |
15 |
16 |
17 |
18 |
19 |
20 |
21 |
22 |
23 |
24 |
25 |
26 |
27 |
28 |
29 |
30 |
31 |
32 |
33 |
34 |
35 |
36 |
37 |
38 |
39 |
40 |
41 |
42 |
43 |
44 |
45 |
46 |
47 |
48 |
49 |
50 |
51 |
52 |
53 |
54 |
55 |
56 |
57 |
58 |
59 |
60 |
61 |
62 |
63 |
64 |
65 |
66 |
67 |
68 |
69 |
70 |
71 |
72 |
73 |
74 |
75 |
76 |
77 |
78 |
79 |
80 |
81 |
82 |
83 |
84 |
85 |
86 |
87 |
88 |
89 |
90 |
91 |
92 |
93 |
94 |
95 |
96 |
97 |
98 |
99 |
100 |
101 |
102 |
103 |
104 |
105 |
106 |
107 |
108 |
109 |
110 |
111 |
112 |
113 |
114 |
115 |
116 |
117 |
118 |
119 |
120 |
121 |
122 |
123 |
124 |
125 |
126 |
127 |
128 |
129 |
130 |
131 |
132 |
--------------------------------------------------------------------------------
/assets/preloader.gif:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/snollygolly/IsoCitySim/d230c8b44c63eff513e027ef023a05aa4526d4cb/assets/preloader.gif
--------------------------------------------------------------------------------
/bower.json:
--------------------------------------------------------------------------------
1 | {
2 | "name": "isocitysim",
3 | "version": "0.0.0",
4 | "dependencies": {
5 | "phaser-official": "2.3.0"
6 | }
7 | }
8 |
--------------------------------------------------------------------------------
/config.json:
--------------------------------------------------------------------------------
1 | {
2 | "projectName": "IsoCitySim",
3 | "gameWidth": "1024",
4 | "gameHeight": "768"
5 | }
6 |
--------------------------------------------------------------------------------
/css/rStats.css:
--------------------------------------------------------------------------------
1 | .rs-base{
2 | position: absolute;
3 | z-index: 10000;
4 | padding: 10px;
5 | background-color: #222;
6 | font-size: 10px;
7 | line-height: 1.2em;
8 | width: 350px;
9 | font-family: 'Roboto Condensed', tahoma, sans-serif;
10 | left: 0;
11 | top: 0;
12 | overflow: hidden;
13 | }
14 |
15 | .rs-base h1{
16 | margin: 0;
17 | padding: 0;
18 | font-size: 1.4em;
19 | color: #fff;
20 | margin-bottom: 5px;
21 | cursor: pointer;
22 | }
23 |
24 | .rs-base div.rs-group{
25 | margin-bottom: 10px;
26 | }
27 |
28 | .rs-base div.rs-group.hidden{
29 | display: none;
30 | }
31 |
32 | .rs-base div.rs-fraction{
33 | position: relative;
34 | margin-bottom: 5px;
35 | }
36 |
37 | .rs-base div.rs-fraction p{
38 | width: 120px;
39 | text-align: right;
40 | margin: 0;
41 | padding: 0;
42 | }
43 |
44 | .rs-base div.rs-legend{
45 | position: absolute;
46 | line-height: 1em;
47 | }
48 |
49 | .rs-base div.rs-counter-base{
50 | position: relative;
51 | margin: 2px 0;
52 | height: 1em;
53 | }
54 |
55 | .rs-base span.rs-counter-id{
56 | position: absolute;
57 | left: 0;
58 | top: 0;
59 | }
60 |
61 | .rs-base div.rs-counter-value{
62 | position: absolute;
63 | left: 90px;
64 | width: 30px;
65 | height: 1em;
66 | top: 0;
67 | text-align: right;
68 | }
69 |
70 | .rs-base canvas.rs-canvas{
71 | position: absolute;
72 | right: 0;
73 | }
74 |
--------------------------------------------------------------------------------
/css/styles.css:
--------------------------------------------------------------------------------
1 | body {
2 | background-color: #333;
3 | }
4 |
5 | #isocitysim {
6 | border: 2px solid white;
7 | width: 1024px;
8 | margin-left: auto;
9 | margin-right: auto;
10 | cursor: pointer;
11 | }
--------------------------------------------------------------------------------
/game/main.js:
--------------------------------------------------------------------------------
1 | 'use strict';
2 |
3 | //global variables
4 | window.onload = function () {
5 | var game = new Phaser.Game(1024, 768, Phaser.AUTO, 'isocitysim', null, false, false);
6 | var Roads = require('./plugins/Roads');
7 | var Generate = require('./plugins/Generate');
8 | var WorldManager = require('./plugins/WorldManager');
9 | game.tiles = require('./tiles.json');
10 | game.roads = new Roads(game);
11 | game.generate = new Generate(game);
12 | game.worldManager = new WorldManager(game);
13 |
14 | // Game States
15 | game.state.add('boot', require('./states/boot'));
16 | game.state.add('gameover', require('./states/gameover'));
17 | game.state.add('menu', require('./states/menu'));
18 | game.state.add('play', require('./states/play'));
19 | game.state.add('preload', require('./states/preload'));
20 |
21 |
22 | game.state.start('preload');
23 | };
24 |
--------------------------------------------------------------------------------
/game/plugins/Generate.js:
--------------------------------------------------------------------------------
1 |
2 | 'use strict';
3 |
4 | var game;
5 |
6 | function Generate(gameObj) {
7 | console.log("* Generate Init");
8 | game = gameObj;
9 | }
10 |
11 | Generate.prototype = {
12 | //chunks start here
13 | generateChunk: function(map, tiles){
14 | //this generates a chunk (20x20 block) according to rules we've defined
15 | //this is where it happens.
16 | var HIGHWAY_WIDTH = game.tiles.highways.straight["n"].length + game.tiles.highways.edges["n"].length;
17 | //how much land undeveloped between highway and block
18 | var HIGHWAY_EASEMENT = 2;
19 | var HIGHWAY_SINGLE_WIDTH = (HIGHWAY_WIDTH + HIGHWAY_EASEMENT) / 2;
20 | //only half of the highway width is used on each side, that equals a full one
21 | var CITY_CHUNK_SPACE = map.units - (HIGHWAY_WIDTH + HIGHWAY_EASEMENT);
22 | var CITY_START = (map.units * HIGHWAY_SINGLE_WIDTH) + HIGHWAY_SINGLE_WIDTH;
23 | //road consts
24 | var ROAD_START_OFFSET = 4;
25 | var MIN_ROAD_SPLIT = 3;
26 | var MAX_ROAD_SPLIT = 4;
27 | //building consts
28 | //density, 1 out of X building tiles will be a Y
29 | var PARK_DENSITY = 12;
30 | var WALL_DENSITY = 12;
31 | //this will get it's own section i think
32 | var heart = {
33 | z_min: 2,
34 | z_max: 6,
35 | radius: 2
36 | };
37 | //calculate some values
38 | heart.x = this.getRandomNumber((HIGHWAY_SINGLE_WIDTH + heart.radius), (map.units - HIGHWAY_SINGLE_WIDTH) - heart.radius);
39 | heart.y = this.getRandomNumber((HIGHWAY_SINGLE_WIDTH + heart.radius), (map.units - HIGHWAY_SINGLE_WIDTH) - heart.radius);
40 | heart.x_min = heart.x - heart.radius;
41 | heart.x_max = heart.x + heart.radius;
42 | heart.y_min = heart.y - heart.radius;
43 | heart.y_max = heart.y + heart.radius;
44 | //start the looping for layers
45 | var l = 0;
46 | var rect, box;
47 | //this is hardcoded for now, may change, may not, buildings start on 2
48 | while (l < 4){
49 | switch (l){
50 | case 0:
51 | //grass on dirt
52 | rect = this.generateRect(map.units, map.units, 67);
53 | tiles[l] = this.mergePartial2D(map, tiles[l], rect, 0);
54 | break;
55 | case 1:
56 | //this spawns paved areas
57 | //14 because the highway takes up 3 on each edge, this will probably change
58 | rect = this.generateRect(CITY_CHUNK_SPACE, CITY_CHUNK_SPACE, 66);
59 | //starting on 63 because that's the 4,4 after highway edges
60 | tiles[l] = this.mergePartial2DSafe(map, tiles[l], rect, CITY_START);
61 | //drawing highways
62 | tiles[l] = this.generateHighway(map, tiles[l], 0, "s", ["e"], map.units);
63 | tiles[l] = this.generateHighway(map, tiles[l], (map.units - (HIGHWAY_WIDTH / 2)), "s", ["w"], map.units);
64 | tiles[l] = this.generateHighway(map, tiles[l], 0, "e", ["s"], map.units);
65 | tiles[l] = this.generateHighway(map, tiles[l], ((map.units * map.units) - (map.units * (HIGHWAY_WIDTH / 2))), "e", ["n"], map.units);
66 | //fix the highways
67 | tiles[l] = game.roads.fixHighways(map, tiles[l], "nw");
68 | tiles[l] = game.roads.fixHighways(map, tiles[l], "ne");
69 | tiles[l] = game.roads.fixHighways(map, tiles[l], "se");
70 | tiles[l] = game.roads.fixHighways(map, tiles[l], "sw");
71 | //start to spawn the roads
72 | var x = this.getRandomNumber((ROAD_START_OFFSET + 1), (ROAD_START_OFFSET + 2));
73 | while (x < (map.units - ROAD_START_OFFSET)){
74 | var index = this.getIndexFromCoords(map, x, HIGHWAY_EASEMENT)
75 | tiles[l] = this.generateRoad(map, tiles[l], "city_plain", index, "s", map.units - HIGHWAY_EASEMENT);
76 | //cap the highways
77 | tiles[l] = game.roads.joinRoadHighway(map, tiles[l], x, HIGHWAY_EASEMENT, "n");
78 | tiles[l] = game.roads.joinRoadHighway(map, tiles[l], x, map.units - 1, "s");
79 | x += this.getRandomNumber(MIN_ROAD_SPLIT, MAX_ROAD_SPLIT);
80 | }
81 | var y = this.getRandomNumber((ROAD_START_OFFSET + 1), (ROAD_START_OFFSET + 2));
82 | while (y < (map.units - ROAD_START_OFFSET)){
83 | var index = this.getIndexFromCoords(map, HIGHWAY_EASEMENT, y)
84 | tiles[l] = this.generateRoad(map, tiles[l], "city_plain", index, "e", map.units - HIGHWAY_EASEMENT);
85 | //cap the highways
86 | tiles[l] = game.roads.joinRoadHighway(map, tiles[l], HIGHWAY_EASEMENT, y, "w");
87 | tiles[l] = game.roads.joinRoadHighway(map, tiles[l], map.units - 1, y, "e");
88 | y += this.getRandomNumber(MIN_ROAD_SPLIT, MAX_ROAD_SPLIT);
89 | }
90 | //road magic!
91 | tiles[l] = game.roads.fixRoads(map, tiles[l], "city_plain");
92 | break;
93 | case 2:
94 | //start to generate buildings
95 | var ewTiles = game.roads.getIndices(["e", "w"]);
96 | var nsTiles = game.roads.getIndices(["n", "s"]);
97 | var i = 0;
98 | var cType, index;
99 | while (i < tiles[l].length){
100 | //randomly place features
101 | if (tiles[l-1][i] == 66 && this.getRandomNumber(1,PARK_DENSITY) == 1){
102 | //this will be a park
103 | tiles[l-1][i] = game.tiles.parks[this.getRandomNumber(0,game.tiles.parks.length - 1)];
104 | }else{
105 | //we aren't drawing a park
106 | if(this.getRandomNumber(1,WALL_DENSITY) == 1){
107 | //we are drawing a wall
108 | cType = "wall";
109 | }else{
110 | cType = "building"
111 | }
112 | if (tiles[l-1][i] != 66) {
113 | //find eligible directions
114 | var eligibleDirs = [];
115 | if (ewTiles.indexOf(tiles[l-1][i]) != -1 && tiles[l-1][i - map.units] == 66){eligibleDirs.push("s");}
116 | if (nsTiles.indexOf(tiles[l-1][i]) != -1 && tiles[l-1][i + 1] == 66){eligibleDirs.push("w");}
117 | if (ewTiles.indexOf(tiles[l-1][i]) != -1 && tiles[l-1][i + map.units] == 66){eligibleDirs.push("n");}
118 | if (nsTiles.indexOf(tiles[l-1][i]) != -1 && tiles[l-1][i - 1] == 66){eligibleDirs.push("e");}
119 | //check to see what to do (draw the buildings)
120 | if (eligibleDirs.indexOf("s") != -1){
121 | //match the north side of the road
122 | index = i - map.units;
123 | if (tiles[l][index] == 0){
124 | if (cType == "building"){
125 | var coords = this.getCoordsFromIndex(map, index);
126 | box = game.generate.generateBuilding("s", coords, heart);
127 | tiles = game.generate.mergePartial3DSafe(map, tiles, box, l, index);
128 | }else if (cType == "wall"){
129 | tiles[l-1][index] = game.tiles.walls.s[this.getRandomNumber(0, (game.tiles.walls.s.length - 1))];
130 | }
131 | }
132 | }
133 | if (eligibleDirs.indexOf("e") != -1){
134 | //match the west side of the road
135 | index = i - 1;
136 | if (tiles[l][index] == 0){
137 | if (cType == "building"){
138 | var coords = this.getCoordsFromIndex(map, index);
139 | box = game.generate.generateBuilding("e", coords, heart);
140 | tiles = game.generate.mergePartial3DSafe(map, tiles, box, l, index);
141 | }else if (cType == "wall"){
142 | tiles[l-1][index] = game.tiles.walls.e[this.getRandomNumber(0, (game.tiles.walls.e.length - 1))];
143 | }
144 | }
145 | }
146 | if (eligibleDirs.indexOf("w") != -1){
147 | //match the east side of the road
148 | index = i + 1;
149 | if (tiles[l][index] == 0){
150 | if (cType == "building"){
151 | var coords = this.getCoordsFromIndex(map, index);
152 | box = game.generate.generateBuilding("w", coords, heart);
153 | tiles = game.generate.mergePartial3DSafe(map, tiles, box, l, index);
154 | }else if (cType == "wall"){
155 | tiles[l-1][index] = game.tiles.walls.w[this.getRandomNumber(0, (game.tiles.walls.w.length - 1))];
156 | }
157 | }
158 | }
159 | if (eligibleDirs.indexOf("n") != -1){
160 | //match the south side of the road
161 | index = i + map.units;
162 | if (tiles[l][index] == 0){
163 | if (cType == "building"){
164 | var coords = this.getCoordsFromIndex(map, index);
165 | box = game.generate.generateBuilding("n", coords, heart);
166 | tiles = game.generate.mergePartial3DSafe(map, tiles, box, l, index);
167 | }else if (cType == "wall"){
168 | tiles[l-1][index] = game.tiles.walls.n[this.getRandomNumber(0, (game.tiles.walls.n.length - 1))];
169 | }
170 | }
171 | }
172 | }
173 | }
174 | i++;
175 | }
176 | }
177 | l++;
178 | }
179 | return tiles;
180 | },
181 | //highways start here
182 | generateHighway: function(map, tiles, start, direction, half, length){
183 | //generates highways from lines (2d, pass in only one array)
184 | //lines should be expressed: {start: 1, direction: s, length: 5}
185 | var highway = game.tiles.highways.straight[direction];
186 | var edge = game.tiles.highways.edges[direction]
187 | var fullSlice = [edge[b], highway[0], highway[1], edge[b]];
188 | var i = 0;
189 | //for border toggle
190 | var b = 0;
191 | while (i < length){
192 | //flip flop b
193 | //b = ((b == 0) ? 1 : 0);
194 | fullSlice = [edge[b], highway[0], highway[1], edge[b]];
195 | //the the direction matching logic stuff
196 | if (direction == "e" || direction == "w"){
197 | //everything is same except the offset
198 | var index = ((direction == "e") ? (start + i) : (start -1) );
199 | var c = 0;
200 | if (half.indexOf("n") != -1){
201 | tiles[index + (map.units * c++)] = fullSlice[0];
202 | tiles[index + (map.units * c++)] = fullSlice[1];
203 | }
204 | if (half.indexOf("s") != -1){
205 | tiles[index + (map.units * c++)] = fullSlice[2];
206 | tiles[index + (map.units * c++)] = fullSlice[3];
207 | }
208 | }else if (direction == "n" || direction == "s"){
209 | //everything is same except the offset
210 | var index = ((direction == "s") ? (start + (map.units * i)) : (start - (map.units * i)));
211 | var c = 0;
212 | if (half.indexOf("w") != -1){
213 | tiles[index + (c++)] = fullSlice[0];
214 | tiles[index + (c++)] = fullSlice[1];
215 | }
216 | if (half.indexOf("e") != -1){
217 | tiles[index + (c++)] = fullSlice[2];
218 | tiles[index + (c++)] = fullSlice[3];
219 | }
220 | }
221 | i++;
222 | }
223 | return tiles;
224 | },
225 | //roads start here
226 | generateRoad: function(map, tiles, set, start, direction, length){
227 | //generates roads from lines (2d, pass in only one array)
228 | //lines should be expressed: {start: 1, direction: s, length: 5}
229 | if (direction == "n" || direction == "s"){
230 | var road = game.roads.getIndex("ns".split(""), "city_plain");
231 | }else{
232 | var road = game.roads.getIndex("ew".split(""), "city_plain");
233 | }
234 | tiles[start] = road;
235 |
236 | var i = 1;
237 | while (i < length){
238 | switch (direction) {
239 | case "n":
240 | tiles[start - (map.units * i)] = road;
241 | break;
242 | case "e":
243 | tiles[start + i] = road;
244 | break;
245 | case "w":
246 | tiles[start - i] = road;
247 | break;
248 | case "s":
249 | tiles[start + (map.units * i)] = road;
250 | break;
251 | }
252 | i++;
253 | }
254 | return tiles;
255 | },
256 | //buildings starts here
257 | generateBuilding: function(direction, coords, heart){
258 | //test stuff with auto types and height
259 | var type;
260 | var low = heart.z_min;
261 | var high = heart.z_max;
262 | if (coords.x >= heart.x_min && coords.x <= heart.x_max && coords.y >= heart.y_min && coords.y <= heart.y_max){
263 | //this is going to be a commercial building
264 | type = "commercial";
265 | //figure out the distance to the heart (int = intensity)
266 | var int_p = 1 / (heart.radius + 1);
267 | var int_m_x = Math.abs(coords.x - heart.x);
268 | var int_m_y = Math.abs(coords.y - heart.y);
269 | var int_m = (int_m_x + int_m_y) / 2;
270 | var int = 1 - (int_m * int_p);
271 | var z_mod = ((high - low) * int);
272 | high = Math.floor(z_mod + low);
273 | low = (((high - 1) < low) ? low : (high - 1));
274 | }else{
275 | //this is a residential building
276 | type = "residential";
277 | low = 1;
278 | high = 2;
279 | }
280 | //end test
281 | var colors = ["red", "grey", "brown", "beige"];
282 | var color = colors[this.getRandomNumber(0, colors.length -1)];
283 | var building = null;
284 | //while we don't find a suitable color...
285 | while (building === null){
286 | //try to find a suitable color
287 | if (game.tiles.buildings[type][color].bottoms[direction].length != 0){
288 | var building = {
289 | bottom: game.tiles.buildings[type][color].bottoms[direction][this.getRandomNumber(0, game.tiles.buildings[type][color].bottoms[direction].length -1)],
290 | floors: this.getRandomNumber(low, high)
291 | };
292 | }else{
293 | //if we didn't find a suitable color, shuffle the colors
294 | color = colors[this.getRandomNumber(0, colors.length -1)];
295 | }
296 | }
297 | //directional top
298 | if (direction == "n" || direction == "s"){
299 | building.top = game.tiles.buildings[type][color].tops["ns"][this.getRandomNumber(0, game.tiles.buildings[type][color].tops["ns"].length -1)];
300 | }else{
301 | building.top = game.tiles.buildings[type][color].tops["ew"][this.getRandomNumber(0, game.tiles.buildings[type][color].tops["ew"].length -1)];
302 | }
303 | //pick a roof
304 | if (this.getRandomNumber(0,1) == 1 && game.tiles.buildings[type]["all"].roofs["all"].length != 0){
305 | //this is going to be an "all" direction roof
306 | building.roof = game.tiles.buildings[type]["all"].roofs["all"][this.getRandomNumber(0, game.tiles.buildings[type]["all"].roofs["all"].length -1)];
307 | }else{
308 | //directional top
309 | building.roof = game.tiles.buildings[type]["all"].roofs[direction][this.getRandomNumber(0, game.tiles.buildings[type]["all"].roofs[direction].length -1)];
310 | }
311 | return this.makeBuilding(building);
312 | },
313 | makeBuilding: function(building){
314 | var returnArr = this.makeFilled3DArray(building.top, building.floors);
315 | returnArr[0][0] = building.bottom;
316 | returnArr.push([building.roof]);
317 | return returnArr;
318 | },
319 | //terrain starts here
320 | generateMap: function(map, fill){
321 | //generates a blank map based on dimensions
322 | var i = 0;
323 | var tiles = [];
324 | while (i < (map.units * map.units)){
325 | tiles[i] = fill;
326 | i++;
327 | }
328 | return tiles;
329 | },
330 | generateRect: function(width, height, fill){
331 | var r = 0;
332 | var rows = [];
333 | while (r < height){
334 | rows[r] = this.makeFilled2DArray(fill, width);
335 | r++;
336 | }
337 | return rows;
338 | },
339 | generateSliceRect: function(width, height, slice){
340 | //generates a rectangle based on the slice provided (hardcoded atm)
341 | var masterRows = [];
342 | var slices = game.tiles.slices[slice];
343 | //row index
344 | var r = 0;
345 | while (r < slices.length){
346 | masterRows[r] = [];
347 | masterRows[r][0] = slices[r][0];
348 | var i = 1;
349 | while (i < (width - 1)){
350 | masterRows[r][i] = slices[r][1];
351 | i++;
352 | }
353 | masterRows[r][i] = slices[r][2];
354 | r++;
355 | }
356 | //build out the final array
357 | var rectArr = [];
358 | rectArr[0] = masterRows[0];
359 | var r = 1;
360 | while (r < (height - 1)){
361 | rectArr[r] = masterRows[1];
362 | r++;
363 | }
364 | rectArr[r] = masterRows[2];
365 | return rectArr;
366 | },
367 | //misc utility functions start here
368 | makeFilled2DArray: function(fill, length){
369 | //makes a filled array: [0,0,0]
370 | var array = [];
371 | for (var i = 0; i < length; i++) {
372 | array[i] = fill;
373 | }
374 | return array;
375 | },
376 | makeFilled3DArray: function(fill, length){
377 | //makes a filled 3d array: [[0], [0]]
378 | //currently only makes single length arrays
379 | var array = [];
380 | for (var i = 0; i < length; i++) {
381 | array[i] = [fill];
382 | }
383 | return array;
384 | },
385 | mergePartial2D: function(map, tiles, partial, index){
386 | //will overwrite all tiles
387 | //takes a map, and a partial map, and merges the partial into the map
388 | var i = 0;
389 | //partial should consist of an array of arrays, one array per row
390 | while (i < partial.length){
391 | //remove items from the array
392 | tiles.splice(index + (map.units * i), partial[i].length);
393 | //remove items from the array
394 | tiles.splice.apply(tiles, [index + (map.units * i), 0].concat(partial[i]));
395 | i++;
396 | }
397 | return tiles;
398 | },
399 | mergePartial3D: function(map, tiles, partial, layer, index){
400 | //will overwrite all tiles
401 | //takes a map, and a partial map, and merges the partial into the map
402 | //expects 3d arrays for tiles and partial
403 | var l = 0;
404 | while (l < partial.length){
405 | tiles[(l + layer)] = this.mergePartial2D(map, tiles[(l + layer)], partial[l], index);
406 | l++;
407 | }
408 | return tiles;
409 | },
410 | //misc utility functions start here
411 | mergePartial2DSafe: function(map, tiles, partial, index){
412 | //will overwrite all tiles
413 | //takes a map, and a partial map, and merges the partial into the map
414 | var i = 0;
415 | //partial should consist of an array of arrays, one array per row
416 | while (i < partial.length){
417 | var j = 0;
418 | while (j < partial[i].length){
419 | if (partial[i][j] != 0){
420 | //there's some content here we want to merge
421 | tiles[index + (map.units * i) + j] = partial[i][j];
422 | }
423 | j++;
424 | }
425 | i++;
426 | }
427 | return tiles;
428 | },
429 | mergePartial3DSafe: function(map, tiles, partial, layer, index){
430 | //will overwrite all tiles
431 | //takes a map, and a partial map, and merges the partial into the map
432 | //expects 3d arrays for tiles and partial
433 | var l = 0;
434 | while (l < partial.length){
435 | tiles[(l + layer)] = this.mergePartial2DSafe(map, tiles[(l + layer)], [partial[l]], index);
436 | l++;
437 | }
438 | return tiles;
439 | },
440 | getCoordsFromIndex: function(map, index){
441 | //1,1 is top left corner
442 | //give it the index of the tile you want and get the x,y coords
443 | var y = Math.floor(index / map.units);
444 | var x = index - (y * map.units);
445 | return {
446 | x: x + 1,
447 | y: y + 1
448 | };
449 | },
450 | getIndexFromCoords: function(map, x, y){
451 | //1,1 is top left corner
452 | //give it the x / y of the tile you want, and it'll give you its index in the array
453 | var xOffset = x - 1;
454 | var yOffset = (y - 1) * map.units;
455 | return xOffset + yOffset;
456 | },
457 | getRandomNumber: function(min, max){
458 | return Math.floor(Math.random() * (max - min + 1)) + min;
459 | }
460 | };
461 |
462 | module.exports = Generate;
463 |
--------------------------------------------------------------------------------
/game/plugins/Roads.js:
--------------------------------------------------------------------------------
1 |
2 | 'use strict';
3 |
4 | var game;
5 |
6 | function Roads(gameObj) {
7 | console.log("* Roads Init");
8 | game = gameObj;
9 | }
10 |
11 | Roads.prototype = {
12 | fixRoads: function(map, tiles, set){
13 | //give it all your tiles and it makes your roads perfect
14 | //Road Magic!
15 | var problemTiles = [];
16 | var nsProbs = this.findNSProblems(map, tiles);
17 | var ewProbs = this.findEWProblems(map, tiles);
18 | problemTiles = this.arrayUnique(nsProbs.concat(ewProbs));
19 | //tiles = this.displayProblemTiles(tiles, problemTiles);
20 | //return tiles;
21 | tiles = this.fixProblemTiles(map, tiles, set, problemTiles);
22 | return tiles;
23 | },
24 | fixHighways: function(map, tiles, corner){
25 | //give it the tiles, the corner this join happens in, puts some corners on your highway
26 | //i wish this was more magical, like road magic. *sigh*.
27 | switch (corner){
28 | case "nw":
29 | var cornerX = 2;
30 | var cornerY = 2;
31 | //fix the corner roads
32 | tiles[game.generate.getIndexFromCoords(map, cornerX - 1, cornerY - 1)] = game.tiles.highways.open;
33 | tiles[game.generate.getIndexFromCoords(map, cornerX, cornerY - 1)] = game.tiles.highways.straight.w[1];
34 | tiles[game.generate.getIndexFromCoords(map, cornerX - 1, cornerY)] = game.tiles.highways.straight.n[1];
35 | tiles[game.generate.getIndexFromCoords(map, cornerX, cornerY)] = game.tiles.highways.corner;
36 | //fix edge caps
37 | tiles[game.generate.getIndexFromCoords(map, cornerX + 1, cornerY)] = game.tiles.highways.edge_caps.w;
38 | tiles[game.generate.getIndexFromCoords(map, cornerX, cornerY + 1)] = game.tiles.highways.edge_caps.n;
39 | break;
40 | case "ne":
41 | var cornerX = map.units - 1;
42 | var cornerY = 2;
43 | //fix the corner roads
44 | tiles[game.generate.getIndexFromCoords(map, cornerX + 1, cornerY - 1)] = game.tiles.highways.open;
45 | tiles[game.generate.getIndexFromCoords(map, cornerX, cornerY - 1)] = game.tiles.highways.straight.w[1];
46 | tiles[game.generate.getIndexFromCoords(map, cornerX + 1, cornerY)] = game.tiles.highways.straight.s[0];
47 | tiles[game.generate.getIndexFromCoords(map, cornerX, cornerY)] = game.tiles.highways.corner;
48 | //fix edge caps
49 | tiles[game.generate.getIndexFromCoords(map, cornerX - 1, cornerY)] = game.tiles.highways.edge_caps.e;
50 | tiles[game.generate.getIndexFromCoords(map, cornerX, cornerY + 1)] = game.tiles.highways.edge_caps.n;
51 | break;
52 | case "se":
53 | var cornerX = map.units - 1;
54 | var cornerY = map.units - 1;
55 | //fix the corner roads
56 | tiles[game.generate.getIndexFromCoords(map, cornerX + 1, cornerY + 1)] = game.tiles.highways.open;
57 | tiles[game.generate.getIndexFromCoords(map, cornerX, cornerY + 1)] = game.tiles.highways.straight.e[0];
58 | tiles[game.generate.getIndexFromCoords(map, cornerX + 1, cornerY)] = game.tiles.highways.straight.n[0];
59 | tiles[game.generate.getIndexFromCoords(map, cornerX, cornerY)] = game.tiles.highways.corner;
60 | //fix edge caps
61 | tiles[game.generate.getIndexFromCoords(map, cornerX - 1, cornerY)] = game.tiles.highways.edge_caps.e;
62 | tiles[game.generate.getIndexFromCoords(map, cornerX, cornerY - 1)] = game.tiles.highways.edge_caps.s;
63 | break;
64 | case "sw":
65 | var cornerX = 2;
66 | var cornerY = map.units - 1;
67 | //fix the corner roads
68 | tiles[game.generate.getIndexFromCoords(map, cornerX - 1, cornerY + 1)] = game.tiles.highways.open;
69 | tiles[game.generate.getIndexFromCoords(map, cornerX, cornerY + 1)] = game.tiles.highways.straight.w[0];
70 | tiles[game.generate.getIndexFromCoords(map, cornerX - 1, cornerY)] = game.tiles.highways.straight.s[1];
71 | tiles[game.generate.getIndexFromCoords(map, cornerX, cornerY)] = game.tiles.highways.corner;
72 | //fix edge caps
73 | tiles[game.generate.getIndexFromCoords(map, cornerX + 1, cornerY)] = game.tiles.highways.edge_caps.w;
74 | tiles[game.generate.getIndexFromCoords(map, cornerX, cornerY - 1)] = game.tiles.highways.edge_caps.s;
75 | break;
76 | }
77 | return tiles;
78 | },
79 | joinRoadHighway: function(map, tiles, x, y, direction){
80 | //joins together highways and roads
81 | switch (direction){
82 | case "n":
83 | //set join piece
84 | tiles[game.generate.getIndexFromCoords(map, x, y - 1)] = game.tiles.highways.joins.s;
85 | //caps
86 | tiles[game.generate.getIndexFromCoords(map, x - 1, y)] = game.tiles.highways.edge_caps.e;
87 | tiles[game.generate.getIndexFromCoords(map, x + 1, y)] = game.tiles.highways.edge_caps.w;
88 | break;
89 | case "e":
90 | //set join piece
91 | tiles[game.generate.getIndexFromCoords(map, x + 1, y)] = game.tiles.highways.joins.w;
92 | //caps
93 | tiles[game.generate.getIndexFromCoords(map, x, y - 1)] = game.tiles.highways.edge_caps.s;
94 | tiles[game.generate.getIndexFromCoords(map, x, y + 1)] = game.tiles.highways.edge_caps.n;
95 | break;
96 | case "w":
97 | //set join piece
98 | tiles[game.generate.getIndexFromCoords(map, x - 1, y)] = game.tiles.highways.joins.e;
99 | //caps
100 | tiles[game.generate.getIndexFromCoords(map, x, y + 1)] = game.tiles.highways.edge_caps.n;
101 | tiles[game.generate.getIndexFromCoords(map, x, y - 1)] = game.tiles.highways.edge_caps.s;
102 | break;
103 | case "s":
104 | //set join piece
105 | tiles[game.generate.getIndexFromCoords(map, x, y + 1)] = game.tiles.highways.joins.n;
106 | //caps
107 | tiles[game.generate.getIndexFromCoords(map, x - 1, y)] = game.tiles.highways.edge_caps.e;
108 | tiles[game.generate.getIndexFromCoords(map, x + 1, y)] = game.tiles.highways.edge_caps.w;
109 | break;
110 | }
111 | return tiles;
112 | },
113 | displayProblemTiles: function(tiles, problems){
114 | var i = 0;
115 | while (i < problems.length){
116 | tiles[problems[i]] = 43;
117 | i++;
118 | }
119 | return tiles;
120 | },
121 | fixProblemTiles: function(map, tiles, set, problems){
122 | //pass it map, tiles, and an array of problem tiles and it fixes them
123 | var i = 0;
124 | //let's work on our tiles one by one
125 | while (i < problems.length){
126 | //this is our desired object
127 | var needle = {
128 | n: false,
129 | e: false,
130 | w: false,
131 | s: false,
132 | set: set
133 | };
134 | //check to see if there's a road tile to the north
135 | var n = (problems[i] - map.units);
136 | if (tiles[n] != 0){
137 | var nX = this.getDirections(tiles[n]);
138 | if (nX){
139 | if (nX.s == true && nX.set == set){
140 | //this tile to the north needs a south connection (us)
141 | needle.n = true;
142 | }
143 | }
144 | }
145 | //check to see if there's a road tile to the south
146 | var s = (problems[i] + map.units);
147 | if (tiles[s] != 0){
148 | var sX = this.getDirections(tiles[s]);
149 | if (sX){
150 | if (sX.n == true && sX.set == set){
151 | //this tile to the south needs a north connection (us)
152 | needle.s = true;
153 | }
154 | }
155 | }
156 | //check to see if there's a road tile to the east
157 | var e = (problems[i] + 1);
158 | if (tiles[e] != 0){
159 | var eX = this.getDirections(tiles[e]);
160 | if (eX){
161 | if (eX.w == true && eX.set == set){
162 | //this tile to the east needs a west connection (us)
163 | needle.e = true;
164 | }
165 | }
166 | }
167 | //check to see if there's a road tile to the west
168 | var w = (problems[i] - 1);
169 | if (tiles[w] != 0){
170 | var wX = this.getDirections(tiles[w]);
171 | if (wX){
172 | if (wX.e == true && wX.set == set){
173 | //this tile to the west needs an east connection (us)
174 | needle.w = true;
175 | }
176 | }
177 |
178 | }
179 | //we have our needle now, let's find it!
180 | var index = this.getIndexFromObj(needle);
181 | if (index != false){
182 | //we found a match
183 | tiles[problems[i]] = index;
184 | if (needle.n === true){tiles[n] = this.getIndex("ns", "city_intersection");}
185 | if (needle.e === true){tiles[e] = this.getIndex("ew", "city_intersection");}
186 | if (needle.w === true){tiles[w] = this.getIndex("ew", "city_intersection");}
187 | if (needle.s === true){tiles[s] = this.getIndex("ns", "city_intersection");}
188 | }
189 | i++;
190 | }
191 | return tiles;
192 | },
193 | findNSProblems: function(map, tiles){
194 | //finds problems using the n/s tile as the master tile
195 | var masterTiles = this.getIndices(["n", "s"]);
196 | var problemTiles = [];
197 | var i = 0;
198 | while (i < tiles.length){
199 | if (masterTiles.indexOf(tiles[i]) != -1){
200 | var n = i - map.units;
201 | var s = i + map.units;
202 | //there's a match, this is a "master tile, let's check its friends
203 | if (masterTiles.indexOf(tiles[n]) === -1){
204 | //there's i don't recognize what's up there
205 | problemTiles.push(n)
206 | }
207 | if (masterTiles.indexOf(tiles[s]) === -1){
208 | //there's i don't recognize what's down there
209 | problemTiles.push(s)
210 | }
211 | }
212 | i++;
213 | }
214 | return problemTiles;
215 | },
216 | findEWProblems: function(map, tiles){
217 | //finds problems using the e/w tile as the master tile
218 | var masterTiles = this.getIndices(["e", "w"]);
219 | var problemTiles = [];
220 | var i = 0;
221 | while (i < tiles.length){
222 | if (masterTiles.indexOf(tiles[i]) != -1){
223 | var e = i + 1;
224 | var w = i - 1;
225 | //there's a match, this is a "master tile, let's check its friends
226 | if (masterTiles.indexOf(tiles[e]) == -1){
227 | //there's i don't recognize what's up there
228 | problemTiles.push(e)
229 | }
230 | if (masterTiles.indexOf(tiles[w]) == -1){
231 | //there's i don't recognize what's down there
232 | problemTiles.push(w)
233 | }
234 | }
235 | i++;
236 | }
237 | return problemTiles;
238 | },
239 | getIndex: function(directions, set){
240 | //give it an array of directions and it will tell you which piece fits the bill
241 | var i = 0;
242 | var needle = {
243 | n: directions.indexOf("n") != -1 ? true : false,
244 | e: directions.indexOf("e") != -1 ? true : false,
245 | w: directions.indexOf("w") != -1 ? true : false,
246 | s: directions.indexOf("s") != -1 ? true : false,
247 | set: set
248 | }
249 | return this.getIndexFromObj(needle);
250 | },
251 | getIndexFromObj: function(needle){
252 | for (var key in game.tiles.roads) {
253 | if (game.tiles.roads.hasOwnProperty(key)) {
254 | if (this.compareJSON(game.tiles.roads[key], needle)){
255 | return parseInt(key);
256 | }
257 | }
258 | }
259 | console.log("! No match found for getIndexFromObj in Roads");
260 | //console.log(JSON.stringify(needle));
261 | return false;
262 | },
263 | getIndices: function(directions){
264 | //give it an array of directions and it will tell you which pieces fits the bill (no set required)
265 | var needles = [];
266 | var needle = {
267 | n: directions.indexOf("n") != -1 ? true : false,
268 | e: directions.indexOf("e") != -1 ? true : false,
269 | w: directions.indexOf("w") != -1 ? true : false,
270 | s: directions.indexOf("s") != -1 ? true : false
271 | }
272 | for (var key in game.tiles.roads) {
273 | if (game.tiles.roads[key].n == needle.n && game.tiles.roads[key].s == needle.s){
274 | if (game.tiles.roads[key].e == needle.e && game.tiles.roads[key].w == needle.w){
275 | //this piece is the piece we want
276 | needles.push(parseInt(key));
277 | }
278 | }
279 | }
280 | return needles;
281 | },
282 | getDirections: function(index){
283 | //give it an index and it will return a direction object back to you
284 | return game.tiles.roads[index];
285 | },
286 | isRoad: function(index){
287 |
288 | },
289 | compareJSON: function(a, b){
290 | if (JSON.stringify(a) === JSON.stringify(b)){
291 | return true;
292 | }else{
293 | return false;
294 | }
295 | },
296 | arrayUnique: function(array) {
297 | var a = array.concat();
298 | for(var i=0; i _max ) _max = _current;
112 | _ctx.drawImage( _canvas, 1, 0, _canvas.width - 1, _canvas.height, 0, 0, _canvas.width - 1, _canvas.height );
113 | if( alarm ) {
114 | _ctx.drawImage( _alarmCanvas, _canvas.width - 1, _canvas.height - _current * _canvas.height / _max - _elHeight );
115 | } else {
116 | _ctx.drawImage( _dotCanvas, _canvas.width - 1, _canvas.height - _current * _canvas.height / _max - _elHeight );
117 | }
118 | }
119 |
120 | _init();
121 |
122 | return {
123 | draw: _draw
124 | }
125 |
126 | }
127 |
128 | function StackGraph( _dom, _num ) {
129 |
130 | var _canvas = document.createElement( 'canvas' ),
131 | _ctx = _canvas.getContext( '2d' ),
132 | _max = 0,
133 | _current = 0;
134 |
135 | function _init() {
136 |
137 | _canvas.width = _elWidth;
138 | _canvas.height = _elHeight * _num;
139 | _canvas.style.width = _canvas.width + 'px';
140 | _canvas.style.height = _canvas.height + 'px';
141 | _canvas.className = 'rs-canvas';
142 | _dom.appendChild( _canvas );
143 |
144 | _ctx.fillStyle = '#444444';
145 | _ctx.fillRect( 0, 0, _canvas.width, _canvas.height );
146 |
147 | }
148 |
149 | function _draw( v ) {
150 | _ctx.drawImage( _canvas, 1, 0, _canvas.width - 1, _canvas.height, 0, 0, _canvas.width - 1, _canvas.height );
151 | var th = 0;
152 | iterateKeys( v, function( j ) {
153 | var h = v[ j ] * _canvas.height;
154 | _ctx.fillStyle = _colours[ j ];
155 | _ctx.fillRect( _canvas.width - 1, th, 1, h );
156 | th += h;
157 | } );
158 | }
159 |
160 | _init();
161 |
162 | return {
163 | draw: _draw
164 | }
165 |
166 | }
167 |
168 | function PerfCounter( id, group ) {
169 |
170 | var _id = id,
171 | _time,
172 | _value = 0,
173 | _total = 0,
174 | _averageValue = 0,
175 | _accumValue = 0,
176 | _accumStart = Date.now(),
177 | _accumSamples = 0,
178 | _dom = document.createElement( 'div' ),
179 | _spanId = document.createElement( 'span' ),
180 | _spanValue = document.createElement( 'div' ),
181 | _spanValueText = document.createTextNode( '' ),
182 | _def = _settings?_settings.values[ _id.toLowerCase() ]:null,
183 | _graph = new Graph( _dom, _id, _def );
184 |
185 | _dom.className = 'rs-counter-base';
186 |
187 | _spanId.className = 'rs-counter-id'
188 | _spanId.textContent = ( _def && _def.caption )?_def.caption:_id;
189 |
190 | _spanValue.className = 'rs-counter-value';
191 | _spanValue.appendChild( _spanValueText );
192 |
193 | _dom.appendChild( _spanId );
194 | _dom.appendChild( _spanValue );
195 | if( group ) group.div.appendChild( _dom );
196 | else _div.appendChild( _dom );
197 |
198 | _time = performance.now();
199 |
200 | function _average( v ) {
201 | if( _def && _def.average ) {
202 | _accumValue += v;
203 | _accumSamples++;
204 | var t = Date.now();
205 | if( t - _accumStart >= ( _def.avgMs || 1000 ) ) {
206 | _averageValue = _accumValue / _accumSamples;
207 | _accumValue = 0;
208 | _accumStart = t;
209 | _accumSamples = 0;
210 | }
211 | }
212 | }
213 |
214 | function _start(){
215 | _time = performance.now();
216 | }
217 |
218 | function _end() {
219 | _value = performance.now() - _time;
220 | _average( _value );
221 | }
222 |
223 | function _tick() {
224 | _end();
225 | _start();
226 | }
227 |
228 | function _draw() {
229 | var v = ( _def && _def.average )?_averageValue:_value
230 | _spanValueText.nodeValue = Math.round( v * 100 ) / 100;
231 | var a = ( _def && ( ( _def.below && _value < _def.below ) || ( _def.over && _value > _def.over ) ) );
232 | _graph.draw( _value, a );
233 | _dom.style.color = a?'#b70000':'#ffffff';
234 | }
235 |
236 | function _frame() {
237 | var t = performance.now();
238 | var e = t - _time;
239 | _total++;
240 | if( e > 1000 ) {
241 | if( _def.interpolate === false ) {
242 | _value = _total;
243 | } else {
244 | _value = _total * 1000 / e;
245 | }
246 | _total = 0;
247 | _time = t;
248 | _average( _value );
249 | }
250 | }
251 |
252 | function _set( v ) {
253 | _value = v;
254 | _average( _value );
255 | }
256 |
257 | return {
258 | set: _set,
259 | start: _start,
260 | tick: _tick,
261 | end: _end,
262 | frame: _frame,
263 | value: function(){ return _value; },
264 | draw: _draw
265 | }
266 |
267 | }
268 |
269 | function sample() {
270 |
271 | var _value = 0;
272 |
273 | function _set( v ) {
274 | _value = v;
275 | }
276 |
277 | return {
278 | set: _set,
279 | value: function(){ return _value; }
280 | }
281 |
282 | }
283 |
284 | var _base,
285 | _div,
286 | _height = null,
287 | _elHeight = 10,
288 | _elWidth = 200;
289 |
290 | var _perfCounters = {},
291 | _samples = {};
292 |
293 | function _perf( id ) {
294 |
295 | id = id.toLowerCase();
296 | if( id === undefined ) id = 'default';
297 | if( _perfCounters[ id ] ) return _perfCounters[ id ];
298 |
299 | var group = null;
300 | if( _settings && _settings.groups ) {
301 | iterateKeys( _settings.groups, function( j ) {
302 | var g = _settings.groups[ parseInt( j, 10 ) ];
303 | if( !group && g.values.indexOf( id.toLowerCase() ) != -1 ) {
304 | group = g;
305 | }
306 | } );
307 | }
308 |
309 | var p = new PerfCounter( id, group );
310 | _perfCounters[ id ] = p;
311 | return p;
312 |
313 | }
314 |
315 | function _init() {
316 |
317 | if( _settings.plugins ) {
318 | if( !_settings.values ) _settings.values = {};
319 | if( !_settings.groups ) _settings.groups = [];
320 | if( !_settings.fractions ) _settings.fractions = [];
321 | for( var j = 0; j < _settings.plugins.length; j++ ) {
322 | _settings.plugins[ j ].attach( _perf );
323 | iterateKeys( _settings.plugins[ j ].values, function( k ) {
324 | _settings.values[ k ] = _settings.plugins[ j ].values[ k ];
325 | } );
326 | _settings.groups = _settings.groups.concat( _settings.plugins[ j ].groups );
327 | _settings.fractions = _settings.fractions.concat( _settings.plugins[ j ].fractions );
328 | }
329 | } else {
330 | _settings.plugins = {};
331 | }
332 |
333 | _base = document.createElement( 'div' );
334 | _base.className = 'rs-base';
335 | _div = document.createElement( 'div' );
336 | _div.className = 'rs-container';
337 | _div.style.height = 'auto';
338 | _base.appendChild( _div );
339 | document.body.appendChild( _base );
340 |
341 | var style = window.getComputedStyle( _base, null ).getPropertyValue( 'font-size' );
342 | //_elHeight = parseFloat( style );
343 |
344 | if( !_settings ) return;
345 |
346 | if( _settings.groups ) {
347 | iterateKeys( _settings.groups, function( j ) {
348 | var g = _settings.groups[ parseInt( j, 10 ) ];
349 | var div = document.createElement( 'div' );
350 | div.className = 'rs-group';
351 | g.div = div;
352 | var h1 = document.createElement( 'h1' );
353 | h1.textContent = g.caption;
354 | h1.addEventListener( 'click', function( e ) {
355 | this.classList.toggle( 'hidden' );
356 | e.preventDefault();
357 | }.bind( div ) );
358 | _div.appendChild( h1 );
359 | _div.appendChild( div );
360 | } );
361 | }
362 |
363 | if( _settings.fractions ) {
364 | iterateKeys( _settings.fractions, function( j ) {
365 | var f = _settings.fractions[ parseInt( j, 10 ) ];
366 | var div = document.createElement( 'div' );
367 | div.className = 'rs-fraction';
368 | var legend = document.createElement( 'div' );
369 | legend.className = 'rs-legend';
370 |
371 | var h = 0;
372 | iterateKeys( _settings.fractions[ j ].steps, function( k ) {
373 | var p = document.createElement( 'p' );
374 | p.textContent = _settings.fractions[ j ].steps[ k ];
375 | p.style.color = _colours[ h ];
376 | legend.appendChild( p );
377 | h++;
378 | } );
379 | div.appendChild( legend );
380 | div.style.height = h * _elHeight + 'px';
381 | f.div = div;
382 | var graph = new StackGraph( div, h );
383 | f.graph = graph;
384 | _div.appendChild( div );
385 | } );
386 | }
387 |
388 | }
389 |
390 | function _update() {
391 |
392 | iterateKeys( _settings.plugins, function( j ) {
393 | _settings.plugins[ j ].update();
394 | } );
395 |
396 | iterateKeys( _perfCounters, function( j ) {
397 | _perfCounters[ j ].draw();
398 | } );
399 |
400 | if( _settings && _settings.fractions ) {
401 | iterateKeys( _settings.fractions, function( j ) {
402 | var f = _settings.fractions[ parseInt( j, 10 ) ];
403 | var v = [];
404 | var base = _perfCounters[ f.base.toLowerCase() ];
405 | if( base ) {
406 | base = base.value();
407 | iterateKeys( _settings.fractions[ j ].steps, function( k ) {
408 | var s = _settings.fractions[ j ].steps[ parseInt( k, 10 ) ].toLowerCase();
409 | var val = _perfCounters[ s ];
410 | if( val ) {
411 | v.push( val.value() / base );
412 | }
413 | } );
414 | }
415 | f.graph.draw( v );
416 | } );
417 | }
418 |
419 | /*if( _height != _div.clientHeight ) {
420 | _height = _div.clientHeight;
421 | _base.style.height = _height + 2 * _elHeight + 'px';
422 | console.log( _base.clientHeight );
423 | }*/
424 |
425 | }
426 |
427 | _init();
428 |
429 | return function( id ) {
430 | if( id ) return _perf( id );
431 | return {
432 | element: _base,
433 | update: _update
434 | }
435 | }
436 |
437 | };
438 |
--------------------------------------------------------------------------------
/game/states/boot.js:
--------------------------------------------------------------------------------
1 |
2 | 'use strict';
3 |
4 | var game;
5 | var cursors;
6 | var rS;
7 | var wPx, hPx;
8 | var velocity = 5;
9 |
10 | function Boot() {
11 | rS = new rStats( {
12 | values: {
13 | fps: { caption: 'Framerate (FPS)' },
14 | update: { caption: 'Total update time (ms)' },
15 | render: { caption: 'Total render time (ms)' }
16 | }
17 | } );
18 | }
19 |
20 | Boot.prototype = {
21 | preload: function() {
22 | game = this.game;
23 | //generate the world
24 | wPx = game.worldManager.world.chunks * (game.worldManager.world.units * 132);
25 | hPx = game.worldManager.world.chunks * (game.worldManager.world.units * 74);
26 | game.world.setBounds(0, 0, wPx, hPx);
27 | //generate all the layers
28 | game.worldManager.createWorld(game.generate.generateMap(game.worldManager.world, 0));
29 | //build the chunk!
30 | var c = 0;
31 | while (c < game.worldManager.chunks.length){
32 | var tiles = game.worldManager.getAllTiles(c);
33 | tiles = game.generate.generateChunk(game.worldManager.world, tiles);
34 | game.worldManager.setAllTiles(c, tiles);
35 | game.worldManager.cleanWorld();
36 | c++;
37 | }
38 |
39 | //other stuff?
40 | game.time.advancedTiming = true;
41 | game.debug.renderShadow = false;
42 | game.stage.disableVisibilityChange = true;
43 | game.stage.smoothed = false;
44 | //set up plugins and game
45 | game.plugins.add(new Phaser.Plugin.Isometric(game));
46 | game.physics.startSystem(Phaser.Plugin.Isometric.ISOARCADE);
47 | game.iso.anchor.setTo(0.5, 0.1);
48 | game.renderer.renderSession.roundPixels = true;
49 | //this does nothing, default is .50
50 | //game.iso.projectionAngle = Math.atan(100/200);
51 | },
52 | create: function() {
53 | game.worldManager.drawWorld();
54 | cursors = game.input.keyboard.createCursorKeys();
55 | game.world.camera.roundPx = false;
56 | this.moveCamera((wPx / 2) - (1024 / 2), (hPx / 2) - (768 / 2));
57 | },
58 | update: function () {
59 | rS( 'FPS' ).frame();
60 | rS( 'update' ).start();
61 | //trigger the frame for anyone watching
62 | rS().update();
63 | //this is how scaling is done, but this code is super rough
64 | //isoGroup.scale.setTo(2,2);
65 | if (cursors.right.isDown){
66 | this.moveCamera((game.world.camera.x + velocity), game.world.camera.y);
67 | }
68 | if (cursors.left.isDown){
69 | this.moveCamera((game.world.camera.x - velocity), game.world.camera.y);
70 | }
71 | if (cursors.down.isDown){
72 | this.moveCamera(game.world.camera.x, (game.world.camera.y + velocity));
73 | }
74 | if (cursors.up.isDown){
75 | this.moveCamera(game.world.camera.x, (game.world.camera.y - velocity));
76 | }
77 | rS( 'update' ).end();
78 | },
79 | render: function () {
80 | rS( 'render' ).start();
81 |
82 | rS( 'render' ).end();
83 | rS().update();
84 | },
85 | moveCamera: function(x, y){
86 | //set the camera first
87 | game.world.camera.setPosition(x,y);
88 | //get the real world view coords of the cam
89 | var isoCam = game.world.camera.view;
90 | //make a rectangle out of them
91 | //TODO: change resolution to consts
92 | var viewport = {
93 | left: isoCam.x,
94 | right: isoCam.x + 1024,
95 | top: isoCam.y,
96 | bottom: isoCam.y + 768
97 | };
98 | //go through each chunk, and check to see if it's in frame or not
99 | var i = 0;
100 | while (i < game.worldManager.chunks.length){
101 | if (intersectRect(game.worldManager.chunks[i], viewport) === true){
102 | //do something
103 | game.worldManager.chunks[i].group.visible = true;
104 | //console.log("chunk : " + i + " is visible");
105 | }else{
106 | game.worldManager.chunks[i].group.visible = false;
107 | //console.log("chunk : " + i + " is invisible");
108 | }
109 | i++;
110 | }
111 | //functions
112 | function intersectRect(r1, r2) {
113 | // console.log("intersect: (chunk / camera)");
114 | // console.log("camera.left (" + r2.left + ") > chunk.right (" + r1.right + ") - [" + ((r2.left > r1.right)?"bad":"good") + "]");
115 | // console.log("camera.right (" + r2.right + ") > chunk.left (" + r1.left + ") - [" + ((r2.right < r1.left)?"bad":"good") + "]");
116 | // console.log("camera.top (" + r2.top + ") > chunk.bottom (" + r1.bottom + ") - [" + ((r2.top > r1.bottom)?"bad":"good") + "]");
117 | // console.log("camera.bottom (" + r2.bottom + ") > chunk.top (" + r1.top + ") - [" + ((r2.bottom < r1.top)?"bad":"good") + "]");
118 | return !(r2.left > r1.right ||
119 | r2.right < r1.left ||
120 | r2.top > r1.bottom ||
121 | r2.bottom < r1.top);
122 | }
123 | }
124 | };
125 |
126 | module.exports = Boot;
127 |
--------------------------------------------------------------------------------
/game/states/gameover.js:
--------------------------------------------------------------------------------
1 |
2 | 'use strict';
3 | function GameOver() {}
4 |
5 | GameOver.prototype = {
6 | preload: function () {
7 |
8 | },
9 | create: function () {
10 | var style = { font: '65px Arial', fill: '#ffffff', align: 'center'};
11 | this.titleText = this.game.add.text(this.game.world.centerX,100, 'Game Over!', style);
12 | this.titleText.anchor.setTo(0.5, 0.5);
13 |
14 | this.congratsText = this.game.add.text(this.game.world.centerX, 200, 'You Win!', { font: '32px Arial', fill: '#ffffff', align: 'center'});
15 | this.congratsText.anchor.setTo(0.5, 0.5);
16 |
17 | this.instructionText = this.game.add.text(this.game.world.centerX, 300, 'Click To Play Again', { font: '16px Arial', fill: '#ffffff', align: 'center'});
18 | this.instructionText.anchor.setTo(0.5, 0.5);
19 | },
20 | update: function () {
21 | if(this.game.input.activePointer.justPressed()) {
22 | this.game.state.start('play');
23 | }
24 | }
25 | };
26 | module.exports = GameOver;
27 |
--------------------------------------------------------------------------------
/game/states/menu.js:
--------------------------------------------------------------------------------
1 |
2 | 'use strict';
3 | function Menu() {}
4 |
5 | Menu.prototype = {
6 | preload: function() {
7 |
8 | },
9 | create: function() {
10 | var style = { font: '65px Arial', fill: '#ffffff', align: 'center'};
11 | this.sprite = this.game.add.sprite(this.game.world.centerX, 138, 'yeoman');
12 | this.sprite.anchor.setTo(0.5, 0.5);
13 |
14 | this.titleText = this.game.add.text(this.game.world.centerX, 300, '\'Allo, \'Allo!', style);
15 | this.titleText.anchor.setTo(0.5, 0.5);
16 |
17 | this.instructionsText = this.game.add.text(this.game.world.centerX, 400, 'Click anywhere to play "Click The Yeoman Logo"', { font: '16px Arial', fill: '#ffffff', align: 'center'});
18 | this.instructionsText.anchor.setTo(0.5, 0.5);
19 |
20 | this.sprite.angle = -20;
21 | this.game.add.tween(this.sprite).to({angle: 20}, 1000, Phaser.Easing.Linear.NONE, true, 0, 1000, true);
22 | },
23 | update: function() {
24 | if(this.game.input.activePointer.justPressed()) {
25 | this.game.state.start('play');
26 | }
27 | }
28 | };
29 |
30 | module.exports = Menu;
31 |
--------------------------------------------------------------------------------
/game/states/play.js:
--------------------------------------------------------------------------------
1 |
2 | 'use strict';
3 | function Play() {}
4 | Play.prototype = {
5 | create: function() {
6 |
7 | },
8 | update: function() {
9 |
10 | }
11 | };
12 |
13 | module.exports = Play;
14 |
--------------------------------------------------------------------------------
/game/states/preload.js:
--------------------------------------------------------------------------------
1 |
2 | 'use strict';
3 | function Preload() {
4 | this.asset = null;
5 | this.ready = false;
6 | }
7 |
8 | Preload.prototype = {
9 | preload: function() {
10 | console.log("* Preload Init");
11 | this.asset = this.add.sprite(this.width/2,this.height/2, 'preloader');
12 | this.asset.anchor.setTo(0.5, 0.5);
13 |
14 | this.load.onLoadComplete.addOnce(this.onLoadComplete, this);
15 | this.load.setPreloadSprite(this.asset);
16 | this.load.atlasXML('landscape', 'assets/landscapeTiles_sheet.png', 'assets/landscapeTiles_sheet.xml');
17 | this.load.atlasXML('building', 'assets/buildingTiles_sheet.png', 'assets/buildingTiles_sheet.xml');
18 | this.load.atlasXML('city', 'assets/cityTiles_sheet.png', 'assets/cityTiles_sheet.xml');
19 |
20 | },
21 | create: function() {
22 | this.asset.cropEnabled = false;
23 | },
24 | update: function() {
25 | if(!!this.ready) {
26 | this.game.state.start('boot');
27 | }else{
28 | }
29 | },
30 | onLoadComplete: function() {
31 | this.ready = true;
32 | }
33 | };
34 |
35 | module.exports = Preload;
36 |
--------------------------------------------------------------------------------
/game/tiles.json:
--------------------------------------------------------------------------------
1 | {
2 | "slices": {
3 | "island":[
4 | [53,42,61],
5 | [35,59,34],
6 | [60,27,68]
7 | ],
8 | "hill":[
9 | [0,10,0],
10 | [16,67,15],
11 | [0,22,0]
12 | ],
13 | "paved":[
14 | [114,80,119],
15 | [87,81,88],
16 | [118,95,122]
17 | ],
18 | "grass_road":[
19 | [123,74,126],
20 | [82,0,82],
21 | [125,74,127]
22 | ],
23 | "city_road":[
24 | [122,73,125],
25 | [81,0,81],
26 | [124,73,126]
27 | ]
28 | },
29 | "highways": {
30 | "open": 80,
31 | "corner": 59,
32 | "edges": {
33 | "n": [75,54],
34 | "e": [83,62],
35 | "w": [83,62],
36 | "s": [75,54]
37 | },
38 | "edge_caps":{
39 | "n": 61,
40 | "e": 69,
41 | "w": 68,
42 | "s": 76
43 | },
44 | "joins": {
45 | "n": 93,
46 | "e": 101,
47 | "w": 100,
48 | "s": 107
49 | },
50 | "straight": {
51 | "n": [86,87],
52 | "e": [79,94],
53 | "w": [79,94],
54 | "s": [86,87]
55 | }
56 | },
57 | "roads": {
58 | "89": {
59 | "n": true,
60 | "e": true,
61 | "w": true,
62 | "s": true,
63 | "set": "city_plain"
64 | },
65 | "96": {
66 | "n": false,
67 | "e": true,
68 | "w": true,
69 | "s": true,
70 | "set": "city_plain"
71 | },
72 | "88": {
73 | "n": true,
74 | "e": false,
75 | "w": true,
76 | "s": true,
77 | "set": "city_plain"
78 | },
79 | "103": {
80 | "n": true,
81 | "e": true,
82 | "w": true,
83 | "s": false,
84 | "set": "city_plain"
85 | },
86 | "95": {
87 | "n": true,
88 | "e": true,
89 | "w": false,
90 | "s": true,
91 | "set": "city_plain"
92 | },
93 | "122":{
94 | "n": false,
95 | "e": true,
96 | "w": false,
97 | "s": true,
98 | "set": "city_plain"
99 | },
100 | "125":{
101 | "n": false,
102 | "e": false,
103 | "w": true,
104 | "s": true,
105 | "set": "city_plain"
106 | },
107 | "124":{
108 | "n": true,
109 | "e": true,
110 | "w": false,
111 | "s": false,
112 | "set": "city_plain"
113 | },
114 | "126":{
115 | "n": true,
116 | "e": false,
117 | "w": true,
118 | "s": false,
119 | "set": "city_plain"
120 | },
121 | "73":{
122 | "n": false,
123 | "e": true,
124 | "w": true,
125 | "s": false,
126 | "set": "city_plain"
127 | },
128 | "81":{
129 | "n": true,
130 | "e": false,
131 | "w": false,
132 | "s": true,
133 | "set": "city_plain"
134 | },
135 | "56":{
136 | "n": true,
137 | "e": false,
138 | "w": false,
139 | "s": true,
140 | "set": "city_intersection"
141 | },
142 | "64":{
143 | "n": false,
144 | "e": true,
145 | "w": true,
146 | "s": false,
147 | "set": "city_intersection"
148 | }
149 | },
150 | "parks":[43,51,59,67],
151 | "walls":{
152 | "n": [12,23],
153 | "e": [8,17],
154 | "s": [7,16],
155 | "w": [4,11],
156 | },
157 | "buildings": {
158 | "residential":{
159 | "red":{
160 | "bottoms": {
161 | "n": [92],
162 | "e": [36],
163 | "s": [30],
164 | "w": [106],
165 | },
166 | "tops": {
167 | "ns": [45,52],
168 | "ew": [49,54]
169 | }
170 | },
171 | "grey":{
172 | "bottoms": {
173 | "n": [85],
174 | "e": [42],
175 | "s": [37],
176 | "w": [85],
177 | },
178 | "tops": {
179 | "ns": [50,55],
180 | "ew": [53,56]
181 | }
182 | },
183 | "brown":{
184 | "bottoms": {
185 | "n": [131],
186 | "e": [21],
187 | "s": [14],
188 | "w": [131],
189 | },
190 | "tops": {
191 | "ns": [32,43],
192 | "ew": [38,47]
193 | }
194 | },
195 | "beige":{
196 | "bottoms": {
197 | "n": [130],
198 | "e": [29],
199 | "s": [22],
200 | "w": [130],
201 | },
202 | "tops": {
203 | "ns": [39,48],
204 | "ew": [44,51]
205 | }
206 | },
207 | "all":{
208 | "roofs": {
209 | "n": [59,64,66,73,75,77,89,91,105],
210 | "e": [61,68,70,80,82,84,96,112],
211 | "s": [58,63,65,72,74,76,88,90,104],
212 | "w": [57,60,62,67,69,71,81,83,97,98],
213 | "all": []
214 | }
215 | }
216 | },
217 | "commercial":{
218 | "red":{
219 | "bottoms": {
220 | "n": [33,46,92],
221 | "e": [1,9,17,26,41,99],
222 | "s": [2,10,18,34,113,123],
223 | "w": [25,40,106],
224 | },
225 | "tops": {
226 | "ns": [16,23],
227 | "ew": [16,23]
228 | }
229 | },
230 | "grey":{
231 | "bottoms": {
232 | "n": [19,35,85,114],
233 | "e": [3,12,28,93,100,107,116,124],
234 | "s": [4,20,101,108,109,115,117,125],
235 | "w": [11,27,122],
236 | },
237 | "tops": {
238 | "ns": [24,31],
239 | "ew": [24,31]
240 | }
241 | },
242 | "brown":{
243 | "bottoms": {
244 | "n": [131],
245 | "e": [],
246 | "s": [],
247 | "w": [131],
248 | },
249 | "tops": {
250 | "ns": [7,129],
251 | "ew": [7,129]
252 | }
253 | },
254 | "beige":{
255 | "bottoms": {
256 | "n": [130],
257 | "e": [],
258 | "s": [],
259 | "w": [130],
260 | },
261 | "tops": {
262 | "ns": [8,15],
263 | "ew": [8,15]
264 | }
265 | },
266 | "all":{
267 | "roofs": {
268 | "n": [87,103],
269 | "e": [94,110],
270 | "s": [86,102],
271 | "w": [79,95],
272 | "all": [5,6,13,111,118,119,120,121,127,128]
273 | }
274 | }
275 | }
276 | }
277 | }
278 |
--------------------------------------------------------------------------------
/index.html:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 | IsoCitySim
8 |
9 |
10 |
11 |
12 |
13 |
14 |
15 |
16 |
17 |
18 |
19 |
20 |
21 |
--------------------------------------------------------------------------------
/package.json:
--------------------------------------------------------------------------------
1 | {
2 | "name": "isocitysim",
3 | "private": true,
4 | "devDependencies": {
5 | "bower": "~0.9.2",
6 | "browserify": "~3.38.0",
7 | "connect-livereload": "~0.1.3",
8 | "grunt": "~0.4.1",
9 | "grunt-browserify": "~1.3.0",
10 | "grunt-contrib-connect": "~0.2.0",
11 | "grunt-contrib-copy": "*",
12 | "grunt-contrib-watch": "~0.4.3",
13 | "grunt-gh-pages": "^0.10.0",
14 | "grunt-html-build": "~0.3.2",
15 | "grunt-open": "~0.2.0",
16 | "matchdep": "~0.1.2",
17 | "moment": "~2.0.0",
18 | "underscore": "*",
19 | "underscore.string": "*"
20 | },
21 | "engines": {
22 | "node": ">=0.8.0"
23 | }
24 | }
25 |
--------------------------------------------------------------------------------
/templates/_main.js.tpl:
--------------------------------------------------------------------------------
1 | 'use strict';
2 |
3 | //global variables
4 | window.onload = function () {
5 | var game = new Phaser.Game(<%= gameWidth %>, <%= gameHeight %>, Phaser.AUTO, '<%= _.slugify(projectName) %>', null, false, false);
6 | var Roads = require('./plugins/Roads');
7 | var Generate = require('./plugins/Generate');
8 | var WorldManager = require('./plugins/WorldManager');
9 | game.tiles = require('./tiles.json');
10 | game.roads = new Roads(game);
11 | game.generate = new Generate(game);
12 | game.worldManager = new WorldManager(game);
13 |
14 | // Game States
15 | <% _.forEach(gameStates, function(gameState) { %>game.state.add('<%= gameState.shortName %>', require('./states/<%= gameState.shortName %>'));
16 | <% }); %>
17 |
18 | game.state.start('preload');
19 | };
20 |
--------------------------------------------------------------------------------