Questions from the forum

Top  Previous  Next

Q: How do I add movement to my player and put the camera behind it, so that when I press W,A,S,D the player will move and the camera will be kept always behind the player?

A: There you go:

 

action my_player()

{

       var movement_speed = 10; // movement speed

       var walk_percentage;

       var stand_percentage;

       VECTOR temp;

       player = my; // I'm the player

       while (1)

       {

               player.pan -= 5 * mouse_force.x * time_step; // rotate the player using the mouse

               if(!key_w && !key_s) // the player isn't moving at all?

             {

                       ent_animate(my, "stand", stand_percentage, ANM_CYCLE); // then play its "stand" animation

                       stand_percentage += 5 * time_step; // 5 = animation speed

               }

            else // the player is moving?

               {

                       ent_animate(my, "walk", walk_percentage, ANM_CYCLE); // then play its "walk" animation

                       walk_percentage += 6 * time_step; // 6 = animation speed

               }

               camera.x = player.x - 250 * cos(player.pan);

               camera.y = player.y - 250 * sin(player.pan);

               camera.pan = player.pan; // the camera and the player have the same pan angle

               camera.z = player.z + 150; // place the camera above the player, play with this value

               camera.tilt = -25;

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

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

               temp.z = 0;

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

               wait (1);

       }

}

 

 

Q: How can I add pixel & vertex shaders to entities (the easiest way)?

A: First of all, you need an .fx file that contains the shader definition - you can find plenty of them at Conitec's forum. Copy the fx file, as well as the additional resources specified inside the fx file (if any) to your game project folder. Then, create a material definition that uses your fx file, just like this:

 

MATERIAL* my_test_material =

{

       effect = "my_shader.fx"; // put  the name of your own .fx file here

}

 

Finally, create an action for your entity, using the previously defined material:

 

action easy_shaders()

{

       my.material = my_test_material;

       // the rest of the code for your entity goes here

}

 

 

Q: How can we create code that places bullet holes on surfaces?

A: Here's the updated example from Aum59.

 

VECTOR trace_coords;

var weapon_height;

var current_ammo = 20;

var players_ammo;

 

STRING* hithole_tga = "hithole.tga";

STRING* target_mdl = "target.mdl";

 

SOUND* bullet_wav = "bullet.wav";

SOUND* gotweapon2_wav = "gotweapon2.wav";

SOUND* nobullets_wav = "nobullets.wav";

SOUND* gotammo_wav = "gotammo.wav";

 

function fire_bullets(); // creates the bullets

function show_target(); // displays the (red) target model

function display_hithole(); // shows the hit hole bitmap

 

ENTITY* weapon2_ent =

{

       type = "ar18.mdl"; // weapon model

       pan = 0; // weapon angle

       x = 55; // 55 quants ahead of the view, play with this value

       y = -22; // 22 quants towards the right side of the screen, play with this value

       z = -22; // 22 quants below, play with this value

       pan = 2; // weapon's pan angle (you can also use tilt and roll)

}

 

action player1() // attach this action to your player

{

       var movement_speed = 10; // movement speed

       VECTOR temp;

       player = my; // I'm the player

       set (my, INVISIBLE);

       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); // play with 50 and 1.1

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

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

       }

}

 

action players_weapon() // attach this action to your player model

{

       set (my, PASSABLE); // the weapon is made passable

       while (!player) {wait (1);} // we wait until the player is created

       while (vec_dist (player.x, my.x) > 50) // we wait until the player comes closer than 50 quants

       {

               my.pan += 3 * time_step;

               wait (1);

       }

       players_ammo = 300;

       snd_play (gotweapon2_wav, 80, 0);

       set (my, INVISIBLE);

       set (weapon2_ent, VISIBLE);

       wait (-1);

       ent_remove (my);

}

 

function use_weapon_startup()

{

       on_mouse_left = fire_bullets; // call this function when the left mouse button is pressed

       proc_mode = PROC_LATE; // run this function at the end of the function scheduler list (elliminates jerkiness)

       VECTOR player1_pos; // stores the initial position of the player

       VECTOR player2_pos; // stores the position of the player after a frame

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

       while (1)

       {

               vec_set (player1_pos.x, player.x); // store the initial player position

               if (is (weapon2_ent, VISIBLE)) // the weapon is visible?

               {

                       vec_set(trace_coords.x, vector(10000, 0, 0)); // the weapon has a firing range of up to 10,000 quants

                       vec_rotate(trace_coords.x, camera.pan);

                       vec_add(trace_coords.x, camera.x);

                       if (c_trace(camera.x, trace_coords.x, IGNORE_ME | IGNORE_PASSABLE) > 0) // hit something?

                       {

                               ent_create (target_mdl, target.x, show_target); // then show the target model

                       }

               }

               wait (1);

               vec_set (player2_pos.x, player.x); // store player's position after 1 frame

               if (vec_dist (player1_pos.x, player2_pos.x) != 0) // the player has moved during the last frame?

               {

                       weapon_height += 30 * time_step; // then offset weapon_height (30 = weapon waving speed)

                       weapon2_ent.z += 0.03 * sin(weapon_height); // (0.03 = weapon waving amplitude)

               }

       }

}

 

function show_target()

{

       set (my, PASSABLE); // the target model is passable

       my.ambient = 100; // and should look bright enough

       my.scale_x = minv (6, vec_dist (my.x, camera.x) / 500); // play with 6 and with 500

       my.scale_y = my.scale_x;

       my.scale_z = my.scale_x;

       wait (1);

       ent_remove (my);

}

 

function fire_bullets()

{

       if (is (weapon2_ent, INVISIBLE)) {return;} // don't do anything if the player hasn't picked up the weapon yet

       if (current_ammo > 0) // got ammo?

       {

               c_trace(camera.x, trace_coords.x, IGNORE_ME | IGNORE_PASSABLE | ACTIVATE_SHOOT);

               if (you == NULL) // hit a wall?

               {

                       ent_create (hithole_tga, target.x, display_hithole); // then create a bullet hit hole

               }

               snd_play (bullet_wav, 100, 0); // play the bullet sound at a volume of 100

               current_ammo -= 1; // decrease the number of bullets

       }

       else // no ammo left?

       {

               snd_play (nobullets_wav, 100, 0); // then play the noammo.wav sound

       }

}

 

function display_hithole()

{

       vec_to_angle (my.pan, normal); // orient the hit hole sprite correctly

       vec_add(my.x, normal.x); // move the sprite a bit away from the wall

       set (my, PASSABLE); // the hit hole bitmap is passable

       set (my, TRANSLUCENT); // and transparent

       my.ambient = 50;

       my.roll = random(360); // and has a random roll angle (looks nicer this way)

       my.scale_x = 0.5; // we scale it down

       my.scale_y = my.scale_x; // on the x and y axis

       wait (-20); // show the hit hole for 20 seconds

       ent_remove (my); // and then remove it

}

 

action ammo_pack() // attach this action to your ammo pack models

{

       set (my, PASSABLE);

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

       while (vec_dist (player.x, my.x) > 50)

       {

               my.pan += 3 * time_step;

               wait (1);

       }

       snd_play (gotammo_wav, 80, 0);

       set (my, INVISIBLE);

       current_ammo += 20; // use your own value here

       wait (-1);

       ent_remove (my);

}

 

 

Q: How can I program a character that changes its size every time when it is shot?

A: Here's an example:

 

function got_shot()

{

       if (you == player) {return;} // don't react if the player touches the entity

       my.scale_x += 0.1;

       my.scale_y = my.scale_x;

       my.scale_z = my.scale_x;

}

 

action my_entity()

{

       set (my, POLYGON);

       my.emask |= (ENABLE_IMPACT | ENABLE_SHOOT); // shoot using real bullets or c_trace

       my.event = got_shot; // the event function runs every time when the entity is hit

}

 

 

Q: I have encoded an animation to avi (Indeo 5.1) but when I play it in 3DGS it doesn't look good (bad image, sometimes bad frame rate). How can I play good quality videos using media_play?

A: If you need speed, try to use 16 bit color videos whenever it is possible. Then, don't use huge resolutions and big frame rates for your movies. You can run movies of 800x600 pixels at 15 fps on a decent computer without any trouble; I did that a few minutes ago. Finally, don't use movie formats that require additional codecs; wmv files are supported by all the computers that run Windows since 2001.

 

 

Q: How can I destroy a little part of a wall using a bullet?

A: Create your wall (or only the part that needs to be destroyed) out of several small mdl or wmb entities, and then attach them the following action.

 

STRING* explosion_pcx = "explo+7.pcx";

 

function animated_explosion()

{

       wait (1);

         set (my, PASSABLE);

         my.ambient = 100;

       while (my.frame < 7)

       {

               my.frame += 1 * time_step;

            wait (1);

       }

       ent_remove(my);

}

 

function destroy_wall()

{

       if (you == player) {return;} // don't react if the player touches the wall

       my.event = NULL; // don't react to other bullets from now on

       set (my, INVISIBLE);

       set (my, PASSABLE);

       ent_create (explosion_pcx, my.x, animated_explosion);

       wait (-2); // wait until the explosion frames are played

       ent_remove (my);

}

 

action wall_piece()

{

       my.emask |= (ENABLE_IMPACT | ENABLE_SHOOT); // shoot with real bullets or c_trace

       my.event = destroy_wall;

}

 

 

Q: How can I activate an "if" branch only if the model is, for example, "model.mdl"?

A: Here's an example:

 

STRING* temp_str = "                    ";

 

// attach the action below to several entities; only the one that is named "model.mdl" will rotate

action test_me()

{

       str_for_entfile(temp_str, my);

       if (str_cmpi(temp_str, "model.mdl")) // the entity is named model.mdl?

       {

               while (1) // then let the rotation begin!

               {

                       my.pan += 4 * time_step;

                       wait (1);

               }

       }

}

 

 

Q: How can we program a 3rd person camera that stays behind the player and rotates around the character if the player doesn't move for a while?

A: Here's an example.

 

action player1()

{

       var movement_speed = 10; // movement speed

       var anim_percentage;

       var standing_still = 0;

       var camangle;

       VECTOR temp;

       VECTOR temp2;

       player = my; // I'm the player

       while (1)

       {

               if((!key_w) && (!key_s) && (!key_a) && (!key_d)) // the player isn't moving at all?

     {

                       standing_still += time_step / 8; // play with 8 until you get the proper pausing interval

                       ent_animate(my, "stand", anim_percentage, ANM_CYCLE); // and play the "stand" animation

               }

     else // the player is moving?

               {

                       camangle = 0; // reset the camera rotation angle

                       standing_still = 0; // reset standing_still

                       ent_animate(my, "walk", anim_percentage, ANM_CYCLE); // and play the "walk" animation

               }

               anim_percentage += 5 * time_step; // 5 = animation speed

               if (standing_still > 10) // the player didn't move at all lately? Then rotate the camera around it

               {

                       camera.x = player.x - 250 * cos(camangle);

                       camera.y = player.y - 250 * sin(camangle);

                       camangle += 0.5 * time_step;

                       vec_set(temp2.x, my.x);

                       vec_sub(temp2.x, camera.x);

                       vec_to_angle(camera.pan, temp2);

               }

               else // the player has changed its position recently?

               {

                       camera.x = player.x - 250 * cos(player.pan);

                       camera.y = player.y - 250 * sin(player.pan);

                       camera.pan = player.pan; // the camera and the player have the same pan angle

               }

               camera.z = player.z + 150; // place the camera above the player, play with this value

               camera.tilt = -25;

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

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

               temp.z = 0;

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

               wait (1);

       }

}

 

 

Q: How do you use FXA_Mirror? It doesn't work anymore! I am using A7 professional.

A: Create a map entity; set the "mirror" flag for the face that is supposed to be the mirror and "none" for all the other faces. Then, cut a hole in the floor and place then mirror entity inside it. Finally, attach your map entity the action below.

 

VIEW* fxa_mirror_view =

{                

       layer = 10;

}

 

action FXA_Mirror() // attach this action to your map entity

{

       // initialize camera portal for realtime reflections

       camera.portal = fxa_mirror_view;

       set (fxa_mirror_view, NOSHADOW); // suppress shadows in the mirror

       set (fxa_mirror_view, PORTALCLIP); // clip at portal plane

       while(1)

       {

               proc_mode = PROC_LATE; // place it at the end of the function list - the camera must be moved before

               fxa_mirror_view.genius = camera.genius;

               fxa_mirror_view.aspect = -camera.aspect;        // flip the image upside down

               fxa_mirror_view.arc = camera.arc;

               fxa_mirror_view.x = camera.x;

               fxa_mirror_view.y = camera.y;

               fxa_mirror_view.z = 2 * camera.portal_z - camera.z; // move the camera at its mirror position

               fxa_mirror_view.pan = camera.pan;

               fxa_mirror_view.tilt = -camera.tilt; // flip the vertical camera angle

               fxa_mirror_view.roll = -camera.roll;

               wait(1);

       }

}

 

aum72_faq1

 

 

Q: My npc is supposed to rotate towards the player and say its line once, but only when it is looking directly at the player. How can I do that?

A: There you go.

 

action my_npc() // attach this action to your npc

{

       // make sure that the player action includes this line of code: "player = my;"

       VECTOR temp;

       var rot_speed = 20; // 20 gives the rotation speed, play with it

       var npc_angle;

       var new_line = 0;

       while (1)

       {

               if (vec_dist (my.x, player.x) < 300)

               {

                       vec_set(temp.x, player.x);

                       vec_sub(temp.x, my.x);

                       vec_to_angle(npc_angle, temp.x);

                       if (ang(npc_angle - my.pan) < -3)

                       {

                               my.pan -= rot_speed * time_step;

                       }

                       else

                       {

                               if (abs(ang(npc_angle - my.pan)) > 3)

                          {

                                       my.pan += rot_speed * time_step;

                               }

                               else // the npc faces the player here, so let's play its line

                               {

                                       if (!new_line) // the line hasn't been played yet?

                                       {

                                               new_line = 1;

                                               beep();

                                               // plays your line here only once

                                       }

                               }

                       }

               }

               wait (1);

       }

}