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