diff --git a/.gitignore b/.gitignore index 13bae1a..22a76cb 100644 --- a/.gitignore +++ b/.gitignore @@ -1,3 +1,10 @@ -.*.sw[pon] +# Build and temporary files build/ node_modules/ +samples/brick_breaker_requires.js +*.log +samples/brickbreaker/levels/levels.js + +# IDE files +.*.sw[pon] +*~ diff --git a/README.md b/README.md index 0e8774c..c47a192 100644 --- a/README.md +++ b/README.md @@ -3,7 +3,7 @@ Framework to create javascript games ## Samples: ### Brick Breaker -http://fco.github.io/JSGames +http://fco.github.io/JSGames/brickbreaker ## Test: npm run brickbreaker diff --git a/element_factory.js b/element_factory.js index 171cbf5..2fa77be 100644 --- a/element_factory.js +++ b/element_factory.js @@ -1,23 +1,14 @@ module.exports = ElementFactory; -require("./lives.js"); -require("./score.js"); -require("./aceleration.js"); -require("./velocity.js"); -require("./poligon.js"); -require("./retangle.js"); -require("./quad.js"); -require("./border.js"); -require("./arc.js"); -require("./levels.js"); +require('./elements/*.js', {mode: 'expand'}); var decamelize = require("decamelize"); -var Velocity = require("./velocity.js"); -var Point = require("./point.js"); +var Velocity = require("./elements/velocity.js"); +var Point = require("./elements/point.js"); function ElementFactory() { } ElementFactory.prototype = { createElement: function(type_class, params) { - var file = "./" + decamelize(type_class) + ".js"; + var file = "./elements/" + decamelize(type_class) + ".js"; var Class = require(file); var tmp_obj = new Class(params); tmp_obj._class = type_class; diff --git a/aceleration.js b/elements/aceleration.js similarity index 100% rename from aceleration.js rename to elements/aceleration.js diff --git a/arc.js b/elements/arc.js similarity index 100% rename from arc.js rename to elements/arc.js diff --git a/border.js b/elements/border.js similarity index 100% rename from border.js rename to elements/border.js diff --git a/levels.js b/elements/levels.js similarity index 97% rename from levels.js rename to elements/levels.js index a66a326..f759cfe 100644 --- a/levels.js +++ b/elements/levels.js @@ -9,7 +9,7 @@ Levels.prototype = { separator: ": ", levels: null, generic: function(){}, - current_level: -1, + current_level: 0, starter: function(){}, add_level: function(level) { diff --git a/lives.js b/elements/lives.js similarity index 100% rename from lives.js rename to elements/lives.js diff --git a/point.js b/elements/point.js similarity index 100% rename from point.js rename to elements/point.js diff --git a/poligon.js b/elements/poligon.js similarity index 100% rename from poligon.js rename to elements/poligon.js diff --git a/quad.js b/elements/quad.js similarity index 100% rename from quad.js rename to elements/quad.js diff --git a/retangle.js b/elements/retangle.js similarity index 100% rename from retangle.js rename to elements/retangle.js diff --git a/score.js b/elements/score.js similarity index 100% rename from score.js rename to elements/score.js diff --git a/velocity.js b/elements/velocity.js similarity index 100% rename from velocity.js rename to elements/velocity.js diff --git a/gulpfile.js b/gulpfile.js new file mode 100644 index 0000000..bbf27ed --- /dev/null +++ b/gulpfile.js @@ -0,0 +1,55 @@ +var gulp = require('gulp'); +var chug = require('gulp-chug'); +var flatten = require('gulp-flatten'); +var glob = require('glob'); +var path = require('path'); +var webserver = require('gulp-webserver'); + +gulp.task('default', ['watch'], function() { + gulp + .src("build/") + .pipe(webserver({ + livereload: true, + open: true, + directoryListing: { + enable: true, + path: "build" + } + })) + ; +}); + +gulp.task("build", function() { + gulp + .src( './samples/**/gulpfile.js', { read: false } ) + .pipe( chug({tasks: ["build"]}) ) + ; + + gulp + .src( './samples/**/build/*' ) + .pipe( flatten({ includeParents: 1}) ) + .pipe( gulp.dest('build') ) + ; +}); + +gulp.task("watch", ["build"], function() { + gulp.watch(["**.js", "**.json"], ['build']); +}); + +glob.sync("samples/*").forEach(function(filepath) { + var sample = path.basename(filepath); + gulp.task(sample, function() { + gulp + .src( filepath + '/gulpfile.js', { read: false } ) + .pipe( chug() ) + ; + }); + ["build", "watch"].forEach(function(task) { + gulp.task(sample + ":" + task, function() { + gulp + .src( filepath + '/gulpfile.js', { read: false } ) + .pipe( chug({tasks: [task]}) ) + ; + }); + }); +}); diff --git a/package.json b/package.json index 68ade7f..314cf65 100644 --- a/package.json +++ b/package.json @@ -4,8 +4,8 @@ "description": "Framework to create javascript games", "main": "index.js", "scripts": { - "build": "rm -rf build || true; mkdir -p build; cp samples/*.html build; for js in samples/*.js; do browserify $js > $(echo $js | perl -pe 's{^samples}{build}'); done", - "brickbreaker": "npm install; cd samples; budo brick_breaker.js --open --live --debug" + "build": "npm install && gulp build", + "brickbreaker": "npm install && gulp brickbreaker" }, "repository": { "type": "git", @@ -19,10 +19,25 @@ "homepage": "https://github.com/FCO/JSGames", "devDependencies": { "browserify": "^13.0.0", - "budo": "^8.2.1" + "budo": "^8.2.1", + "glob": "^7.0.3", + "gulp": "^3.9.1", + "gulp-browserify2": "0.0.2", + "gulp-chug": "^0.5.1", + "gulp-concat": "^2.6.0", + "gulp-flatten": "^0.2.0", + "gulp-inject": "^4.0.0", + "gulp-insert": "^0.5.0", + "gulp-minify": "^0.0.10", + "gulp-replace": "^0.5.4", + "gulp-util": "^3.0.7", + "gulp-webserver": "^0.9.1", + "path": "^0.12.7" }, "dependencies": { + "brfs": "^1.4.3", "bulkify": "^1.2.0", - "decamelize": "^1.2.0" + "decamelize": "^1.2.0", + "require-globify": "^1.3.0" } } diff --git a/samples/brickbreaker/blocks/regular_block.js b/samples/brickbreaker/blocks/regular_block.js new file mode 100644 index 0000000..07e74c5 --- /dev/null +++ b/samples/brickbreaker/blocks/regular_block.js @@ -0,0 +1,20 @@ +exports.symbol = "###"; +exports.type = "Poligon"; +exports.transformation = function(data) { + var color = "#000000"; + if(data && data.color) color = data.color; + this.draw_colision_area = false; + this.solid = true; + this.do_not_colide_with = ["Border"]; + this.type = "Block"; + this.color = color; + this.add_vertice(-13, 0); + this.add_vertice(12, 0); + this.add_vertice(12, 15); + this.add_vertice(-13, 15); + this.on_colide_with("ball", function(bola) { + this.score.add("block"); + this.on_destroy(); + this.randomPowerUp(bola.velocity); + }); +}; diff --git a/samples/brickbreaker/generate_levels.sh b/samples/brickbreaker/generate_levels.sh new file mode 100644 index 0000000..a3bda3e --- /dev/null +++ b/samples/brickbreaker/generate_levels.sh @@ -0,0 +1,6 @@ +#!/bin/bash +cd levels +for level in *.lvl; do + COMMAND="exports.$(echo $level | cut -d. -f1) = require('fs').readFileSync('levels/$level');" + echo $COMMAND +done > levels.js diff --git a/samples/brickbreaker/gulpfile.js b/samples/brickbreaker/gulpfile.js new file mode 100644 index 0000000..b5417f2 --- /dev/null +++ b/samples/brickbreaker/gulpfile.js @@ -0,0 +1,53 @@ +var gulp = require('gulp'); +var concat = require('gulp-concat'); +var insert = require('gulp-insert'); +var replace = require('gulp-replace'); +var browserify = require("gulp-browserify2"); +var inject = require('gulp-inject'); +var webserver = require('gulp-webserver'); + +gulp.task('levels', function() { + var levelsPath = 'levels/'; + gulp.src(levelsPath + '*.lvl') + .pipe(replace("\n", "\\n")) + .pipe(insert.wrap('"', '"')) + .pipe(concat('levels.js', { newLine: ',' })) + .pipe(insert.wrap('module.exports = [', '];')) + .pipe(gulp.dest(levelsPath)); +}); + +gulp.task('build', ["levels"], function() { + var js = gulp + .src("index.js") + .pipe(browserify({ + fileName: "brickbreaker.js", + transform: [require("brfs"), require("require-globify")], + options: { + debug: true + } + })) + .pipe(gulp.dest("build")) + ; + + gulp + .src("*.html") + .pipe(gulp.dest("build")) + .pipe(inject(js, {relative: true})) + .pipe(gulp.dest("build")) + ; +}); + +gulp.task("watch", ["build"], function() { + gulp.watch(["**.js", "**.lvl", "**.json"], ['build']); +}); + +gulp.task("default", ["watch"], function() { + gulp + .src("build/") + .pipe(webserver({ + livereload: true, + directoryListing: false, + open: true + })) + ; +}); diff --git a/samples/brickbreaker/index.html b/samples/brickbreaker/index.html new file mode 100644 index 0000000..7d1e365 --- /dev/null +++ b/samples/brickbreaker/index.html @@ -0,0 +1,8 @@ + + + + + + + + diff --git a/samples/brick_breaker.js b/samples/brickbreaker/index.js similarity index 58% rename from samples/brick_breaker.js rename to samples/brickbreaker/index.js index ac94cea..3017d1d 100644 --- a/samples/brick_breaker.js +++ b/samples/brickbreaker/index.js @@ -1,4 +1,7 @@ -var Screen = require(".."); +var Screen = require("../.."); +require('./blocks/*.js', {mode: 'expand'}); +var all_levels = require("./levels/levels.js"); + var screen = new Screen(document.body); screen.has_gravity(0, 10); screen.color = "#FFFFFF"; @@ -32,6 +35,32 @@ create_lives(); var quad = screen.createElement("Poligon"); var bola = screen.createElement("Arc"); + +function Blocks(files) { + this.blocks = {}; + files.forEach(function(block) { + var conf = require("./blocks/" + block + ".js"); + this.blocks[conf.symbol] = conf; + }.bind(this)); + +} +Blocks.prototype = { + get: function (symbol) { + var block_conf, pars = {}; + if(symbol in this.blocks) { + block_conf = this.blocks[symbol]; + } else { + block_conf = this.blocks["###"]; + pars.color = "#" + symbol; + } + var block = screen.createElement(block_conf.type); + block_conf.transformation.call(block, pars); + return block; + } +}; + +var blocks = new Blocks(["regular_block"]); + levels.starter = function () { quad.destroy(); bola.destroy(); @@ -83,7 +112,7 @@ levels.starter = function () { }; }; -levels.add_level(function () { +levels.add_generic_level(function (level_number) { screen.add(levels); screen.add(lives); @@ -91,7 +120,6 @@ levels.add_level(function () { score.x = 10; score.y = 10; score.set_point_type("block", 1); - score.set_point_type("ghost", {time: 30000}); score.set_point_type("powerup", {time: 30000}); @@ -144,65 +172,68 @@ levels.add_level(function () { } }; - for(var j = 0; j < 3; j++) { - var w = screen.width; - var number_of_blocks = 25; - var block_size = 25; - var blocks_space = 5; - var r = w - (number_of_blocks * block_size + (number_of_blocks - 1) * blocks_space); - for(var i = r / 2; i < w - (r / 2); i += block_size + blocks_space) { - var block = screen.createElement("Poligon"); - block_counter++; - block.draw_colision_area = false; - block.solid = true; - block.do_not_colide_with = ["Border"]; - block.type = "Block"; - block.color = "#000000"; - block.x = i + block_size / 2; - block.y = 120 + j * 30; - block.add_vertice(-13, 0); - block.add_vertice(12, 0); - block.add_vertice(12, 15); - block.add_vertice(-13, 15); - block.going2destroy = going2destroy; - block.on_colide_with("ball", function(bola) { - score.add("block"); - block_counter--; - //this.do_not_colide_with = ["ball"]; - this.on_colide_with("ball", function(){}); - this.flutuate = false; - this.going2destroy(150); - this.velocity = bola.original_velocity.clone(); - this.velocity.mod *= 0.1; - if(block_counter <= 0) { - setTimeout(function(){ - alert("You Win!"); - this._element_factory.screen.stop = true; - }.bind(this), 100); - } else { - randomPowerUp(this, bola.velocity); - } - }); + var w = screen.width; + var number_of_blocks = 25; + var space_size = 5; + var block_size = 25; + var line_heigth = 30; + var blocks_space = 5; + var initial_i = 30; + var initial_j = 50; + var j = initial_j; + var i = initial_i; + + var level = all_levels[level_number - 1]; + var array = level.toString().match(/\S{3}|\s/g); + array.forEach(function(item) { + if(item == " ") { + i += space_size; + return; + } else if(item == "\n") { + i = initial_i; + j += line_heigth; + return; } - } - - var randomPowerUp = function (sourceBlock, velocity) { + block_counter++; + block = blocks.get(item); + block.randomPowerUp = randomPowerUp; + block.on_destroy = function() { + block_counter--; + this.on_colide_with("ball", function(){}); + this.flutuate = false; + this.going2destroy(150); + this.velocity = bola.original_velocity.clone(); + this.velocity.mod *= 0.1; + console.log(block_counter + " bricks"); + if(block_counter <= 0) { + alert("You Win!"); + //this._element_factory.screen.stop = true; + levels.next_level(); + } + }; + block.score = score; + block.going2destroy = going2destroy; + block.x = i; + block.y = j; + i += block_size; + }); + function randomPowerUp(velocity) { var powerUpPercentage = .1; // 10% of change to receive a power up if(Math.random() <= powerUpPercentage){ // TODO: Create a Power Up factory and multiple types of power ups to randomize var powerup = screen.createElement("Poligon"); - powerup.visible = true; - powerup.color = "#4EA132"; - powerup.draw_colition_area = false - powerup.do_not_colide_with = ["Block"]; - powerup.bounce_when_colide_with = ["Border"]; - powerup.type = "PowerUp"; - powerup.x = sourceBlock.x - powerup.y = sourceBlock.y; - powerup.flutuate = false; - powerup.velocity = velocity.clone(); - powerup.velocity.mod *= 0.3; - powerup.velocity.ang *= -1; + powerup.visible = true; + powerup.color = "#4EA132"; + powerup.draw_colition_area = false + powerup.do_not_colide_with = ["Block"]; + powerup.bounce_when_colide_with = ["Border"]; + powerup.type = "PowerUp"; + powerup.x = this.x + powerup.y = this.y; + powerup.flutuate = false; + powerup.velocity = velocity.clone(); + powerup.velocity.mod *= 0.3; + powerup.velocity.ang *= -1; powerup.add_vertice(0, 0); powerup.add_vertice(7, 14); @@ -214,44 +245,6 @@ levels.add_level(function () { }); } } - - var ghost = screen.createElement("Poligon"); - ghost.visible = true; - ghost.color = "#888888"; - ghost.draw_colision_area = false; - ghost.do_not_colide_with = ["Border"]; - ghost.type = "Block"; - ghost.color = "#888888"; - ghost.x = screen.width / 2; - ghost.y = 40; - ghost.add_vertice(-13, 0); - ghost.add_vertice(12, 0); - ghost.add_vertice(12, 15); - ghost.add_vertice(-13, 15); - - ghost.going2destroy = going2destroy; - - ghost.on_colide_with("ball", function(bola) { - clearInterval(this.blink_id); - score.add("ghost"); - this.do_not_colide_with = ["ball"]; - this.going2destroy(); - if(block_counter <= 0) { - setTimeout(function(){ - alert("You Win!"); - this._element_factory.screen.stop = true; - }.bind(this), 100); - } - }); - - ghost.blink_id = setInterval(function(){ - if(ghost.visible) { - ghost.do_not_colide_with = ["Border", "ball"]; - } else { - ghost.do_not_colide_with = ["Border"]; - } - ghost.visible = ! ghost.visible; - }, 5000); }); levels.next_level(); diff --git a/samples/brickbreaker/levels/level1.lvl b/samples/brickbreaker/levels/level1.lvl new file mode 100644 index 0000000..d246ef8 --- /dev/null +++ b/samples/brickbreaker/levels/level1.lvl @@ -0,0 +1,7 @@ + ### ### ### ### ### ### ### ### ### ### ### ### ### ### ### ### ### ### ### ### ### ### ### ### + + ### ### ### f00 0f0 ### ### ### ### ### ### f00 0f0 ### ### ### ### ### ### f00 0f0 ### ### ### + + ### ### ### 00f 0ff ### ### ### ### ### ### 00f 0ff ### ### ### ### ### ### 00f 0ff ### ### ### + + ### ### ### ### ### ### ### ### ### ### ### ### ### ### ### ### ### ### ### ### ### ### ### ### diff --git a/samples/brickbreaker/levels/level2.lvl b/samples/brickbreaker/levels/level2.lvl new file mode 100644 index 0000000..bc53b0d --- /dev/null +++ b/samples/brickbreaker/levels/level2.lvl @@ -0,0 +1,5 @@ + + ### ### ### ### ### ### ### ### ### ### + ### ### ### ### ### ### ### ### ### + ### ### ### ### ### ### ### ### ### ### + ### ### ### ### ### ### ### ### ### diff --git a/samples/index.html b/samples/index.html deleted file mode 100644 index 5cd5f81..0000000 --- a/samples/index.html +++ /dev/null @@ -1,9 +0,0 @@ - - - - - - - - diff --git a/screen.js b/screen.js index f9a88d1..5dbb6da 100644 --- a/screen.js +++ b/screen.js @@ -1,6 +1,6 @@ module.exports = Screen; var ElementFactory = require("./element_factory.js"); -var Aceleration = require("./aceleration.js"); +var Aceleration = require("./elements/aceleration.js"); function Screen(container) { this.container = container;