Questions from the forum |
Top Previous Next |
Q: I'd like my camera to tilt when the player is going through a slope on a mountain. Can you help? A: Use the snippet below:
action players_code() // attach this action to your player { var movement_speed = 10; // movement speed VECTOR temp; ANGLE temp_angles; set (my, INVISIBLE); // 1st person player player = my; // I'm the player while (1) { my.pan -= 7 * mouse_force.x * time_step; camera.x = my.x; camera.y = my.y; camera.z = my.z + 50 + 1.1 * sin(my.skill44); // play with 50 and 1.1 camera.pan = my.pan; camera.tilt = player.tilt; 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) - 2; // play with 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); temp_angles.tilt = 0; temp_angles.roll = 0; temp_angles.pan = -my.pan; vec_rotate(normal, temp_angles); temp_angles.tilt = -asin(normal.x); temp_angles.roll = -asin(normal.y); my.tilt += 0.1 * ang(temp_angles.tilt - my.tilt); // play with 0.1 my.roll += 0.1 * ang(temp_angles.roll - my.roll); // play with 0.1 wait (1); } }
Q: How can I trap the mouse pointer in a rectangular area located in the center of the screen? A: Use this example:
// trap the mouse in an area that has 200x100 pixels and is located in the center of the screen var area_x = 200; var area_y = 100;
BMAP* pointer_tga = "pointer.tga";
function mouse_startup() { VECTOR temp1_pos, temp2_pos; mouse_mode = 2; mouse_map = pointer_tga; while (1) { vec_set(mouse_pos, mouse_cursor); temp1_pos.x = (screen_size.x - area_x) / 2; temp2_pos.x = (screen_size.x + area_x) / 2; mouse_pos.x = clamp(mouse_pos.x, temp1_pos.x, temp2_pos.x); temp1_pos.y = (screen_size.y - area_y) / 2; temp2_pos.y = (screen_size.y + area_y) / 2; mouse_pos.y = clamp(mouse_pos.y, temp1_pos.y, temp2_pos.y); wait(1); } }
Q: How can I make it so that an entity moves for a specified number of seconds when I press a button? A: There you go:
action moving_puppet() { var movement_time = 5; // move for 5 seconds when the "M" key is pressed var movement_speed = 2; // movement speed VECTOR temp; while (1) { while (!key_m) {wait (1);} // wait until the player presses the "M" key on the keyboard while (key_m) {wait (1);} // wait until the player releases the "M" key while (movement_time > 0) { movement_time -= time_step / 16; // decrease 1 from movement_time each second my.skill1 += 4 * time_step; // 4 gives the animation speed vec_set (temp.x, my.x); // trace 10,000 quants below the entity temp.z -= 10000; temp.z = -c_trace (my.x, temp.x, IGNORE_ME | IGNORE_PASSABLE | USE_BOX) + 20; // play with 20 // move the entity with the speed given by movement_speed along the direction pointed by its pan angle c_move (my, vector(movement_speed, 0, temp.z), nullvector, IGNORE_PASSABLE | GLIDE); // animate the model using its "walk" animation in a loop ent_animate(my, "walk", my.skill1, ANM_CYCLE); wait (1); } // the walking is over here, so let's switch to the "stand" animation ent_animate(my, "stand", 0, 0); movement_time = 5; // prepare for a new movement session } }
Q: How can I make a sound play once as soon as a comparison instruction is successful? A: Here's an example:
STRING* password_str = "iliketoeatalot"; STRING* input_str = "#20"; // this empty string can store up to 20 characters STRING* messages_str = "30";
SOUND* passok_wav = "passok.wav";
TEXT* input_txt = { pos_x = 300; pos_y = 400; string(input_str); }
TEXT* messages_txt = { pos_x = 300; pos_y = 300; string(messages_str); }
function password_startup() { wait (-3); // wait until the game starts, etc // the following loop will run until the correct password is typed in while (1) { str_cpy(messages_str, "Type in the correct password"); messages_txt.flags |= SHOW; // show the intro message wait (-3); // for 3 seconds messages_txt.flags &= ~SHOW; // now hide the intro message input_txt.flags |= SHOW; // show the input str_cpy(input_str, "#20"); // reset the string (if needed) inkey(input_str); if (str_cmpi(input_str, password_str) == 1) // the correct password was typed in? { snd_play(passok_wav, 90, 0); break; // get out of the loop } } // the correct password was typed in here str_cpy(messages_str, "Logged into the system"); messages_txt.flags |= SHOW; // show the outro message wait (-5); // for 5 seconds messages_txt.flags &= ~SHOW; // now hide the outro message sys_exit(NULL); // shut down the engine }
Q: I want to attach the camera of my game to an object (sphere, etc) so that the camera has a physical behaviour and doesn't go through walls anymore. A: Use this piece of code:
VECTOR movement_force;
action solid_camera() // attach this action to a sphere model { set (my, INVISIBLE); // no need to see the sphere model while (1) { // use the W and S keys to move forward / backward, 5 gives the movement speed movement_force.x = 5 * (key_w - key_s); // use the A and D keys to move sideways, 3 gives the movement speed movement_force.y = 3 * (key_a - key_d); // don't allow the z value of movement_force to change movement_force.z = 0; my.pan -= 3 * mouse_force.x * time_step; // 3 = horizontal rotation speed my.tilt -= 3 * mouse_force.y * time_step; // 3 = vertical rotation speed // now move the sphere in the direction given by its pan and tilt angles c_move (my, movement_force.x, nullvector, IGNORE_PASSABLE | GLIDE); // the camera will inherit the same position and angles with the sphere vec_set (camera.x, my.x); camera.pan = my.pan; camera.tilt = my.tilt; wait(1); } }
Q: For my tests I'd need a snippet which, with the press of a button, writes camera's coordinates to an ini file. Then, with the press of another button, the camera would load those coordinates from the ini file. A: There you go:
var file_handle;
VECTOR vSpeed, vAngularSpeed, vForce, vMove;
function camera_startup() // this camera can pass through walls { while (1) { vForce.x = - 5 * (key_force.x + mouse_force.x); // pan angle vForce.y = 5 * (key_force.y + mouse_force.y); // tilt angle vForce.z = 0; // no changes for the roll angle vec_accelerate (vMove, vAngularSpeed, vForce, 0.8); vec_add (camera.pan, vMove); vForce.x = 6 * (key_w - key_s); // use W and S to move forward vForce.y = 6 * (key_a - key_d); // use A and D to move sideways vForce.z = 6 * (key_home - key_end); // use Home and End to move upwards / downwards vec_accelerate (vMove, vSpeed, vForce, 0.5); vec_rotate (vMove, camera.pan); vec_add (camera.x, vMove); wait(1); } }
function save_position() { file_handle = file_open_write ("camera.ini"); // save the data to the camera.ini file file_var_write (file_handle, camera.x); // save x, y, z, pan, tilt, roll file_var_write (file_handle, camera.y); file_var_write (file_handle, camera.z); file_var_write (file_handle, camera.pan); file_var_write (file_handle, camera.tilt); file_var_write (file_handle, camera.roll); file_close (file_handle); // close the file, we won't be needing it from now on }
function load_position() { file_handle = file_open_read("camera.ini"); // try to open ini file if (file_handle) // the file exists? (the player could press "2" without pressing "1" first) { camera.x = file_var_read (file_handle); // then restore the x, y, z, pan, tilt, roll camera.y = file_var_read (file_handle); camera.z = file_var_read (file_handle); camera.pan = file_var_read (file_handle); camera.tilt = file_var_read (file_handle); camera.roll = file_var_read (file_handle); } }
function init_startup() { on_1 = save_position; // press "1" to save the camera coordinates on_2 = load_position; // press "2" to load the camera coordinates }
Q: I'd like to be able to pick, move and drop an object using the mouse cursor. A: Here's an improved version of my code from Aum52's faq that runs fine with A7 / lite-C:
BMAP* pointer_tga = "pointer.tga";
VECTOR temp;
function mouse_startup() { mouse_mode = 2; mouse_map = pointer_tga; while (1) { vec_set(mouse_pos, mouse_cursor); wait(1); } }
function pick_or_drop() { wait (1); my.skill1 += 1; if ((my.skill1 % 2) == 1) // clicked the object? { while (mouse_left) {wait (1);} // wait until the player releases the left mouse button while (!mouse_left) // move the object until the player presses the mouse button again { temp.x = mouse_cursor.x; temp.y = mouse_cursor.y; temp.z = 200; // move the object 200 quants below the camera, play with this value vec_for_screen(temp.x, camera); vec_set (my.x, temp.x); set (my, PASSABLE); wait (1); } } else // drop the object here { vec_set (temp.x, my.x); temp.z -= 3000; // trace up to 5,000 quants below the player // make sure to drop the object on the ground my.z -= c_trace (my.x, temp.x, IGNORE_ME + IGNORE_SPRITES + IGNORE_MODELS + USE_BOX); reset (my, PASSABLE); } }
action click_and_move() { my.skill1 = 0; my.emask |= ENABLE_CLICK; my.event = pick_or_drop; }
Q: I have developed a small project where the player has to guess a number from 1 to 9. I can enter the code using the keyboard numbers from 1 to 9 but nothing happens when pressing the numerical keypad numbers. I have the num_lock on. Why does this not work? A: The numerical keypad numbers have other scan codes; use the snippet below to detect the names and the scan codes for the keys on the keyboard. I suggest that you should always use scan codes for your projects.
STRING* temp_str = "#10";
TEXT* header_txt = { pos_x = 180; pos_y = 5; string("Key name ------- Scan code"); flags = SHOW; }
TEXT* keypressed_txt = { pos_x = 200; pos_y = 20; string(temp_str); flags = SHOW; }
PANEL* keypressed_pan = { layer = 15; digits(300, 20, 3, * , 1, key_lastpressed); flags = SHOW; }
function keys_startup() { while (1) { if (key_any) { beep(); str_for_key(temp_str, key_lastpressed); // convert the scan code to the key name } while (key_any) {wait (1);} // wait until all the keys are released wait (1); } }
Q: I'd like to have a dynamic light that can be picked up by pressing space near it and follows the player. The light should always be on, even after a level changing instruction. How can I do that? A: The actions attached to entities stop running after a level_load instruction; nevertheless, the variables keep their values and can be used to recreate what's needed, just like this:
var got_flashlight = 0;
SOUND* gotflashlight_wav = "gotflashlight.wav";
ENTITY* flashlight;
function move_flashlight() { set (my, PASSABLE | INVISIBLE | CAST); my.lightrange = 350; my.red = 200; my.green = 200; my.blue = 160; while (player) // this loop will run for as long as the player pointer exists { vec_set(my.x, player.x); wait (1); } }
action my_flashlight() { while (!player) {wait (1);} while (1) { if (vec_dist(player.x, my.x) < 70) { if (key_space) { snd_play(gotflashlight_wav, 50, 0); flashlight = ent_create("flashlight.mdl", player.x, move_flashlight); got_flashlight = 1; wait (2); break; // get out of this loop } } wait (1); } set(my, PASSABLE | INVISIBLE); // hide the flashlight model on the floor while (vec_dist(player.x, my.x) < 300) {wait (1);} // wait until the player moves away // and then remove the flashlight model from the floor (give the sound effect enough time to play) ent_remove (my); }
action players_code() // attach this action to your player model in all the levels { var movement_speed = 10; // movement speed VECTOR temp; set (my, INVISIBLE); // 1st person player player = my; // I'm the player
// this section recreates the flashlight (if needed) if (got_flashlight == 1) // the flashlight was picked up in a previous level? { flashlight = ent_create("flashlight.mdl", player.x, move_flashlight); // the recreate it! } // end of the section that recreates the flashlight (if needed)
while (1) { my.pan -= 7 * mouse_force.x * time_step; camera.x = my.x; camera.y = my.y; camera.z = my.z + 50 + 1.1 * sin(my.skill44); // play with 50 and 1.1 camera.pan = my.pan; camera.tilt = player.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) - 2; // play with 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); wait (1); } }
action lever_changer() // attach this action to your level changing entity { while (!player) {wait (1);} // wait until the player model is loaded // wait until the player comes closer than 100 quants to the level changing entity while (vec_dist (player.x, my.x) > 100) {wait (1);} // now load the new level; the flashlight will be recreated if it was picked up in a previous level level_load("level2.wmb"); }
Q: I'd like to create a mini math quiz with a text like 5 x 2 that appears on the screen. The users enter an answer and press Enter in order to move on to the following question. If they are wrong their score is decreased. A: Use this example as a base for your code:
var score = 0, number1, number2, my_result;
STRING* question_str = "#20"; STRING* answer_str = "#5"; STRING* temp_str = "#5";
SOUND* goodjob_wav = "goodjob.wav"; SOUND* missed_wav = "missed.wav";
TEXT* question_txt = { pos_x = 200; pos_y = 200; string(question_str); flags = SHOW; }
TEXT* answer_txt = { pos_x = 300; pos_y = 200; string(answer_str); flags = SHOW; }
PANEL* score_pan = { layer = 15; digits(700, 20, 4, * , 1, score); flags = SHOW; }
function init_startup() { random_seed(0); // generate a random sequence of numbers wait (-3); // wait until the level is loaded while (1) { str_cpy(question_str, "What is "); number1 = integer(random(10) + 1); // number 1 ranges from 1 to 10 str_for_num(temp_str, number1); // convert number1 to a string str_cat(question_str, temp_str); // add number1 to question_str str_cat(question_str, " x "); number2 = integer(random(10) + 1); // number 2 ranges from 1 to 10 str_for_num(temp_str, number2); // convert number1 to a string str_cat(question_str, temp_str); // add number2 to question_str wait (1); str_cat(question_str, " = "); str_cpy(answer_str, "#5"); inkey(answer_str); my_result = str_to_num(answer_str); if (my_result == (number1 * number2)) // the player has got the correct answer? { score += 1; // then increase the score snd_play(goodjob_wav, 60, 0); } else { snd_play(missed_wav, 60, 0); score -= 1; // then decrease the score score = maxv(0, score); // don't allow negative score values } wait (-3); // wait for 5 seconds before generating a new exercise } }
|