Questions from the forum

Top  Previous  Next

Q: Is it possible to create a high precision timer for my racing game?

A: Use the snippet below:

 

FONT* arial_font = "Arial#20";

 

var hours;

var minutes;

var seconds;

var milliseconds;

 

function timer_startup()

{

       while (1)

       {

               milliseconds += (timer() / 1000);

               if (milliseconds > 1000)

               {

                       milliseconds -= 1000;

                       seconds += 1;

               }

               if(seconds > 59)

            {

                    minutes += 1;

                       seconds -= 60;

                       if(minutes >= 59)

                       {

                               hours += 1;

                          minutes -= 60;

                       }

               }

               wait (1);

       }

}

 

PANEL* timer_pan =

{

       layer = 15;

       digits(100, 20, 2, arial_font , 1, hours);

       digits(150, 20, 2, arial_font , 1, minutes);

       digits(200, 20, 2, arial_font , 1, seconds);

       digits(250, 20, 3, arial_font , 1, milliseconds);

       flags = SHOW;

}

 

 

aum84_faq1

 

 

Q: Does anyone know a way to make an entity appear at a spot on the level where a user clicks?

A: Use this example:

 

BMAP* pointer_tga = "pointer.tga";

 

STRING* target_mdl = "dot.mdl";

 

function adjust_target()

{

       my.z += 5; // play with the target entity here        

}

 

function create_target()

{

       VECTOR pos1, pos2;

       pos1.x = mouse_pos.x;

       pos1.y = mouse_pos.y;

       pos1.z = 0;

       vec_for_screen (pos1, camera);

       pos2.x = mouse_pos.x;

       pos2.y = mouse_pos.y;

       pos2.z = 20000; // use a big value here

       vec_for_screen (pos2, camera);

       c_trace (pos1.x, pos2.x, IGNORE_PASSABLE); // now "target" holds the coordinates of the hit point

       ent_create (target_mdl, target, adjust_target); // create the entity at the "target" position

}

 

function mouse_startup()

       on_mouse_left = create_target; // create a target entity when the player presses the left mouse button

       mouse_mode = 2;

       mouse_map = pointer_tga;

       while (1)

       

               vec_set(mouse_pos, mouse_cursor);

               wait(1);

       }

}

 

 

Q: Is there any other way to detect entity collision other than using event_type? I'd like to track a collision only with a particular door.

A: You can use event_type to check if an entity has collided only with a particular door, just like this:

 

ENTITY* my_door;

 

action special_door() // attach this action to your door

{

       my_door = my;

}

 

function detect_door()

{

       if (you == my_door)

       {

               beep(); // beep twice only if the player has collided with the particular door

               beep();

       }

}

 

action players_code() // attach this action to your player

{

       var movement_speed = 10; // movement speed

       VECTOR temp;

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

       player = my; // I'm the player

       my.emask |= (ENABLE_IMPACT | ENABLE_ENTITY);

       my.event = detect_door;

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

       }

}

 

 

Q: How can I make an entity move to the specified location?

A: Here's an example that moves an NPC character towards its goal using primitive, and yet fully functional obstacle avoidance code.

 

ENTITY* goal;

 

action npc_goal() // attach this action to the destination entity

{

       goal = my;        

}

 

action goal_tracker() // attach this action to your NPC character

{

       while (!goal) {wait (1);} // wait until the goal entity is loaded

       VECTOR temp, temp_angle;

       var npc_speed = 5;

       var covered_dist, i;

       while (1)

       {

               my.skill10 += 6 * time_step; // 6 gives the animation speed

               vec_set (temp.x, my.x); // trace 10,000 quants below the npc entity

               temp.z -= 10000;

               temp.z = -c_trace (my.x, temp.x, IGNORE_ME | IGNORE_PASSABLE | USE_BOX) + 20; // play with 20

               temp.x = npc_speed * time_step;

               temp.y = 0;

               ent_animate(my, "walk", my.skill10, ANM_CYCLE);

               covered_dist = c_move (my, temp.x, nullvector, IGNORE_PASSABLE | GLIDE);

               if (covered_dist < 0.1) // the npc is stuck?

               {

                       my.pan += 90 - random(180); // then add a random angle to its pan angle

                       i = 0;

                       while (i < 10) // walk in the new direction for 10 frames, play with 10

                       {

                               c_move (my, temp.x, nullvector, IGNORE_PASSABLE | GLIDE);

                               ent_animate(my, "walk", my.skill10, ANM_CYCLE);

                               i++;

                               wait (1);

                       }                                

               }

               else // the npc can move? Then rotate it towards the goal again!

               {

                       vec_set(temp_angle, goal.x);

                       vec_sub(temp_angle, my.x);

                       vec_to_angle(my.pan, temp_angle);

                       my.tilt = 0;

               }

               if (vec_dist(goal.x, my.x) < 50) // the npc has found the goal entity?

                       break; // then get out of the while loop!

               wait (1);

       }

       // the goal was reached here

       ent_animate(my, "stand", 0, 0); // switch to "stand"

}

 

aum84_faq2

 

 

Q: I have a car model; how do I make it follow the direction of the path smoothly?

A: Here's a simplified version of the code used in my car demo.

 

#define car_speed skill55

 

SOUND* aiskids1_wav = "aiskids1.wav";

SOUND* carai1_wav = "carai1.wav";

 

ENTITY* dummy1;

ENTITY* carai1_dummy;

ENTITY* carai1;

 

action car_ai()

{

       carai1 = my;

       var distance = 0;

       var previous_pan;

       var following_pan;

       var min_speed = 20;

       var max_speed;

       var carai_engine;

       var engine_factor;

       var dist_z;

       var skids_once = 0;

       VECTOR last_pos[3];

       VECTOR direction[3];

       VECTOR temp[3];

       max_speed = 35;

       dummy1 = ent_create(NULL, nullvector, NULL);

       // create another (carai1_dummy) dummy entity that will move on the path

       // the ai car will use the same x, y, pan, tilt and roll with the carai1_dummy entity that moves on the path

       // but will compute its own z using c_trace; this way, the nodes don't have to be place precisely above the ground

       carai1_dummy = ent_create(NULL, nullvector, NULL);

       path_set(dummy1, "path_001"); // make sure to name your path this way

       engine_factor = 2 + random(2); // start with a random engine sound frecquency each and every time

       carai_engine = ent_playloop(carai1, carai1_wav, 300); // start playing the car ai engine sound in a loop

       while(1)

       {

               previous_pan = carai1.pan;

               // place the carai1 entity on the path

               path_spline(dummy1, carai1_dummy.x, distance);

               distance += dummy1.car_speed * time_step;

               // let carai1 look ahead

               vec_diff(direction, carai1_dummy.x, last_pos);

               vec_to_angle(carai1_dummy.pan, direction);

               vec_set(last_pos, carai1_dummy.x);

               carai1.pan = carai1_dummy.pan;

               carai1.tilt = carai1_dummy.tilt;

               carai1.roll = carai1_dummy.roll;

               carai1.x = carai1_dummy.x;

               carai1.y = carai1_dummy.y;

               vec_set (temp.x, carai1_dummy.x);

               temp.z -= 2000;

               dist_z = c_trace(carai1_dummy.x, temp.x, IGNORE_ME | IGNORE_PASSABLE | IGNORE_MODELS); // ignore the "real" carai

               carai1.z = carai1_dummy.z - dist_z + 35; // 35 = experimental value

               // sets a variable car ai engine frequency, depending on the speed of the car

               snd_tune(carai_engine, 0, dummy1.car_speed * engine_factor, 0);

               wait(1);

               following_pan = carai1.pan;

               if (abs(following_pan - previous_pan) > 1) // sudden direction change? Then lower the speed of the AI car

               {

                       dummy1.car_speed -= 4 * time_step;

                       if (skids_once == 0)                        

                       {

                               skids_once = 1;

                               if (random(1) > 0.9)

                               {

                                       ent_playsound(dummy1, aiskids1_wav, 3000);

                               }

                       }

               }

               else

               {

                       skids_once = 0;

                       dummy1.car_speed += 2 * time_step;

               }

               dummy1.car_speed = clamp(dummy1.car_speed, min_speed, max_speed);

       }

}

 

 

Q: How can I make a bitmap stay full screen, regardless of the screen resolution?

A: Use this snippet:

 

BMAP* splash_tga = "splash.tga"; // splash screen bitmap

 

PANEL* splash_pan =

{

       bmap = splash_tga;

       layer = 15;

       flags = SHOW;

}

 

// makes the panel fill the entire screen, regardless of the screen size and / or the bitmap resolution

function panel_startup()

{

       while (1)

       {

               splash_pan.scale_x = screen_size.x / bmap_width(splash_tga);

               splash_pan.scale_y = screen_size.y / bmap_height(splash_tga);

               wait (1);

       }

}

 

 

Q: I wonder if it is possible to make an installer of the game I created. How can I do that?

A: There are several free installers that get the job done; here's how Inno Setup from http://www.jrsoftware.org/ works:

 

aum84_inno1

 

aum84_inno2

 

aum84_inno3

 

aum84_inno4

 

aum84_inno5

 

aum84_inno6

 

aum84_inno7

 

aum84_inno8

 

aum84_inno9

 

aum84_inno10

 

aum84_inno11

 

aum84_inno12

 

aum84_inno13

 

aum84_inno14

 

aum84_inno15

 

aum84_inno16

 

 

Q: I want to have a light moving on a path. How can I do that?

A: Use this snippet:

 

var entity_speed = 3;

var movement_enabled = 0;

var dist_to_node;

var current_node = 1;

 

VECTOR temp_angle;

VECTOR pos_node; // stores the position of the node

 

function move_target()

{

       while(1)

       {

               if(movement_enabled)

               {

                       entity_speed = minv(5, entity_speed + 0.5 * time_step);

                       c_move(my, vector(entity_speed * time_step, 0, 0), nullvector, IGNORE_PASSABLE | GLIDE);

                       vec_to_angle (my.pan, vec_diff (temp_angle, pos_node, my.x));

               }

               wait(1);

       }

}

 

action light_follows_path() // attach this action to your light model

//        set (my, INVISIBLE | PASSABLE); // if you don't want the light to be visible

       vec_set(my.blue, vector(255, 255, 255)); // set a white color for the light

       my.lightrange = 300; // and a range of 300 quants

       move_target();

       result = path_scan(me, my.x, my.pan, vector(360, 0, 500)); // scan the area

       if (result) {movement_enabled = 1;}

       path_getnode (my, 1, pos_node, NULL);

       vec_to_angle (my.pan, vec_diff (temp_angle, pos_node, my.x)); // rotate towards the node

       while(1)

       {

               dist_to_node = vec_dist(my.x, pos_node);

               if(dist_to_node < 50) // close to the node?

               {

                       current_node = path_nextnode(my, current_node, 1);

                       if (!current_node) {current_node = 1;} // reached the end of the path? Then start over!

                       path_getnode (my, current_node, pos_node, NULL);

               }

               wait(1);

       }

}

 

 

Q: I'm looking for a jump-pad snippet like in Quake.

A: There you go:

 

SOUND* jump_wav = "jump.wav";

 

function jump_now()

{

       snd_play(jump_wav, 80, 0);

       my.event = NULL; // don't trigger several jumps at once

       var vertical_force = 100; // play with 100

       while(vertical_force > 1) //while we have some jump force left

       {

               if (player) // we are controlling the player?

               {

                       c_move(player, vector(0, 0, vertical_force * time_step), nullvector, 0);

               }

               vertical_force -= 2.5 * time_step; // play with 2.5

               wait(1);

       }

       my.event = jump_now; // allow the jumps again

}

 

action jumping_pad() // attach this action to your jump pad model / wmb entity

{

       my.emask |= (ENABLE_IMPACT | ENABLE_ENTITY);

       my.event = jump_now;

}

 

action players_code() // need special player code as well

{

       var movement_speed = 10; // movement speed

       VECTOR temp;

       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 += 5 * mouse_force.y * time_step;

               temp.x = movement_speed * (key_w - key_s) * time_step;

               temp.y = movement_speed * (key_a - key_d) * 0.6 * time_step;

               temp.z = -15 * time_step;

               c_move (my, temp.x, nullvector, IGNORE_PASSABLE | GLIDE);

               wait (1);

       }

}

 

aum84_faq3

 

 

Q: How can I create a 3D menu, with 3D buttons that can be clicked?

A: Use this example as a base for your code:

 

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

{

       printf("Starts a new game");

}

 

function new_game()

{

       my.emask |= ENABLE_CLICK;

       my.event = start_game;

}

 

function end_game()

{

       sys_exit (NULL); // shut down the engine

}

 

function quit_game()

{

       my.emask |= ENABLE_CLICK;

       my.event = end_game;

}

 

function main()

{

       vec_set(screen_color, vector(200, 0, 0)); // make the background color blue

       fps_max = 70;

       video_mode = 7; // run in 800x600 pixels

       video_depth = 32; // 32 bit mode

       level_load (NULL); // load an empty level

       wait (2); // wait a bit

       camera.pan = 90; // point the camera in the right direction

       ent_create("background.mdl", vector (0, 200, 0), NULL); // create the background model

       ent_create("newgame.mdl", vector (0, 135, 30), new_game); // create the "New game" model

       ent_create("quitgame.mdl", vector (0, 135, -30), quit_game); // create the "Quit game" model

}

 

aum84_faq4