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.
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 } }
|