Questions from the forum

Top  Previous  Next

Q: How do you trigger a dramatic music loop when the player enters a certain area and fade it out when it leaves the area?

A: Use the following snippet.

 

var loop_handle;

var loop_volume = 100;

 

action music_trigger()

{

       set (my, INVISIBLE | PASSABLE);

       while (!player) {wait (1);} // wait until the player model is loaded

       while (1)

       {

               // the player has come closer than 150 quants to the target area?

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

               {

                       if (!media_playing(loop_handle)) // the loop isn't being played already?        

                               loop_handle = media_loop("dramatic.mp3", NULL, 100); // then play the dramatic sound effect

               }

               else // the player is away from the target area

               {

                       if (media_playing(loop_handle)) // the loop is being played?

                       {

                               while (loop_volume > 5) // then let's decrease its volume!

                               {

                                       loop_volume -= 1 * time_step; // loop fading speed

                                       media_tune(loop_handle, loop_volume, 100, 0);

                                       wait (1);

                               }

                               media_stop(loop_handle); // stop the loop for good

                               loop_volume = 100; // restore the initial loop volume

                       }

               }

               wait (1);

       }

}

 

 

Q: How do I manipulate all the entities (trees) that have been placed in Wed and have their skill1 set to 199? I know that I can create individual pointers and attach an action to each tree, but that would be overkill...

A: Here's an example that goes through all the Wed entities, and then doubles scale_z for the ones that have their skill1 set to 199.

 

var index = 0;

var wed_entities[1000]; // stores the IDs for up to 1000 Wed entities

 

ENTITY* my_tree;

 

function trees_startup()

{

       wait (-2); // wait until the entire level is loaded

       you = ent_next(NULL); // retrieve the first Wed entity

       // loop until all the Wed entities handles are stored inside the "wed_entities" array

       while(you)

       {

         wed_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

       }

       // all the Wed entities have been retrieved here, so do what you want with them

       // we'll just wait for a second, and then set scale_z to 2 for the ones that have their skill1 set to 199

       wait (-1);

       index = 0; // reset the index

       // get the first Wed entity and assign its address the "my_tree" pointer

       my_tree = ptr_for_handle(wed_entities[index]);

       while (my_tree != NULL) // loop for as long as there are still valid Wed entities in the level

       {

               if (my_tree.skill1 == 199)

               {

                       // do whatever you need with your special entities here

                       my_tree.scale_z = 2;

               }

               index += 1; // move on to the next array element        

               my_tree = ptr_for_handle(wed_entities[index]);

       }

       // No more Wed entities have been found, so the loop has ended here

}

 

 

Q: How do I create a home cinema room that plays a small movie in a loop?

A: Here's an example that includes a bonus feature: the movie will only run when the player is visible, thus saving precious resources.

 

var video_handle;

 

// attach this action to a sprite that will be used for your home cinema screen

action cinema_screen()

{

       // wait until the player entity is loaded

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

       // the movie will only loop if the player is visible, to save precious CPU resources

       while (1)

       {

               c_trace(my.x, player.x, IGNORE_ME);

               // the player needs to have a "player = me;" line of code inside its action

               if (you == player) // the player is visible?

               {

                       if (!media_playing(video_handle)) // the loop isn't playing at the moment?

                       {

                               video_handle = media_loop("movie.wmv", bmap_for_entity (my, 0), 100); // then start it right away!

                       }

               }

               else // the player isn't visible, so there's no need to waste precious CPU resources and memory

               {

                       media_stop(video_handle);                

               }

               wait (1);

       }      

}

 

 

Q: How do I make my enemies change their skins to their more and more bruised versions as they get hit?

A: Use this snippet as a base for your code; move the player close to the enemy several times to see its skin changing.

 

function decrease_health()

{

       // make sure that player's action includes a "player = me;" line of code

       if ((event_type == EVENT_IMPACT) && (you == player))

       {

               my.skill1 -= 20;

               my.event = NULL; // don't allow the player to trigger several events at once

       }

       // wait until the player has moved away from the enemy before changing the enemy skin again

       while (vec_dist(player.x, my.x) < 200) {wait (1);}

       my.event = decrease_health;

}

 

action my_enemy()

{

       my.skill1 = 100; // the entity starts with 100 health points

       my.emask |= ENABLE_IMPACT;

       my.event = decrease_health;

       my.skill2 = 0;

       while (my.skill1 > 0)

       {

               if (my.skill1 == 80)

                       ent_morphskin(my, "bruised1.pcx"); // the first bruised skin

               if (my.skill1 == 60)

                       ent_morphskin(my, "bruised2.pcx"); // the second bruised skin

               if (my.skill1 == 40)

                       ent_morphskin(my, "bruised3.pcx"); // the third bruised skin

               if (my.skill1 == 20)

                       ent_morphskin(my, "bruised4.pcx"); // the fourth bruised skin                        

               my.skill22 += 4 * time_step; // 4 gives the "stand" animation speed

               ent_animate(my, "stand", my.skill22, ANM_CYCLE);

               wait (1);

       }

       my.skill22 = 0;

       while (my.skill22 < 100)

       {

               my.skill22 += 3 * time_step;

               ent_animate(my, "death", my.skill22, NULL);

               wait (1);

       }

       set (my, PASSABLE); // the corpse is passable now

}

 

 

Q: How can I measure player's reaction speed after a sound is being played (in an accurate manner)?

A: There you go.

 

var wait_time;

var seconds;

var milliseconds;

 

SOUND* ready_wav = "ready.wav"; // this sounds is triggered at t = 0

 

function reaction_startup()

{

       while (1)

       {

               wait_time = -random(5) - 3;

               wait (wait_time);

               snd_play(ready_wav, 100, 0);        

               milliseconds = 0;

               seconds = 0;

               timer();

               while (!key_space) // wait until the player presses the space key to measure its reaction time

               {

                       milliseconds += (timer() / 1000);

                       if (milliseconds > 1000)

                       {

                               milliseconds -= 1000;

                               seconds += 1;

                       }

                       wait (1);

               }

               while (key_space) {wait (1);}

       }

}

 

PANEL* time_pan =

{

       layer = 15;

       digits(200, 20, 2, *, 1, seconds);

       digits(220, 20, 3, *, 1, milliseconds);

       flags = SHOW;

}

 

 

Q: How do I code a bunch of spiders that are constantly chasing the player?

A: Here's a snippet that does what you want.

 

action deadly_spiders() // attach this action to your spider models

{

       while (!player) {wait (1);} // wait until the player entity is loaded

       VECTOR temp, temp_angle;

       var spider_speed = 8;

       var covered_dist;

       while (1)

       {

           vec_set (temp.x, my.x); // trace 1000 quants below the spider

               temp.z -= 1000;

               // place the spider 10 quants above the floor, play with 10

               temp.z = -c_trace (my.x, temp.x, IGNORE_ME | IGNORE_PASSABLE | USE_BOX) + 10;

               temp.x = spider_speed * time_step;

               temp.y = 0;

               ent_animate(my, "run", my.skill10, ANM_CYCLE);

               my.skill10 += 15 * time_step; // 15 gives the "run" animation speed

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

               if (covered_dist < 0.1) // the spider is stuck?

               {

                    my.pan += 90 - random(180); // then add a random angle to its pan angle

                       my.skill99 = 0;

                       while (my.skill99 < 10) // walk in the new direction for 10 frames, play with 10

                       {

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

                               my.skill99 += 1;

                               wait (1);

                       }                           

               }

               else // the spider can move again? Then rotate it towards the player once more!

               {

                    vec_set(temp_angle, player.x);

                       vec_sub(temp_angle, my.x);

                       vec_to_angle(my.pan, temp_angle);

                       my.tilt = 0;

               }

               if (vec_dist(player.x, my.x) < 150) // the spider has come really close to the player?

               {

                    while (vec_dist(player.x, my.x) < 150)

                       {

                            // don't forget to add some code that damages the player here!

                               ent_animate(my, "attack", my.skill10, ANM_CYCLE);        

                               my.skill10 += 10 * time_step; // 10 gives the "attack" animation speed

                               wait (1);

                       }

               }

               wait (1);

       }

}

 

 

Q: How do I password-protect my game? Only the players who know the password should be able to play it!

A: There you go.

 

STRING* password_str = "hacker1234";

STRING* input_str = "#20"; // this empty string can store up to 20 characters

STRING* output_str = "30"; // this empty string can store up to 30 characters

 

TEXT* input_txt =

{

       pos_x = 300;

       pos_y = 100;

       string(input_str);

}

 

TEXT* output_txt =

{

       pos_x = 300;

       pos_y = 100;

       string(output_str);

}

 

function password_startup()

{

       wait (-3); // wait until the game level loads

       freeze_mode = 1; // pause all the entity and particle functions

       str_cpy(output_str, "Type in the password to play:");

       output_txt.flags |= SHOW; // show the message

       wait (-3); // for 3 seconds

       output_txt.flags &= ~SHOW; // now hide the  message

       input_txt.flags |= SHOW; // show the input

       inkey(input_str);

       if (str_cmpi(input_str, password_str) == 1) // the correct password was typed in?

       {

               input_txt.flags &= ~SHOW; // now hide the  message

               str_cpy(output_str, "Access granted!");

               output_txt.flags |= SHOW; // show the message

               wait (-3); // for 3 seconds

               output_txt.flags &= ~SHOW; // now hide the  message

               freeze_mode = 0; // unfreeze the game

       }

       else

       {

               input_txt.flags &= ~SHOW; // now hide the  message

               str_cpy(output_str, "Wrong password!");

               output_txt.flags |= SHOW; // show the message

               wait (-3); // for 3 seconds

               output_txt.flags &= ~SHOW; // now hide the  message

               sys_exit(NULL);

       }                        

}

 

 

Q: I'd need some code for a smart (creepy?) NPC that follows the player, but only when he isn't looking. Once that the NPC comes in sight, it should stop and play its "stand" animation, but switch to "walk" and move towards the player fast when he isn't looking at the NPC.

A: Here's a smart NPC example that does what you want.

 

action smart_npc()

{       

       var walk_speed = 10;

       var anim_percentage = 0;

       VECTOR temp_angle;

       while (!player) {wait (1);} // wait until the player model is loaded

       while (1)

       {

               vec_set(temp_angle, player.x);

               vec_sub(temp_angle, my.x);

               vec_to_angle(my.pan, temp_angle);        // rotate towards the player at all times

               // the npc is visible? Then play its "stand" animation!

               if (!(my.eflags & CLIPPED))

               {

                    ent_animate(my, "stand", anim_percentage, NULL);                               

                       anim_percentage += 2 * time_step;

                       anim_percentage %= 100;

               }

            else // the player can't see the npc? Then play its "walk" animation and move it towards the player!

            {

                    if (vec_dist(player.x, my.x) > 200) // stop when the npc has come closer than 200 quants to the player

                    {

                               c_move (my, vector(10 * time_step, 0, 0), nullvector, GLIDE);     

                            ent_animate(my, "walk", anim_percentage, NULL);                               

                               anim_percentage += 2 * time_step;

                               anim_percentage %= 100;

                       }

               }

               wait (1);

       }

}

 

 

Q: How do I create a zoom in/out system? I am using a top view player/camera combo and I have tried to use camera.arc to do it, but I don't like the resulting fisheye lens effect. Is there another way?

A: Sure thing! You can zoom in and out by changing the distance from the camera to the player. Here's an example.

 

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

{        

       var movement_speed = 20;

       var camera_height = 300;

       var walk_percentage;

       VECTOR temp;

       player = my;

       while (1)

       {                        

               my.pan -= 7 * mouse_force.x * time_step; // use the mouse to rotate the player around

               vec_set (temp.x, my.x);

               temp.z -= 10000;

               temp.z = 0;

               temp.z = -c_trace (my.x, temp.x, IGNORE_ME | IGNORE_PASSABLE) - 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);

               if (key_w + key_s + key_a + key_d) // one of the movement keys is pressed? Then play the walking animation as well!

               {

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

                       walk_percentage += 5 * time_step;

               }

          camera.tilt = -90; // the camera will look downwards all the time

         camera.x = player.x; //the player and the camera have the same x and y position

     camera.y = player.y;

     // the camera is placed 300 quants above player's origin initially

     // make sure to create a level that's high enough for the camera even when you zoom out to the maximum value

     camera.z = player.z + camera_height;

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

     if (mouse_left) // use the left mouse button to zoom in

     {

            camera_height -= 10 * time_step;

     }

     if (mouse_right) // use the right mouse button to zoom out

     {

            camera_height += 10 * time_step;

     }

               camera_height = clamp(camera_height, 200, 500); // keep the camera height in the 200...500 quants range

               wait (1);

       }

}