Forum

Where to put code?

14 December 2015 12:31
I have a few questions about where to put code for a project.

I have been studying this manual page that outlines the structure of a project.

When I created this project from the Project Manager I checked the 'Bundled Project' option. Was that the right thing to do? I still don't understand exactly what this option is bundling or where it bundles it.

I have been trying to follow the Making a Game Part 1 tutorial. The first thing I noticed is that the HTML file in the tutorial looks a lot different from the HTML file that was generated by the Project Manager.

My current "project_test002.html" file (based on the tutorial):
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1, user-scalable=no">
<script type="text/javascript" src="b4w.min.js"></script>
<script type="text/javascript" src="project_test002.js"></script>

<style>
body {
margin: 0;
padding: 0;
overflow: hidden;
}

div#canvas3d {
position: absolute;
top: 0;
left: 0;
width: 100%;
height: 100%;
overflow: hidden;
}
</style>

</head>
<body>
<div id="canvas3d"></div>
</body>
</html>


I pasted in the code just as the tutorial says but all I get when I open the HTML file I see a logo cube that I can't interact with. Maybe it's not finding the .blend file.

My "project_test002.js" file:
"use strict"

if (b4w.module_check("project_test002"))
throw "Failed to register module: project_test002";

b4w.register("project_test002", function(exports, require) {

var m_anim = require("animation");
var m_app = require("app");
var m_main = require("main");
var m_data = require("data");
var m_ctl = require("controls");
var m_phy = require("physics");
var m_cons = require("constraints");
var m_scs = require("scenes");
var m_trans = require("transform");
var m_cfg = require("config");

var _character;
var _character_rig;

var ROT_SPEED = 1.5;
var CAMERA_OFFSET = new Float32Array([0, 1.5, -4]);

exports.init = function() {
m_app.init({
canvas_container_id: "canvas3d",
callback: init_cb,
physics_enabled: true,
alpha: false,
physics_uranium_path: "uranium.js"
});
}

function init_cb(canvas_elem, success) {

if (!success) {
console.log("b4w init failure");
return;
}

m_app.enable_controls(canvas_elem);

window.addEventListener("resize", on_resize);

load();
}

function on_resize() {
m_app.resize_to_container();
};

function load() {
m_data.load("project_test002.json", load_cb);
}

function load_cb(root) {

}

});

b4w.require("project_test002").init();





function setup_rotation() {
var key_a = m_ctl.create_keyboard_sensor(m_ctl.KEY_A);
var key_d = m_ctl.create_keyboard_sensor(m_ctl.KEY_D);
var key_left = m_ctl.create_keyboard_sensor(m_ctl.KEY_LEFT);
var key_right = m_ctl.create_keyboard_sensor(m_ctl.KEY_RIGHT);

var elapsed_sensor = m_ctl.create_elapsed_sensor();

var rotate_array = [
key_a, key_left,
key_d, key_right,
elapsed_sensor
];

var left_logic = function(s){return (s[0] || s[1])};
var right_logic = function(s){return (s[2] || s[3])};

function rotate_cb(obj, id, pulse) {

var elapsed = m_ctl.get_sensor_value(obj, "LEFT", 4);

if (pulse == 1) {
switch(id) {
case "LEFT":
m_phy.character_rotation_inc(obj, elapsed * ROT_SPEED, 0);
break;
case "RIGHT":
m_phy.character_rotation_inc(obj, -elapsed * ROT_SPEED, 0);
break;
}
}
}

m_ctl.create_sensor_manifold(_character, "LEFT", m_ctl.CT_CONTINUOUS,
rotate_array, left_logic, rotate_cb);
m_ctl.create_sensor_manifold(_character, "RIGHT", m_ctl.CT_CONTINUOUS,
rotate_array, right_logic, rotate_cb);
}




function setup_jumping() {
var key_space = m_ctl.create_keyboard_sensor(m_ctl.KEY_SPACE);

var jump_cb = function(obj, id, pulse) {
if (pulse == 1) {
m_phy.character_jump(obj);
}
}

m_ctl.create_sensor_manifold(_character, "JUMP", m_ctl.CT_TRIGGER,
[key_space], function(s){return s[0]}, jump_cb);
}




function setup_camera() {
var camera = m_scs.get_active_camera();
m_cons.append_semi_soft_cam(camera, _character, CAMERA_OFFSET);
}


I replaced the name "game_example_main" with my project name, "project_test002".

If I load a Fast Preview from within Blender it looks okay, but of course I can't make the character move without the code.

Also, my .b4w_project config file looks different from the one on the manual page. Mine looks like this:

[info]
author =
name = project_test002
title =

[paths]
assets_dirs = apps_dev/project_test002;
blend_dirs = apps_dev/project_test002;
blender_exec = blender
build_dir = apps_dev/project_test002
deploy_dir =

[compile]
apps =
css_ignore =
engine_type = update
js_ignore =
optimization = simple
use_physics =
use_smaa_textures =
version =

[deploy]
assets_path_prefix =
override =


I don't think there are any problems with my .blend file, but here's a link to it anyway.

If anyone can point out what I've done wrong I would really appreciate it.
14 December 2015 20:05
Hello,

First of all, you've put new methods like setup_rotation, setup_jumping etc outside the module definition. They should be under the b4w.register function. Otherwise there'll be a problem with namespaces.
Another important issue is that you put enable_controls to the init_cb section. There are no controllable elements at this stage. Thus, it should be placed to the load_cb section. Also, if you want to control the camera the enable_camera_controls call is required.

The final js should look like this:
"use strict"

if (b4w.module_check("project_test002"))
    throw "failed to register module: project_test002";

b4w.register("project_test002", function(exports, require) {

var m_anim  = require("animation");
var m_app   = require("app");
var m_main  = require("main");
var m_data  = require("data");
var m_ctl   = require("controls");
var m_phy   = require("physics");
var m_cons  = require("constraints");
var m_scs   = require("scenes");
var m_trans = require("transform");
var m_cfg   = require("config");

var _character;
var _character_rig;

var rot_speed = 1.5;
var camera_offset = new float32array([0, 1.5, -4]);

exports.init = function() {
    m_app.init({
        canvas_container_id: "canvas3d",
        callback: init_cb,
        physics_enabled: true,
        alpha: false,
        physics_uranium_path: "uranium.js"
    });
}

function init_cb(canvas_elem, success) {

    if (!success) {
        console.log("b4w init failure");
        return;
    }

    window.addeventlistener("resize", on_resize);

    load();
}

function on_resize() {
    m_app.resize_to_container();
};

function load() {
    m_data.load("project_test002.json", load_cb);
}

function load_cb(root) {
    m_app.enable_controls();
    m_app.enable_camera_controls();
}

function setup_rotation() {
    var key_a     = m_ctl.create_keyboard_sensor(m_ctl.key_a);
    var key_d     = m_ctl.create_keyboard_sensor(m_ctl.key_d);
    var key_left  = m_ctl.create_keyboard_sensor(m_ctl.key_left);
    var key_right = m_ctl.create_keyboard_sensor(m_ctl.key_right);

    var elapsed_sensor = m_ctl.create_elapsed_sensor();

    var rotate_array = [
        key_a, key_left,
        key_d, key_right,
        elapsed_sensor
    ];

    var left_logic  = function(s){return (s[0] || s[1])};
    var right_logic = function(s){return (s[2] || s[3])};

    function rotate_cb(obj, id, pulse) {

        var elapsed = m_ctl.get_sensor_value(obj, "left", 4);

        if (pulse == 1) {
            switch(id) {
            case "left":
                m_phy.character_rotation_inc(obj, elapsed * rot_speed, 0);
                break;
            case "right":
                m_phy.character_rotation_inc(obj, -elapsed * rot_speed, 0);
                break;
            }
        }
    }

    m_ctl.create_sensor_manifold(_character, "left", m_ctl.ct_continuous,
        rotate_array, left_logic, rotate_cb);
    m_ctl.create_sensor_manifold(_character, "right", m_ctl.ct_continuous,
        rotate_array, right_logic, rotate_cb);
}

function setup_jumping() {
    var key_space = m_ctl.create_keyboard_sensor(m_ctl.key_space);

    var jump_cb = function(obj, id, pulse) {
        if (pulse == 1) {
            m_phy.character_jump(obj);
        }
    }

    m_ctl.create_sensor_manifold(_character, "jump", m_ctl.ct_trigger, 
        [key_space], function(s){return s[0]}, jump_cb);
}

function setup_camera() {
    var camera = m_scs.get_active_camera();
    m_cons.append_semi_soft_cam(camera, _character, camera_offset);
}

});
b4w.require("project_test002").init();


And don't forget to check the console output every time you run the application
14 December 2015 20:12
When I created this project from the Project Manager I checked the 'Bundled Project' option. Was that the right thing to do? I still don't understand exactly what this option is bundling or where it bundles it.
This checkbox means that your project won't use external js files from blend4web/apps_dev/folder and asset files from /blend4web/deploy/assets and will use its own internal structure. All scripts and assets would be searched for in the local folder.
15 December 2015 02:08
Evgeny, thank you so much for the explanation and example! This helps a lot.

In what sort of cases should I choose to bundle my project? (What criteria should I base the decision on?)

And can a project that isn't bundled be converted to a bundled one later? Can we switch between these modes?
15 December 2015 10:53
Evgeny, thank you so much for the explanation and example! This helps a lot.
You are welcome.
In what sort of cases should I choose to bundle my project? (What criteria should I base the decision on?)
And can a project that isn't bundled be converted to a bundled one later? Can we switch between these modes?
Generally, bundled projects are good for small projects. If you use this method, this means you are not going to make any changes to the b4w engine or write some additional modules for it. Also, you won't be able to compile a bundled project (obfuscate it and increase the performance a bit).

All this can be done with a non-bundled project. But it has a bit more complex structure.
Conversation is not possible because project manager doesn't know the exact structure of your application. But you can convert the project by yourself. You'll need to change the scripts paths in html files and put required assets to the required destination. But anyway it would be better to create a new project and just place source files to corresponding locations.
15 December 2015 17:13
That makes it more clear - thanks again!
17 December 2015 06:35
Does bundling the app also mean it will not show in the Viewer's "scenes" list even if specified inside assets.son?

When I expand the "Scenes" section of the sidebar I see a message:
"Failed loading scenes list. Maybe a syntax error?"
I am wondering if this is because I bundled the project.
17 December 2015 14:40
Hi,
When I expand the "Scenes" section of the sidebar I see a message:
"Failed loading scenes list. Maybe a syntax error?"
This means that the Viewer cannot load asset.json file. Either you are running the Viewer from local file system, or
you've introduced a syntax error in this JSON file while editing it.
The Founder | Twitter | Facebook | Linkedin
19 December 2015 12:22
Thanks, Yuri. It's working for me again.
 
Please register or log in to leave a reply.