Questions from the forum

Top  Previous  Next

Q: How can I create a vertical door that opens when the player approaches it and closes by itself when the player moves away from it?

A: Here's a fully working example.

 

SOUND* doorsound_wav = "doorsound.wav";

 

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

{        

       var movement_speed = 20;

       VECTOR temp;

       set (my, INVISIBLE);

       player = my;

       while (1)

       {

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

               vec_set (temp.x, my.x);

               temp.z -= 10000;

               temp.z = 0;

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

               camera.x = my.x;

               camera.y = my.y;

               camera.z = my.z + 50;

               camera.pan = my.pan;

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

               wait (1);

       }

}

 

action my_door()

{

       var init_z;

       init_z = my.z;

       while (!player) {wait (1);} // make sure to add the "player = my;" line of code to your player action

       while (1)

       {

               while (vec_dist (player.x, my.x) > 200) {wait (1);} // play with 200

               snd_play (doorsound_wav, 100, 0);

               // this loop opens the door

               while (my.z < init_z + 100) // the door will move upwards 100 quants

               {

                       my.z += 15 * time_step; // 15 = door upwards movement speed

                       wait (1);

               }

            // this section closes the door

               while (vec_dist (player.x, my.x) < 300) {wait (1);} // wait until the player moves away, use a bigger value here

               snd_play (doorsound_wav, 100, 0);

               while (my.z > init_z) // the door will move downwards now

               {

                       my.z -= 10 * time_step; // 10 = door downwards movement speed

                       wait (1);

               }

               my.z = init_z; // set the door z coordinate at the exact, initial height value

       }

}

 

 

Q: How do I create timed doors that open when the player approaches them and close after a few seconds, no matter if the player is near them or far away?

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

 

SOUND* doorsound_wav = "doorsound.wav";

 

action timed_door()

{

       var init_z;

       var waiting_time = 5;

       init_z = my.z;

       while (!player) {wait (1);} // make sure to add the "player = my;" line of code to your player action

       while (1)

       {

               while (vec_dist (player.x, my.x) > 200) {wait (1);} // play with 200

               snd_play (doorsound_wav, 100, 0);

               while (my.z < init_z + 100) // the door will move upwards 100 quants

               {

                       my.z += 15 * time_step; // 15 = door upwards movement speed

                       wait (1);

               }

            // this section closes the door after 5 seconds, play with waiting_time to edit it

            my.skill62 = 0;

               while (my.skill62 < waiting_time)

               {

                       my.skill62 += time_step / 16;

                       wait (1);

               }

               snd_play (doorsound_wav, 100, 0);

               while (my.z > init_z) // the door will move downwards now

               {

                       my.z -= 10 * time_step; // 10 = door downwards movement speed

                       wait (1);

               }

               my.z = init_z; // set the door z coordinate at the exact, initial height value

               // now wait until the player has moved away from the door before allowing it to open the door once again

               while (vec_dist (player.x, my.x) < 250) {wait (1);} // play with 250, make it bigger than 200

       }

}

 

 

Q: How do you create a door that locks the player in a room until it defeats an enemy?

A: Take a look at the snippet below.

 

var enemy_health = 100;

 

SOUND* doorsound_wav = "doorsound.wav";

SOUND* hit_wav = "hit.wav";

 

BMAP* pointer_tga = "pointer.tga";

 

function mouse_startup()

       mouse_mode = 2;

       mouse_map = pointer_tga;

       while (1)

       

               vec_set(mouse_pos, mouse_cursor);

               wait(1);

       }

}

 

function got_clicked()

{

       if (event_type == EVENT_CLICK)

       {

               enemy_health -= 50; // click the enemy twice to kill it        

               snd_play (hit_wav, 100, 0);

       }

}

 

action my_enemy()

{

       var idle_percentage = 0;

       var death_percentage = 0;

       my.emask |= ENABLE_CLICK; // the enemy is sensitive to mouse clicks

         my.event = got_clicked; // and runs this function when it is clicked using the left mouse button

       while (enemy_health > 0)

       {

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

               idle_percentage += 3 * time_step; // "3" controls the "stand" animation speed

               wait (1);

       }

       // the enemy is dead here

       my.event = NULL; // so let's set its event to NULL

       while (death_percentage < 100) // the loop runs until the "death" animation percentage reaches 100%       

       {

               ent_animate(my, "death", death_percentage, NULL); // play the "die" animation only once

               death_percentage += 3 * time_step; // "3" controls the "death" animation speed

               wait (1);

       }

       set (my, PASSABLE); // allow the player to pass through the corpse now        

}

 

action wicked_door()

{

       var init_z;

       init_z = my.z;

       while (!player) {wait (1);} // make sure to add the "player = my;" line of code to your player action

       while (1)

       {

               while (vec_dist (player.x, my.x) > 200) {wait (1);} // play with 200

               snd_play (doorsound_wav, 100, 0);

               // this loop opens the door

               while (my.z < init_z + 100) // the door will move upwards 100 quants

               {

                       my.z += 15 * time_step; // 15 = door upwards movement speed

                       wait (1);

               }

            // this section closes the door

               while (vec_dist (player.x, my.x) < 300) {wait (1);} // wait until the player moves away, use a bigger value here

               snd_play (doorsound_wav, 100, 0);

               while (my.z > init_z) // the door will move downwards now

               {

                       my.z -= 10 * time_step; // 10 = door downwards movement speed

                       wait (1);

               }

               my.z = init_z; // set the door z coordinate at the exact, initial height value

               while (enemy_health > 0) {wait (1);} // don't allow the door to open until the enemy is defeated

       }

}

 

 

Q: How do you create a door trigger? A piece of geometry is placed in the level, made invisible, and given a trigger behavior. Then a door skill is set to match. When the player approaches the trigger, the door opens and stays open.

A: There you go.

 

SOUND* doorsound_wav = "doorsound.wav";

 

// set skill1 to the desired value using Wed

action triggered_door()

{

       var door_closed = 1;

       // wait until the player model is loaded, add "player = my;" to your player action

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

       if (my.skill1 == 0) // if the player forgets to set skill1 for the door in Wed

               my.skill1 = 2; // give it a default value of 2

       while (door_closed == 1)

       {

               // scan around, trying to detect triggers

               c_scan(my.x, my.pan, vector(360, 180, 1000), IGNORE_ME | SCAN_ENTS | SCAN_FLAG2); // play with 1000

               // the trigger will be detected if it is closer than 1,000 quants to the trigger entity

               if (you) // an entity was detected?

               {

                    if (you.skill1 == my.skill1) // detected the proper trigger?

                       {

                               if (vec_dist(player.x, you.x) < 100) // and the player is close to the trigger?

                               {

                                       snd_play (doorsound_wav, 100, 0);

                                       my.skill44 = my.z;

                                       while (my.z < my.skill44 + 100) // the door will move upwards 100 quants

                                       {

                                               my.z += 15 * time_step; // 15 = door upwards movement speed

                                               wait (1);

                                       }

                                       return; // get out of this function - the door is open now

                               }

                       }

               }

               wait (3); // no need to use precious cpu resources with this action

       }

}

 

// set skill1 to the desired value using Wed

action door_trigger()

{

       set (my, INVISIBLE | PASSABLE);        

       set (my, FLAG2); // set flag2 for all the triggers

       if (my.skill1 == 0) // if the player forgets to set skill1 for the trigger in Wed

               my.skill1 = 2; // give it a default value of 2

       while (1)

       {

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

               {

                       // the player has come close to the door, so the door should open!                

                       my.skill99 = 1;

               }

               wait (1);

       }

}

 

 

Q: What is an easy way of counting how many entities of a certain type (for example guard.mdl) are present in a level?

A: Here's an easy method.

 

var counter = 0;

 

STRING* temp_str = "                    ";

 

function entities_startup()

{

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

       while (you)

       {

               str_for_entfile(temp_str, you);

               if (str_cmpi(temp_str, "guard.mdl")) // use the name of the desired entity here

                       counter += 1;       

               you = ent_next(you); // move on to the next entity

       }

}

 

PANEL* counter_pan =

{

       layer = 15;

       digits(10, 10, "Number of entities: %.f", *, 1, counter);

       flags = SHOW;

}

 

 

Q: My friend is trying to play my game on his laptop and because the resolution needs to be smaller than 1024x768 it automatically switches to 800x600. How do I stop it from doing that?

A: Modify your game, making it detect the native screen resolution of the laptop - here's how:

 

STRING* yourlevel_wmb = "yourlevel.wmb";

 

function main()

{

       video_set(sys_metrics(0), sys_metrics(1), 32, 1); // detect and use the best screen resolution

       level_load (yourlevel_wmb);

      // put the rest of your main function code here

}

 

Q: Would it slow down my game to run several c_scan instructions at once? Say like 25 enemies and the player.

A: I ran some tests on an older computer (Core 2 Duo CPU @2.66GHz, 3GB of Ram, Ati Radeon 5770) using the function below, which runs a s_scan instruction each frame.

 

action c_scan_test()

{

       while (1)

       {

               c_scan(my.x, my.pan, vector(360, 180, 1000), IGNORE_ME | SCAN_ENTS | SCAN_FLAG2); // play with 1000

               wait (1); // no need to use precious cpu resources with this action

       }

}

 

The test models have 786 vertices each, and all of them were visible at the same time. Here are the results:

- 1 model -> fps = 512

- 10 models -> fps = 512

- 25 models -> fps = 512

- 100 models -> fps = 512

- 300 models -> fps = 340

 

I realize that the code for your 25 enemies will include more than a c_scan instruction, of course, but the results of this test show clearly that your 25 enemies won't slow down the engine at all. Oh, and here's a shot with those 300 soldiers.

 

aum110_faq1

 

 

Q: I have a 2048 * 2048 pixels texture. Is it better to scale it down to 0.250 of its original size (512 * 512 pixels) in WED, or to simply scale down the original texture in my image editor?

A: Always set the proper texture size in your image editor; this way, your texture will use less video memory. Not only that, but the quality of the resized image should be better if you use a high quality image editor like Adobe Photoshop, etc.

 

 

Q: How do you restart a project? In other words, how to you execute the main script again, in order to retry a mission if the player has lost its life?

A: Here's a fully functional example with a player that can lose its life. When this happens, you can restart the level.

 

var players_health = 100;

 

function kill_player()

{

       if (event_type == EVENT_IMPACT || event_type == EVENT_ENTITY) // the player has collided with an entity?

       {

               if (you.skill20 == 1234) // and that entity was the actual enemy?

                       players_health = 0; // then kill the player!                

       }

}

 

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

{        

       var movement_speed = 20;

       VECTOR temp;

       set (my, INVISIBLE);

       player = my;

       my.emask |= (ENABLE_IMPACT | ENABLE_ENTITY);

       my.event = kill_player;

       while (players_health > 0)

       {

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

               vec_set (temp.x, my.x);

               temp.z -= 10000;

               temp.z = 0;

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

               camera.x = my.x;

               camera.y = my.y;

               camera.z = my.z + 50;

               camera.pan = my.pan;

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

               wait (1);

       }

       camera.ambient = -100; // time to darken the screen

       // the player is dead here - press the "R" key to restart the level

       while (!key_r) {wait (1);} // wait until the player presses the "R" key

       while (key_r) {wait (1);} // wait until the player releases the "R" key        

       //        we need to restore player's health value before starting the level again

       // the variable values aren't loaded after a level_load instruction - that's why we have to set them manually

       players_health = 100;

       camera.ambient = 0; // let's get rid of the screen darkness

       // now we can run function main, so that the level is loaded again

       main(); // run function main again        

}

 

action my_enemy() // simply run into the enemy to kill the player

{

       my.skill20 = 1234; // uniquely identify this enemy

}

 

 

Q: How can you check if a specific game save file exists before loading?

A: Here's a simplified function taken from the RPG template.

 

function load_game() // trying to load the rpg1.sav file here

{

       if (game_load("rpg", 1) <= 0) // couldn't load the game?

       {

               error("Game Loading Error!"); // then let's display an error message!

       }

       else // the game was loaded successfully here

       {

               clear_panels(); // the game was loaded, so create a function that hides the load menu panels

       }                        

}