Questions from the forum |
Top Previous Next |
Q: I really like the collision camera from Morrowing. I tried converting it to lite-c but I'm having problems. Can you help? A: Here's the lite-C player and camera code snippet.
var camera_distance = 200; // distance from the player to the camera in 3rd person mode var camera_height = 240; // distance from the origin of the player to the camera (on the z axis) var distance_traced; // distance that is return by a trace instruction var camera_mode; // starts in 3rd person mode, changes to 1 for first person var stop_player = 0; // set it to 1 to stop the player until stop_player is set to 0 again var player_speed = 15;
VECTOR temporary_distance;
SOUND* step_wav = "step.wav";
function avoid_obstacles(); function first_person_camera(); function third_person_camera();
#define shield skill1 #define mace skill2 #define bodyarmor skill3 #define flare skill4 #define strength skill10 // use these skills to store player's abilities #define experience skill11 #define mana skill12 #define health skill40 // use skill40 to store health for the player and its enemies
action player1() { on_f1 = first_person_camera; on_f3 = third_person_camera; VECTOR temp; VECTOR trace_coords; player = my; // I'm the player set (my, TRANSLUCENT); // the player is transparent my.alpha = 100; // but opaque if the camera doesn't run into obstacles my.skill41 = camera_height; // and its height my.skill42 = camera_distance; // we store the distance to the camera camera_mode = 3; // the game starts with the camera in 3rd person mode my.health = 100; while (my.health > 0) { while (stop_player == 1) {wait (1);} // player's pan is controlled by the mouse and the "A" and "D" keys player.pan -= 10 * mouse_force.x * time_step - 1.5 * (key_a - key_d); camera.x = player.x - camera_distance * cos(player.pan); // keep the camera behind the player camera.y = player.y - camera_distance * sin(player.pan); // at the distance given by camera_distance camera.z = player.z + camera_height + 0.8 * sin(my.skill46 * 3.6); // and above the player camera.pan = player.pan; // the camera has the same pan angle with the player camera.tilt += 7 * mouse_force.y * time_step; // and can tilt freely camera_distance = minv(maxv(camera_distance, 5), 500); // camera_distance can have values between 5 and 500 if (key_w + key_s > 0) // if the player is walking { ent_animate(my, "walk", my.skill46, ANM_CYCLE); // play its "walk" frames animation // the animation speed increases when the player presses the "shift" key my.skill46 += 5 * (1 + key_shift * 0.7) * time_step; my.skill46 %= 100; // loop the animation } else // if the player is standing { my.skill47 = 0; // reset the skill that stores the distance needed for the step sound (not really needed) ent_animate(my, "stand", my.skill48, ANM_CYCLE); // play the "stand" frames animation my.skill48 += 2 * time_step; // "stand" animation speed my.skill48 %= 100; // loop animation } if (camera_mode == 3) // if we are in 3rd person mode { avoid_obstacles(); // run the function that avoids camera collisions with the relief } vec_set (temp, my.x); // trace 10,000 quants below the player temp.z -= 10000; temp.z = - c_trace (my.x, temp, IGNORE_ME | IGNORE_PASSABLE | USE_BOX); // and adjust its height accordingly, placing its feet on the ground // allow the player to move using the "W" and "S" keys; the speed increases to 200% if the player presses the "shift" key temp.x = player_speed * (key_w - key_s) * (1 + 1 * key_shift) * time_step; temp.y = 0; my.skill47 += c_move (my, temp, nullvector, IGNORE_PASSABLE); if (my.skill47 > 250) // play with 250 (here we've got a step sound every 50 quants) { snd_play(step_wav, 15, 0); my.skill47 = 0; } wait (1); } // the player is dead here my.skill40 = 0; // use the same skill40 (health) to control the "death" animation while (my.skill40 < 90) // don't play all the animation frames because the result doesn't look too good { ent_animate(my, "death", my.skill40, NULL); // play the "death" animation my.skill40 += 2 * time_step; // "death" animation speed camera.roll -= 0.3 * time_step; camera.tilt += 0.8 * time_step; wait (1); } set (my, PASSABLE); // the corpse will be passable from now on }
function avoid_obstacles() { vec_set (temporary_distance.x, camera.x); temporary_distance.z -= 50; // sets a position closer to the feet of the player; 50 = experimental value distance_traced = c_trace (player.x, temporary_distance.x, IGNORE_ME | IGNORE_PASSABLE); // trace between the player and temporary_distance if (distance_traced == 0) // no obstacles on the way? { my.alpha = minv(100, my.alpha + 3 * time_step); // then increase player's alpha up to 100 if (player.alpha == 100) { reset(player, TRANSLUCENT); } else { set(player, TRANSLUCENT); } if (camera_distance < my.skill40) // if the camera got closer to the player { camera_distance += 1; // restore the initial camera_distance slowly } } else // obstacles encountered? { distance_traced -= 2; // then bring the camera 2 quants closer to the player! my.alpha = (distance_traced / (my.skill40 + 1)) * 100; // decrease player's alpha; don't allow a division by zero camera.x = player.x - distance_traced * cos(camera.pan); // place the camera behind the player camera.y = player.y - distance_traced * sin(camera.pan); // at the new distance given by distance_traced } }
function first_person_camera() // press "F1" to run this function { camera_distance = 0; // place the camera at player's position camera_height = 150; // play with this value set (player, INVISIBLE); // make the player model invisible camera_mode = 1; // set the camera_mode variable to 1st person }
function third_person_camera() // press "F3" to run this function { camera_height = player.skill41; // restore the height camera_distance = player.skill42; // restore the distance from the player to the camera reset (player, INVISIBLE); // and show the player camera_mode = 3; // set the camera_mode variable to 3rd person }
Q: How do I get a mirror to be on a wall and see yourself (not a floor reflection)? A: Use the code below and these tips:
1) The mirror entity shouldn't be rotated at all; create it and place it in the level using the same orientation. 2) The mirror entity should have its faces set to "flat", excepting the reflecting face, which should be set to "mirror". 3) The mirror code changes depending on the orientation of the mirror entity; my example allows you to place a mirror on the southern wall in Wed's top view. 4) The back of the mirror should have enough empty space; what you see in the mirror is actually created behind the mirror. 5) The level blocks faces that act as a frame for the mirror should be set to none.
VIEW* mirror = { layer = 10; }
function mirror_startup() { while (!player) {wait (1);} camera.portal = mirror; set (mirror, NOSHADOW); // suppress shadows in the mirror set (mirror, NOPARTICLE); // suppress particles in the mirror set (mirror, PORTALCLIP); // clip at portal plane while (1) { proc_kill(4); mirror.genius = camera.genius; mirror.aspect = camera.aspect; mirror.arc = -camera.arc; mirror.x = camera.x; mirror.y = camera.portal_y - (abs(camera.portal_y - camera.y)); mirror.z = camera.z; mirror.pan = -camera.pan; mirror.tilt = camera.tilt; mirror.roll = camera.roll; wait(1); } }
Q: How can I make a model transparent if the player is behind it (less than 60% of it is visible)? I need to make the buildings transparent if the player steps behind them. A: Use this example as a base for your code.
var temp_building;
ENTITY* building_ent;
action my_player() // attach this action to your player { var movement_speed = 10; // movement speed VECTOR temp; VECTOR trace_pos; player = my; // I'm the player set(my, FLAG2); while (1) { my.pan -= 7 * mouse_force.x * time_step; temp.x = movement_speed * (key_w - key_s) * time_step; temp.y = 0; temp.z = 0; my.pan += 4 * (key_a - key_d) * time_step; c_move (my, temp.x, nullvector, IGNORE_PASSABLE | GLIDE); if (key_w + key_s > 0) // if the player is walking { ent_animate(my, "walk", my.skill46, ANM_CYCLE); // play its "walk" frames animation my.skill46 += 5 * time_step; my.skill46 %= 100; // loop the animation } else // if the player is standing { ent_animate(my, "stand", my.skill48, ANM_CYCLE); // play the "stand" frames animation my.skill48 += 2 * time_step; // "stand" animation speed my.skill48 %= 100; // loop the animation } vec_set(trace_pos.x, my.x); trace_pos.z += 20; // play with this value c_trace(trace_pos.x, camera.x, IGNORE_FLAG2 | USE_BOX); if (you) { temp_building = handle(you); set(you, TRANSLUCENT); you.alpha = 60; my.skill99 = 1; } else { if (my.skill99 == 1) // building_ent exists? { building_ent = ptr_for_handle(temp_building); reset (building_ent, TRANSLUCENT); } } wait (1); } }
function camera_startup() // camera code sample { VECTOR temp; vec_set(camera.x, vector(0, 0, 1000)); while (!player) {wait (1);} while (1) { vec_set(temp, player.x); vec_sub(temp, camera.x); vec_to_angle(camera.pan, temp); wait (1); } }
Q: I'd like to read some names from a text file and sort them alphabetically. How can I do that? A: Here's an example.
FONT* arial_font = "Arial#20";
TEXT* names_txt = { pos_x = 30; pos_y = 50; font(arial_font); strings = 30; // stores up to 30 names string = " "; // 20 characters string = " "; // 20 characters string = " "; // 20 characters string = " "; // 20 characters string = " "; // 20 characters string = " "; // 20 characters string = " "; // 20 characters string = " "; // 20 characters string = " "; // 20 characters string = " "; // 20 characters string = " "; // 20 characters string = " "; // 20 characters string = " "; // 20 characters string = " "; // 20 characters string = " "; // 20 characters string = " "; // 20 characters string = " "; // 20 characters string = " "; // 20 characters string = " "; // 20 characters string = " "; // 20 characters string = " "; // 20 characters string = " "; // 20 characters string = " "; // 20 characters string = " "; // 20 characters string = " "; // 20 characters string = " "; // 20 characters string = " "; // 20 characters string = " "; // 20 characters string = " "; // 20 characters string = " "; // 20 characters flags = visible; }
function opendata_startup() { var file_handle; var read_result = 0; var i = 0; while (!player) {wait (1);} file_handle = file_open_read("names.txt"); while (read_result != -1) // read the data until the end of the file is reached { read_result = file_str_read(file_handle, (names_txt.pstring)[i]); i += 1; } str_cpy((names_txt.pstring)[i-1], " "); // reset the last string // all the names are read from the file and stored in the text strings here file_close(file_handle); while (!key_n) {wait (1);} // press the "N" key to sort the names while (key_n) {wait (1);} txt_sort(names_txt); // the names are sorted here }
Q: How can I create a timer that runs faster that sys_seconds? I'd like to have a clock that runs a day in 20...30 minutes. A: Use the code below; it's a clock that runs a day in 24 minutes.
STRING* clock_str = " "; // hh:mm ss = 8 chars STRING* temp_str = " "; // 2 chars storing temporary data
FONT* arial_font = "Arial#20";
TEXT* clock_text = { layer = 20; pos_x = 40; pos_y = 30; font(arial_font); string(clock_str); flags = visible; }
function clock_startup() { // limit the frame rate to 60 fps, 1 second for our clock = 1 / 60 real seconds fps_max = 60; // this clock runs 60 times faster than normal var my_seconds = 0; var my_minutes = 0; var my_hours = 0; var my_days = 0; // not used, but might come in handy someday while (1) { my_seconds += 1; if (my_seconds == 60) // a full minute was reached (in fact, a second has passed)? { my_seconds = 0; my_minutes += 1; } if (my_minutes == 60) // a full hour was reached (in fact, a minute has passed)? { my_minutes = 0; my_hours += 1; } if (my_hours == 24) // a full day has was reached (in fact, 24 minutes have passed)? { my_seconds = 0; my_hours = 0; my_days += 1; } str_for_num(clock_str, my_hours); str_cat(clock_str, ":"); // add : to create hh:mm if (my_minutes < 10) // add a "0" if the minutes are displayed with a digit str_cat(clock_str, "0"); str_for_num(temp_str, my_minutes); str_cat(clock_str, temp_str); wait (1); } }
Q: After starting my game, I can hear the music that I've placed in the level. As soon as I leave the area, the music stops abruptly. What is happening here? A: Don't add your music as a sound in Wed; you should only place static sound effects that way. Copy and paste the code below in your script to add music to your game.
var sound_volume = 50; // controls the sound volume
function music_startup() { while (!player) {wait (1);} // wait until the player model is loaded // replace my_music.wav with the name of your song media_handle = media_loop("my_music.wav", NULL, sound_volume); }
Q: Is it possible to disable the window border (so that my panel is the border) and use the exit button designed by me? A: Use this example.
BMAP* pointer_tga = "pointer.tga"; BMAP* quit1_pcx = "quit1.pcx"; BMAP* quit2_pcx = "quit2.pcx";
STRING* test_wmb = "test.wmb";
function quit_game();
PANEL* my_pan = { layer = 15; pos_x = 0; pos_y = 0; bmap = "mypanel.tga"; // the frame panel button = 780, 0, quit2_pcx, quit1_pcx, quit2_pcx, quit_game, null, null; flags = visible; }
void main() { fps_max = 70; video_mode = 7; // run in 800x600 pixels video_depth = 32; // 32 bit mode video_screen = 2; // start in window mode video_window(NULL, NULL, 1, NULL); level_load (test_wmb); }
function mouse_startup() { mouse_mode = 2; mouse_map = pointer_tga; while (1) { vec_set(mouse_pos, mouse_cursor); wait(1); } }
function quit_game() { sys_exit(NULL); }
Q: I'm trying to implement a simple sky-cube in a lite-C loaded level but I just can't seem to get it to work. A: Here's an example:
STRING* test_wmb = "test.wmb";
void main() { fps_max = 70; video_mode = 7; // run in 800x600 pixels video_depth = 32; // 32 bit mode video_screen = 1; // start in full screen mode level_load (test_wmb); wait (3); ent_createlayer("skycube+6.tga", SKY | CUBE | VISIBLE , 1); }
Q: I need the code for a level loading progress indicator in my game. Can you help? A: Use the code below.
var loading_percentage;
STRING* test_wmb = "test.wmb";
FONT* arial_font = "Arial#20";
function loading_percent(factor) { loading_percentage = factor; loading_percentage = minv(100, loading_percentage); // loaded: 101 / 100 would look bad on the screen }
PANEL* time_pan = { layer = 15; digits (300, 300, "Loaded: %.f / 100", arial_font, 1, loading_percentage); flags = visible; }
void main() { fps_max = 70; video_mode = 7; // run in 800x600 pixels video_depth = 32; // 32 bit mode video_screen = 1; // start in full screen mode on_level = loading_percent; level_load (test_wmb); while (loading_percentage < 100) {wait (1);} // the level is loaded here reset (time_pan, VISIBLE); // so let's hide the panel }
Q: I'd like to know how is it possible to make my character visible to the camera even if there's a block between the camera and the character, blocking the view. A: There you go.
action my_player() // attach this action to your player { var movement_speed = 10; // movement speed VECTOR temp; player = my; // I'm the player while (1) { my.pan -= 7 * mouse_force.x * time_step; temp.x = movement_speed * (key_w - key_s) * time_step; temp.y = 0; temp.z = 0; my.pan += 4 * (key_a - key_d) * time_step; c_move (my, temp.x, nullvector, IGNORE_PASSABLE | GLIDE); if (key_w + key_s > 0) // if the player is walking { ent_animate(my, "walk", my.skill46, ANM_CYCLE); // play its "walk" frames animation my.skill46 += 5 * time_step; my.skill46 %= 100; // loop the animation } else // if the player is standing { ent_animate(my, "stand", my.skill48, ANM_CYCLE); // play the "stand" frames animation my.skill48 += 2 * time_step; // "stand" animation speed my.skill48 %= 100; // loop the animation } if (c_trace(camera.x, player.x, USE_BOX)) // the player isn't visible? { set(player, ZNEAR); } else { reset(player, ZNEAR); } wait (1); } }
|