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

       }

}

 

aum82_faq1

 

aum82_faq2

 

aum82_faq3

 

 

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

}

 

aum82_faq4

 

 

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

}

 

aum82_faq5

 

 

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

       }

}