Questions from the forum

Top  Previous  Next

Q: I want to create a crosshair who will rotate the camera and also move around the center of the screen as I move the mouse around.

A: Simply set mouse_mode to 1 to get the desired result; here's an example.

 

BMAP* pointer_tga = "pointer.tga";

 

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)

       {

               my.pan -= 7 * mouse_force.x * time_step;

               camera.x = my.x;

               camera.y = my.y;

               camera.z = my.z + 50 + 1.1 * sin(my.skill44); // play with 50 and 1.1

               camera.pan = my.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) + 15; // play with 15

               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);

       }

}

 

function mouse_startup()

       mouse_mode = 1;

       mouse_map = pointer_tga;

       while (1)

       

               vec_set(mouse_pos, mouse_cursor);

               wait(1);

       }

}

 

 

Q: Assuming you had a wmb file (a simple level) with lights in it, is it possible to programmatically change the light in the level in order to make it darker or dimmer?

A: Use camera.ambient to achieve what you need; here's a snippet that changes the ambient light in a loop.

 

function lights_startup()

{

       fps_max = 100;

       while (1)

       {

               // camera.ambient will range from 0 to 100

               camera.ambient = 50 + 50 * sin(3 * total_ticks); // 3 gives the speed

               wait (1);

       }

}

 

aum83_faq1

 

aum83_faq2

 

 

Q: I want my character to play its "attack" animation whenever I press the left mouse button. How can I play the entire "attack" animation by clicking my left mouse button only once?

A: Use this example as a base for your code.

 

action player1()

{

       VECTOR temp;

       var camera_distance = 200;

       player = my; // I'm the player

       while (1)

       {

               // player's pan is controlled by the mouse and the "A" and "D" keys

               player.pan -= 10 * mouse_force.x * time_step - 1.5 * (key_a - key_d);

               camera.x = player.x - camera_distance * cos(player.pan); // keep the camera behind the player

               camera.y = player.y - camera_distance * sin(player.pan); // at the distance given by camera_distance

               camera.z = player.z + 100; // and 100 quants above the player

               camera.pan = player.pan; // the camera has the same pan angle with the player

               camera.tilt += 7 * mouse_force.y * time_step; // and can tilt freely

               if (!mouse_left) // the left mouse button wasn't pressed? Then take care of the regular animations (stand, walk)

               {

                       if (key_w + key_s > 0) // if the player is walking

                       {

                               ent_animate(my, "walk", my.skill46, ANM_CYCLE); // play its "walk" frames animation

                               // the animation speed increases when the player presses the "shift" key

                               my.skill46 += 5 * (1 + key_shift * 0.7) * time_step;

                               my.skill46 %= 100; // loop the animation

                       }

                       else // if the player is standing

                       {

                               ent_animate(my, "stand", my.skill48, ANM_CYCLE); // play the "stand" frames animation

                               my.skill48 += 2 * time_step; // "stand" animation speed

                               my.skill48 %= 100; // loop the animation

                       }

               }

               else // the left mouse button was pressed here

               {

                       my.skill40 = 0;

                       while (my.skill40 < 100) // play the "attack" animation until its end

                       {

                               ent_animate(my, "attack", my.skill40, NULL); // play the "attack" animation only once

                               my.skill40 += 2 * time_step; // "attack" animation speed

                               wait (1);

                       }

               }

               vec_set (temp, my.x); // trace 10,000 quants below the player

               temp.z -= 10000;

               // and adjust its height accordingly, placing its feet on the ground

               temp.z = - c_trace (my.x, temp, IGNORE_ME | IGNORE_PASSABLE | USE_BOX) + 15; // play with 15

               // move the player using the "W" and "S" keys; the speed increases to 200% if the player presses the "shift" key

               temp.x = 10 * (key_w - key_s) * (1 + 1 * key_shift) * time_step;

               temp.y = 0;

               my.skill47 += c_move (my, temp, nullvector, IGNORE_PASSABLE);

               wait (1);

       }

}

 

 

Q: What is the key mapping for double click? Is there any key mapping for this?

A: There isn't any key mapping for double click; however, you can track double clicks like this:

 

#define click_rate 0.7 // register a double click if the player presses the left mouse button twice in less than 0.7 seconds

 

STRING* result_str = "#10";

 

TEXT* messages_txt =

{

       pos_x = 200;

       pos_y = 20;

       string(result_str);

       flags = SHOW;

}

 

function track_clicks_startup()

{

       var time_passed;

       var doubleclick_on = 0;

       while (1)

       {

               if (mouse_left) // the left mouse button was clicked at least once?

               {

                       while (mouse_left) {wait (1);} // wait until the player releases the mouse button

                       time_passed = 0;

                       while (time_passed < click_rate)

                       {

                               if (mouse_left)

                               {

                                       str_cpy (result_str, "Double click!");

                                       doubleclick_on = 1;

                                       // do what you want with the double clicks here

                               }

                               time_passed += time_step / 16;

                               wait (1);

                       }

                       if (doubleclick_on == 0)

                       {

                               str_cpy (result_str, "Single click!");

                               // do what you want with the single clicks here

                               time_passed = 0;

                               while (time_passed < 0.5) // display the "Single click!" message for 0.5 seconds

                               {

                                       time_passed += time_step / 16;

                                       wait (1);

                               }        

                       }

               }

               else // the left mouse button wasn't clicked at all here

               {

                       doubleclick_on = 0;

                       str_cpy (result_str, "No mouse clicks!");

               }

               wait (1);

       }

}

 

 

Q: Imagine a plane flying towards a destination that is out of view; I need a needle to point towards the destination. Can you help?

A: Use the code below.

 

ENTITY* plane_target;

 

action my_target()

{

       plane_target = my;

}

 

function my_arrow()

{

       set (my, PASSABLE);

       my.ambient = 100;

       VECTOR arrow_coords;

       VECTOR temp;

       while (1)

       {

               // place the arrow at these xyz coordinates in relation to the player

               vec_set(arrow_coords.x, vector(300, -100, 0));

               vec_rotate(arrow_coords.x, player.pan);

               vec_add(arrow_coords, player.x);

               vec_set(my.x, arrow_coords.x);

               vec_set(temp, plane_target.x);

               vec_sub(temp, my.x);

               vec_to_angle(my.pan, temp);

               // my.tilt = 0; // remove the comment if you want to keep the arrow movement in plain 2D

               wait (1);

       }

}

 

action my_plane() // just a poor sample

{

       VECTOR temp;

       player = my;

       while (!plane_target) {wait (1);}

       ent_create ("arrow.mdl", nullvector, my_arrow);

       while (1)

       {

               my.pan -= 7 * mouse_force.x * time_step;

               camera.x = my.x;

               camera.y = my.y;

               camera.z = my.z;

               camera.pan = my.pan;

               camera.tilt += 5 * mouse_force.y * time_step;

               temp.x = 10 * (key_w - key_s) * time_step;

               temp.y = 5 * (key_a - key_d) * 0.6 * time_step;

               temp.z = 0;

               c_move (my, temp.x, nullvector, IGNORE_PASSABLE | GLIDE);

               wait (1);

       }

}

 

 

Q: Is there a way to scale my sky box texture (skybox+6.tga) so it doesn't get so stretched when it is created?

A: The solution is simple: use a texture with a big resolution. Compare the shots below; the first one uses a 768 x 128 pixels bitmap, while the second one uses a 3072 x 512 pixels bitmap.

 

aum83_faq3

 

aum83_faq4

 

 

Q: Is it possible to have collision detection between a hmp terrain and snow particles?

A: The big difference between sprites and particles is speed; this is achieved by ignoring the collision detection for the particles. Nevertheless, you can fake the collisions in a convincing way by playing with the lifespan for your particles, making sure that they die right after they penetrate the terrain.

 

BMAP* snow_tga = "snow.tga";

 

function snow_effect(PARTICLE *p)

{

       p->vel_x = 1 - random(2);

       p->vel_y = 1 - random(2);

       p->vel_z = -5 + random(3);

       p.lifespan = 70; // this value sets the lifespan for your particles - play with it

       p.alpha = 40 + random(50);

       p.bmap = snow_tga;

       p.size = 3;

       p.flags |= (BRIGHT | MOVE);

       p.event = NULL;

}

 

action snow_generator() // place a model above the terrain and attach it this action

{

       VECTOR temp;

       set (my, INVISIBLE | PASSABLE);

       while (1)

       {

               temp.x = my.x + 1000 - random(2000); // generate snow particles in a range of -1000...+1000 quants

               temp.y = my.y + 1000 - random(2000); // around the object on the x and y axis

               temp.z = my.z;

               effect(snow_effect, 1, temp.x, nullvector);

               temp.x = my.x + 1000 - random(2000);

               temp.y = my.y + 1000 - random(2000);

               temp.z = my.z;

               effect(snow_effect, 1, temp.x, nullvector);

               temp.x = my.x + 1000 - random(2000);

               temp.y = my.y + 1000 - random(2000);

               temp.z = my.z;

               effect(snow_effect, 1, temp.x, nullvector);

               temp.x = my.x + 1000 - random(2000);

               temp.y = my.y + 1000 - random(2000);

               temp.z = my.z;

               effect(snow_effect, 1, temp.x, nullvector);

               temp.x = my.x + 1000 - random(2000);

               temp.y = my.y + 1000 - random(2000);

               temp.z = my.z;

               effect(snow_effect, 1, temp.x, nullvector); // generate 5 snow particles each frame

               wait (1);

       }

}

 

 

Q: I want to make a particle that can rotate together with the entity that it is attached to.

A: Setting a small lifespan value for your particles will destroy them right after their creation. This way,  you can achieve what you want by simply generating a new particle each frame.

 

BMAP* effect_tga = "snow.tga";

 

function my_effect(PARTICLE *p)

{

       p.lifespan = 1; // kill the particle right after its creation

       p.alpha = 50;

       p.bmap = effect_tga;

       p.size = 5;

       p.flags |= (BRIGHT | MOVE);

       p.event = NULL;

}

 

action rotating_object() // just an example

{

       VECTOR temp;

       while (1)

       {

               my.pan += 3 * time_step;

               my.tilt += 4 * time_step;

               my.roll += 2 * time_step;

               vec_for_vertex(temp, my, 10); // generate particles from the 10th vertex of the entity

               effect(my_effect, 1, temp.x, nullvector);

               wait (1);

       }

}

 

 

Q: I have a entity that walks onto a path but I want him to move off that path when the player comes into his scan zone.

A: Use the code below.

 

var entity_speed = 3;

var movement_enabled = 0;

var dist_to_node;

var current_node = 1;

var angle_difference = 0;

 

VECTOR temp_angle;

VECTOR pos_node; // stores the position of the node

 

function move_target()

{

       while(1)

       {

               if(movement_enabled)

               {

                       entity_speed = minv(5, entity_speed + 0.5 * time_step);

                       ent_animate(my, "walk", my.skill46, ANM_CYCLE); // play its "walk" frames animation

                       my.skill46 += 5 * time_step;

                       my.skill46 %= 100; // loop the animation

                       c_move(my, vector(entity_speed * time_step, 0, 0), nullvector, IGNORE_PASSABLE | GLIDE);

                       vec_to_angle (my.pan, vec_diff (temp_angle, pos_node, my.x));

               }

               wait(1);

       }

}

 

action my_enemy() // attach this action to your enemy model

       VECTOR temp;

       while (!player) {wait (1);}     

       move_target();

       result = path_scan(me, my.x, my.pan, vector(90, 80, 400)); // scan the area looking for the player

       if (result) {movement_enabled = 1;}

       path_getnode (my, 1, pos_node, NULL);

       vec_to_angle (my.pan, vec_diff (temp_angle, pos_node, my.x)); // rotate towards the node

       while(1)

       {

               if ((c_scan(my.x, my.pan, vector(180, 90, 1000), IGNORE_ME) > 0) && (you == player)) // detected the player?

                       break; // then get out of this loop!

               dist_to_node = vec_dist(my.x, pos_node);

               if(dist_to_node < 50) // close to the node?

               {

                       current_node = path_nextnode(my, current_node, 1);

                       if (!current_node) {current_node = 1;} // reached the end of the path? Then start over!

                       path_getnode (my, current_node, pos_node, NULL);

               }

               wait(1);

       }

       // the enemy has spotted the player here

       while (1) // so it rotates towards it and starts chasing it

       {

               vec_set(temp, player.x);

               vec_sub(temp, my.x);

               vec_to_angle(my.pan, temp);

               my.tilt = 0;

               wait (1);

       }

}

 

 

Q: I'm not sure what about the numerical scancode values that are returned on my PC. How can I check the values for my joystick?

A: Here's a simple project that returns the values for the keys, mouse buttons, joysticks, etc.

 

void main()

{

       video_screen = 1; // start in full screen mode

       level_load (test_wmb);

       fps_max = 70;

       video_mode = 7; // run in 800x600 pixels

       video_depth = 32; // 32 bit mode

       while (1)

       {

               while (!key_any) {wait (1);} // wait until a key is pressed

               while (key_any) {wait (1);} // wait until a key is released

               wait (1);

       }

}

 

PANEL* scancodes_pan =

{

       digits = 30, 50, 5, *, 1, key_lastpressed; // display the scan code for the last key that was pressed

       flags = SHOW;

}