Questions from the forum
 Q: How can I detect if two particular objects hit each other? A: Here's an example that uses three balls; two of them are special (particular).   function bounce_off() {        vec_to_angle(my.pan, bounce);        my.pan += 5 - random(10); // add some randomness at each collision        if (you) // collided with another entity?        {                if ((you.skill100 == 13579) && (my.skill100 == 13579)) // you and I are special entities?                {                        beep(); // do what you need here                }        } }    action object1() // this is a special object {        my.emask |= (ENABLE_BLOCK | ENABLE_ENTITY); // the object is sensitive to block and entity collisions        my.event = bounce_off;        my.skill100 = 13579; // set this skill to a weird value in order to differentiate the object from the others        while(1)        {                c_move(me, vector(5 * time_step, 0, 0), nullvector, 0); // move ahead, in the direction given by the pan angle                wait(1);        } }   action object2() // this is a special object {        my.emask |= (ENABLE_BLOCK | ENABLE_ENTITY); // the object is sensitive to block and entity collisions        my.event = bounce_off;        my.skill100 = 13579; // set this skill to a weird value in order to differentiate the object from the others        while(1)        {                c_move(me, vector(5 * time_step, 0, 0), nullvector, 0); // move ahead, in the direction given by the pan angle                wait(1);        } }   action object3() // this is a regular object (just an example) {        my.emask |= (ENABLE_BLOCK | ENABLE_ENTITY); // the object is sensitive to block and entity collisions        my.event = bounce_off;        while(1)        {                c_move(me, vector(5 * time_step, 0, 0), nullvector, 0); // move ahead, in the direction given by the pan angle                wait(1);        } }     Q: I would like to know if it is possible to put views from one or more cameras to small windows and display them on the screen. A: There you go.   VIEW* camera1 = {        pos_x = 0;        pos_y = 0;        size_x = 512;        size_y = 384;        flags = VISIBLE; }   VIEW* camera2 = {        pos_x = 512;        pos_y = 0;        size_x = 512;        size_y = 384;        flags = VISIBLE; }   VIEW* camera3 = {        pos_x = 0;        pos_y = 384;        size_x = 512;        size_y = 384;        flags = VISIBLE; }   VIEW* camera4 = {        pos_x = 512;        pos_y = 384;        size_x = 512;        size_y = 384;        flags = VISIBLE; }   function init_startup() {        wait (-1);        video_switch(8, 0, 0); // change the resolution to 1024 x 768 pixels        camera.flags &= ~VISIBLE; // now hide the default camera        // set the desired positions and angles for the 4 cameras        vec_set (camera1.x, vector (800, 700, 100));        camera1.pan = 50;        camera1.tilt = 20;        camera1.roll = 0;        // settings for camera 2        vec_set (camera2.x, vector (500, -600, 200));        camera2.pan = 150;        camera2.tilt = -30;        camera2.roll = 20;        // settings for camera 3        vec_set (camera3.x, vector (-1000, 300, 300));        camera3.pan = 110;        camera3.tilt = -20;        camera3.roll = 10;        // settings for camera 4        vec_set (camera4.x, vector (-800, -700, 200));        camera1.pan = 220;        camera1.tilt = -10;        camera1.roll = 30; } Q: In my racing game I have an object to mark the start and goal. I want to start the watch when the player drives near it. A: Here's an example.   var race_over = 0; var total_time;   action start_counter() // attach this action to your object {        fps_max = 60; // feel free to use other values (75, etc) here        var time_offset;        while (!player) {wait (1);} // wait until player's car is loaded        // wait until the player comes close to the object; play with 100        while (vec_dist(player.x, my.x) > 100) {wait (1);}        time_offset = total_frames; // ignore the frames that have passed until now        while (!race_over) // this loop will run until the race is over        {                total_time = (total_frames - time_offset) / fps_max; // world's simplest racing timer ;)                wait (1);        } }   PANEL* time_pan = {        layer = 150;        digits(700, 20, 4.3 ,* , 1, total_time);        flags = visible; }     Q: I have a problem with A7. When I run the level after a build, no matter what script I use, the camera is messed up - it bounces all over the place. Any ideas why this is happening? I am using Windows XP with sp3. A: Disconnect your joystick / gamepad or (even better) calibrate it using Windows' Control Panel => Game Controllers.     Q: Would it be possible to automatically allocate unique ID's to each entity that is created in Wed, without it being left to the user to find a way? A: There you go.   var index = 0; var my_entities; // stores the IDs for up to 1000 entities   ENTITY* temp_entity;   function setid_startup() {        wait (-3); // wait until the level is loaded        you = ent_next(NULL); // retrieve the first entity from the level        while(you) // run this loop until all the entities are processed        {                my_entities[index] = handle(you); // get a handle to the "you" entity and store it                index += 1; // move on to the following array element                you = ent_next(you); // get the next entity        } }   function entities_startup() // just a test function, allows you to control the entities {        while (!key_s) {wait (1);} // wait until the player presses the "S" key        temp_entity = ptr_for_handle(my_entities); // now get the entity with ID = 1        temp_entity.scale_x = 3; // and set its scale_x parameter to 3        temp_entity = ptr_for_handle(my_entities); // now get the entity with ID = 2        temp_entity.z += 100; // and move it upwards by 100 quants }     Q: I'm building a quite big level, but when I want to compile it, I get the error: "Block outside level boundaries! What can i do to avoid this error? A: Take a look at the wmb compiler window: "Max level size" sets the maximum level size; you can increase this value up to 250,000 quants. If that's not enough, lower the scale of all your entities, objects, etc. If even that isn't enough, you can increase the size of the level even more IF you choose a bigger camera.clip_near value. If some of your important entities (weapons, etc) are clipped because of that you can set their z_near flag - look it up in the manual.     Q: When an object is not tall (like a little box) my player just climbs on it. How can I get rid of that? I'd like to keep the player at the floor level all the time. A: Use regular player code (including gravity) and decrease the negative z component of the speed (temp.z in my example) a bit more, just like below:   action players_code() // attach this action to your player {        var movement_speed = 10; // movement speed        VECTOR temp;        player = my; // I'm the player        set (my, INVISIBLE); // 1st person player        while (1)        {                player.pan -= 7 * mouse_force.x * time_step;                camera.x = player.x;                camera.y = player.y;                camera.z = player.z + 50 + 1.1 * sin(my.skill44);                camera.pan = player.pan;                camera.tilt += 5 * mouse_force.y * time_step;                vec_set (temp.x, my.x); // trace 10,000 quants below the player                temp.z -= 10000;                temp.z = -c_trace (my.x, temp.x, IGNORE_ME | IGNORE_PASSABLE | USE_BOX) - 2; // play with 2                temp.x = movement_speed * (key_w - key_s) * time_step;                temp.y = movement_speed * (key_a - key_d) * 0.6 * time_step;                c_move (my, temp.x, nullvector, IGNORE_PASSABLE | GLIDE);                wait (1);        } }     Q: I am using some sprites for the wheels of my train; however, the sprites are always looking at the camera. How can I fix that? A: Use this example as a base for your code.   function train_wheel1() {        while (1)        {                // play with the numerical values; they give the offset of the wheels in relation to the body                vec_set(my.x, vector(-100, -40, 10));                vec_rotate(my.x, you.pan);                vec_add(my.x, you.x);                my.pan = you.pan + 90;                wait (1);        } }   function train_wheel2() {        while (1)        {                vec_set(my.x, vector(100, -40, 10));                vec_rotate(my.x, you.pan);                vec_add(my.x, you.x);                my.pan = you.pan + 90;                wait (1);        } }   function train_wheel3() {        while (1)        {                vec_set(my.x, vector(-100, 40, 10));                vec_rotate(my.x, you.pan);                vec_add(my.x, you.x);                my.pan = you.pan + 90;                wait (1);        } }   function train_wheel4() {        while (1)        {                vec_set(my.x, vector(100, 40, 10));                vec_rotate(my.x, you.pan);                vec_add(my.x, you.x);                my.pan = you.pan + 90;                wait (1);        } }   action my_train() // attach this action to your train {        var distance_covered;        ent_create("wheel.tga", nullvector, train_wheel1);        ent_create("wheel.tga", nullvector, train_wheel2);        ent_create("wheel.tga", nullvector, train_wheel3);        ent_create("wheel.tga", nullvector, train_wheel4);        while (1)        {                        distance_covered = 0;                while (distance_covered < 1000) // move 1000 quants forward                {                        distance_covered += c_move(my, vector(20 * time_step, 0, 0), nullvector, IGNORE_PASSABLE | GLIDE);                        wait (1);                }                wait (-2); // make a 2 second pause at each end                distance_covered = 0;                while (distance_covered > -1000) // move 1000 quants backward                {                        distance_covered -= c_move(my, vector(-20 * time_step, 0, 0), nullvector, IGNORE_PASSABLE | GLIDE);                        wait (1);                }                wait (-2); // make a 2 second pause at each end        } }     Q: Does anyone know how to put a fire particle effect behind the tail of a jet? A: There you go.   BMAP* fire_tga = "fire.tga";   function fade_fire(PARTICLE *p) {        p.alpha -= 4 * time_step; // fade out the fire particles        if (p.alpha < 0)                p.lifespan = 0; }   function fire_effect(PARTICLE *p) {       p->vel_x = 1 - random(2);       p->vel_y = 1 - random(2);       p->vel_z = 1 + random(1);       p.alpha = 25 + random(50);       p.bmap = fire_tga;       p.size = 25; // gives the size of the fire particles       p.flags |= (BRIGHT | MOVE);       p.event = fade_fire; }   action my_jet() // attach this action to your plane {        VECTOR jet_offset;        // put your own code here        // ........................        while (1)        {                // put your own jet flight code here                // the example below simply makes the plane fly in a circle                c_move (my, vector(20 * time_step, 0, 0), nullvector, IGNORE_PASSABLE | GLIDE);                my.pan += 2 * time_step; // 2 sets the radius of the circle                // end of the simply flying example code                                // the jet particle effect code starts below                // place the particle jet at the proper position, play with these values                vec_set(jet_offset.x, vector(-100, -10, -20));                vec_rotate(jet_offset.x, my.pan);                vec_add(jet_offset.x, my.x);                effect(fire_effect, 5, jet_offset.x, nullvector); // generate 5 fire particles each frame                wait (1);        } } Q: How do I make a level take me to another level after getting a key, instead of making the entire game in one map? A: Follow these simple steps: 1) Paste the code below in one of your scripts. 2) Create two levels and name them level1.wmb and level2.wmb 3) Place a model entity in level1 and attach it the "my_key" action. 4) Place another model entity (a gate?) close to the end of the first level and attach it the action named "level_end". The player will be moved from level1 to level2, but only if he has got the key first and has approached the gate at the end of the first level. You can, of course, repeat the process, adding more different levels, keys, and so on.   var got_key = 0;   STRING* message_str = "#50"; // this string can store up to 50 characters   TEXT* message_txt = {        pos_x = 200;        pos_y = 20;        string(message_str);        flags = VISIBLE; }   action my_key() {        set(my, PASSABLE);        while (!player) {wait (1);} // wait until the player is loaded        while (vec_dist (player.x, my.x) > 50) // this loop runs until the player picks up the key        {                        my.pan += 5 * time_step; // 5 gives the rotation speed of the key                wait (1);        }        // the player has got the key here        got_key = 1; // so let's set the variable named got_key to 1        set(my, INVISIBLE); }   action level_end() // takes the player to the second level if he has got the key first {        while (!player) {wait (1);} // wait until the player is loaded        while (1)        {                if (vec_dist(player.x, my.x) < 100) // the player is closer than 100 quants to the exit gate?                {                        if (got_key) // the player has got the key?                        {                                level_load("level2.wmb"); // then let's load the second level                                break; // and let's get out of this while loop, no need to run it anymore                        }                        else // the player has come close to the exit gate, but hasn't got the key                        {                                str_cpy(message_str, "You need to pick up the key first. Go and find it!");                        }                }                else // the player is away from the exit gate                {                        str_cpy(message_str, ""); // so let's reset the message                }                wait (1);        } }