Questions from the forum

Top  Previous  Next

Q: I am looking for a solution that allows me to check if certain entities are visible in the current camera view.

A: Here's an example.

 

var object_id = -1;

var visible_objects[100]; // displays up to 100 visible objects

var total_visible;

 

action visible_or_not() // attach this action to all the object that need to be tracked

{

       // put the rest of your code here        

       // ..............................

 

       VECTOR my_pos[3];

       object_id += 1;

       my.skill99 = object_id; // don't use skill99 for something else

       while (1)

       {

               // put the rest of your code here

               // ..............................

 

               vec_set(my_pos.x, my.x);

               if (vec_to_screen(my_pos.x, camera)) // if this entity is visible on the screen

               {

                       visible_objects[my.skill99] = 1;

               }

               else // the entity isn't visible on the screen

               {

                       visible_objects[my.skill99] = 0;                        

               }                        

               wait (1);

       }        

}

 

function total_startup()

{

       var i;

       while (1)

       {

               total_visible = 0;

               for(i = 0; i < 100; i++)

               {

                       total_visible += visible_objects[i];        

               }

               wait (1);

       }

}

 

PANEL* entities_pan =

{

       layer = 15;

       digits(20, 20, 3, *, 1, total_visible);

       flags = visible;

}

 

aum79_faq1

 

 

Q: What is the best way to make a simple lives system? It should start with three lives and every time player's health hits zero, one of the lives goes down and the game reloads. If no lives are left, the game should jump to a game over panel.

A: There you go.

 

PANEL* gameover_pan =

{

       layer = 15;

       pos_x = 300;

       pos_y = 200;

       bmap = "gameover.pcx";

}

 

action player_destroyer() // kills the player if the player comes too close

{

       set(my, PASSABLE);

       while (1)

       {        

               if (player) // the player exists?

               {

                       if (vec_dist(player.x, my.x) < 100) // the player has come close to the destroyer object?

                       {

                               player.skill99 -= 5 * time_step; // then decrease player's health

                       }

               }

               wait (1);

       }

}

 

function players_action()

{

       VECTOR temp;

       var movement_speed = 10; // movement speed

       set (my, INVISIBLE); // 1st person player

       my.skill99 = 100; // player's skill99 stores its health

       while (my.skill99 > 0)

       {

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

       }

       player = NULL;

       wait (1);

       ent_remove(my); // remove the player if it is dead

}

 

function init_startup()

{

       wait (-1); // wait until the level is loaded

       player = ent_create("guard.mdl", vector (10, 10, 70), players_action); // first life

       while (player) {wait (1);} // wait until the player disappears from the level

       wait (3);

       player = ent_create("guard.mdl", vector (10, 10, 70), players_action); // create it again (that's the second life)

       while (player) {wait (1);} // wait until the player disappears from the level

       wait (3);

       player = ent_create("guard.mdl", vector (10, 10, 70), players_action); // create it again (that's the third life)

       wait (3);

       while (player) {wait (1);} // wait until the player disappears from the level

       // the game is over here, so let's display the "Game Over" panel

       set(gameover_pan, VISIBLE);

       while (key_any) {wait (1);} // wait until the keys are released

       while (!key_any) {wait (1);} // wait until any key is pressed

       sys_exit(NULL); // and now let's shut down the engine

}

 

 

Q: I would like to display several parameters for my entities on the screen (for debugging purposes). Is there an easy way to do that?

A: Here's an example.

 

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 debug_startup()

{

       while (1)

       {

               if(mouse_ent) // the mouse touches an entity?

                       watched = mouse_ent; // then display information about that entity!

               wait (1);

       }

}

 

aum79_faq2

 

 

Q: How can you jump with a character in lite-C? The character should jump only when he is on the floor.

A: Here's an improved version of my code from Aum52's workshop.

 

action player_code()

{

       VECTOR temp[3];

       VECTOR movement_speed[3]; // player's movement speed

       var anim_percentage; // animation percentage

       var jump_percentage; // animation percentage for jumping

       var distance_to_ground; // the distance between player's origin and the ground

       var jump_height;

       var reached_height;

       player = my; // I'm the player

       while (1)

       {

               my.pan += 6 * (key_a - key_d) * time_step; // rotate the player using the "A" and "D" keys

               vec_set (temp.x, my.x); // copy player's position to temp

               temp.z -= 10000; // set temp.z 10000 quants below player's origin

               distance_to_ground = c_trace (my.x, temp.x, IGNORE_ME | USE_BOX);

               movement_speed.x = 5 * (key_w - key_s) * time_step; // move the player using "W" and "S"

               movement_speed.y = 0; // don't move sideways

               if (key_space && !reached_height)

               {

                       jump_height = minv(40, jump_height + 5 * time_step); // 40 sets the height, 5 sets the ascending speed

                       if (jump_height == 40) // reached the maximum height? Then start descending!

                       {

                               reached_height = 1;

                               jump_height = maxv(0, jump_height - 5 * time_step); // 5 sets the falling speed

                       }

               }

               else // space isn't pressed anymore?

               {

                       jump_height = maxv(0, jump_height - 3 * time_step); // use a smaller falling speed (3) for smaller jumps

                       if (!jump_height && !key_space) // the player has touched the ground?

                       {

                               reached_height = 0; // then allow it to jump again

                       }

               }

               movement_speed.z = -(distance_to_ground - 17) + jump_height; // 17 = experimental value

            movement_speed.z = maxv(-35 * time_step, movement_speed.z); // 35 = falling speed

               c_move (my, movement_speed.x, nullvector, GLIDE); // move the player

            if (!jump_height) // the player isn't jumping?

            {

                    if (!key_w && !key_s) // the player isn't moving?

                       {

                               ent_animate(my, "stand", anim_percentage, ANM_CYCLE); // play the "stand" animation

                       }

                       else // the player is moving?

                       {

                               ent_animate(my, "walk", anim_percentage, ANM_CYCLE); // play the "walk" animation

                       }

                       anim_percentage += 5 * time_step; // 5 = animation speed

                       jump_percentage = 0; // always start jumping with the first frame

               }

            else // the player is jumping

            {

                    jump_percentage += 5 * time_step; // 5 = jump animation speed

                       ent_animate(my, "jump", jump_percentage, ANM_CYCLE); // play the "jump" animation

               }

 

               // camera code

               camera.x = player.x - 250 * cos(player.pan);

               camera.y = player.y - 250 * sin(player.pan); // use the same value (250) here

               camera.z = player.z + 150; // place the camera above the player, play with this value

               camera.tilt = -20; // look down at the player

               camera.pan = player.pan;

               wait (1);

       }

}

 

 

Q: How can I create a convincing police siren sound effect that can be attached to my police cars?

A: Try several sound effects and the following snippet.

 

SOUND* siren_wav = "siren.wav";

 

action police_car()

{

       // put the rest of your car code in here

       // .....................................

 

       var police_handle;

       var freq_range;

       var speed = 30; // sets the speed of the sound effect

       police_handle = ent_playloop (my, siren_wav, 400);

       while (1)

       {

               // freq_range ranges from 30 to 370% (play with 200 and 190)

               freq_range = 200 - 170 * sin(total_ticks * speed);

               snd_tune (police_handle, 0, freq_range, 0); // change the frequency from 10% to 300%

               wait (1);

               

               // put the rest of your car code in here

               // .....................................

       }

}

 

 

Q: Is it possible to adjust the range of a dynamic light using the mouse wheel?

A: Sure. Just move the mouse over the light bulb entity and rotate the wheel.

 

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 adjust_light()

{

       while (event_type != EVENT_RELEASE)

       {

               my.lightrange += 0.5 * mickey.z * time_step;

               my.lightrange = clamp(my.lightrange, 0, 1000); // limit the light range to 0...1000

               wait (1);

       }

}

 

action light_bulb() // attach this action to all the light bulbs

{

       vec_set(my.blue, vector(255, 255, 255)); // generate white light

       my.lightrange = 300; // default light range value

       my.emask |= (ENABLE_TOUCH | EVENT_RELEASE);

       my.event = adjust_light;

}

 

 

Q: I have placed invisible blocks in my level but the player is just going straight through them. Why could this be?

A: Even a player that's driven by a c_move instruction will pass through invisible level blocks, but not through invisible map entities. Add a block to an empty level, save it and build it as a separate wmb entity. Place this entity in the level and check its "Invisible" checkbox; the player won't be able to pass though it.

 

 

Q: I want to create an avatar of the player on screen, filming his face during combat. Is this possible?

A: Create a tga bitmap that has a cutout with a size that's identical to the size of the avatar camera, and then use the code below.

 

VIEW* avatar_cam =

{

       pos_x = 120;

       pos_y = 48;

       size_x = 158;

       size_y = 119;

       layer = 10;

       flags = VISIBLE;

}

 

PANEL* hud_pan =

{

       layer = 5;

       pos_x = 0;

       pos_y = 0;

       bmap = "hud.tga";

       flags = VISIBLE;

}

 

function avatarcam_startup()

{

       while (!player) {wait (1);}

       while (1)

       {

               vec_set (avatar_cam.x, vector (20, 0, 35)); // play with these values

               vec_rotate (avatar_cam.x, player.pan);

               vec_add (avatar_cam.x, player.x);

               avatar_cam.pan = player.pan + 180; // make avatar_cam look at the player

               wait (1);

       }

}

 

aum79_faq3

 

 

Q: I'm trying to make a panel that shows me how much health I have. I want to make something like the Zelda panels.

A: There you go.

 

BMAP* hearts_tga = "hearts.tga"; // that's a stripe that contains 5 small hearts

BMAP* bigheart_tga = "bigheart.tga"; // that's the big heart that appears over the stripe

 

PANEL* hearts_pan =

{

       layer = 15;

       pos_x = 0;

       pos_y = 20;

       bmap = hearts_tga;

       flags = visible;

}

 

PANEL* bigheart_pan =

{

       layer = 25; // this panel appear above one of the other panels

       pos_x = 200;

       pos_y = 15;

       bmap = bigheart_tga;

       flags = visible;

}

 

function health_startup()

{

       while (!player) {wait (1);} // wait until the player is loaded in the level

       player.skill10 = 100;

       while (1)

       {

               if (player.skill10 > 90) // player's health is stored inside its skill10 in this example

                       bigheart_pan.pos_x = 200;

               if ((player.skill10 > 70) && (player.skill10 <= 90))

                       bigheart_pan.pos_x = 150;

               if ((player.skill10 > 50) && (player.skill10 <= 70))

                       bigheart_pan.pos_x = 100;

               if ((player.skill10 > 30) && (player.skill10 <= 50))

                       bigheart_pan.pos_x = 100;

               if ((player.skill10 > 10) && (player.skill10 <= 30))

                       bigheart_pan.pos_x = 50;

               if ((player.skill10 <= 10))

                       bigheart_pan.pos_x = 0;

               wait (1);

       }                

}

 

aum79_faq5

 

 

Q: If I place a model in the level and I set its polygon flag, the collision works as expected; however, if I create the same model using ent_create and I set its polygon flag in the function that drives it, the bounding box doesn't change as expected. How can I fix that?

A: You need to use c_setminmax(my) if you want to ent_create your models and have them use polygon-based collision.

 

function guards_function()

{

       c_setminmax(my);

       // put the rest of your code here

       // ..............................

}

 

function create_startup()

{

       wait (-3); // wait until the level is loaded

       ent_create("guard.mdl", vector(100, 100, 50), guards_function);

}

 

aum79_faq4