Questions from the forum

Top  Previous  Next

Q: I've got some damage code from one of the AUMs working fine in my game. But how can I create a visual effect that looks like a red laser barrier which moves up and down at all times?

A: Use the following snippet.

 

var height;

 

function energy_startup()

{

       while (1)

       {

               // set the starting point for the 3D line

               // the numbers below (100, 100) set the x and y coordinates of the starting point

               draw_line3d(vector(100, 100, height), NULL, 100);

               // draw the red laser line

               // the numbers below (100, 150) set the x and y coordinates of the ending point

               draw_line3d(vector(100, 150, height), vector(0, 0, 255), 100);

               wait (1);

               

       }

}

 

function init_startup()

{

       fps_max = 60; // limit the frame rate

       while (1)

       {

               // -150 is the minimum laser barrier height

               // 80 = laser movement amplitude

               height = -150 + sinv(total_frames) * 80;

               wait (1);        

       }

}

 

 

Q: I need code for a player/NPC combo. The NPC should start playing its "talk" animation when the player comes close and is looking at it. Can you help?

A: Sure, here's your player/NPC combo.

 

var t_player_speed = 25; // player's movement speed

var t_fwdbk_accel = 7; // player's forward / backward acceleration

var t_side_accel = 3; // player's sideway (strafe) acceleration

var t_friction = 1.5; // player's friction - this value should always be greater than 1

var t_fallspeed = 1; // player's fall down speed

var t_jump = 20; // player's jumping force

var t_resilience = 4; // pushes the player upwards a bit if it sinks too much in the floor

var t_disttoground = 64; // distance between the origin of player's model and the ground (used by the camera as well)

var t_camera_h = 12; // horizontal camera acceleration

var t_camera_h_frict = 0.95; // always use a value below 1 here

var t_camera_v = 8; // vertical camera acceleration

var t_camera_v_frict = 0.8; // always use a value below 1 here

var t_players_health = 100; // the player starts with 100 health points

var camera_h_speed = 0;

var camera_v_speed = 0;

 

var animation_mode = 0; // 0 = stand, 1 = talk;

var anim_percentage = 0;

 

action players_code() // attach this piece of code to your player

{

       player = my;

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

       set (my, FLAG2); // will be used by enemies' c_scan instructions to detect the player

       var forward_on, backward_on, right_on, left_on, jump_on, run_on;

       var current_height = 0, jump_handle;

       VECTOR horizontal_speed, vertical_speed, temp;

       vec_set(horizontal_speed.x, nullvector); // initialize this vector

       vec_set(vertical_speed.x, nullvector); // initialize this vector

       while(t_players_health > 0)

       {

               // the player scans on a radius of 1,000 quants around it

               c_scan(my.x, my.pan, vector(60, 180, 150), IGNORE_ME);

                             

               // key input start

               forward_on = 0; // reset all the key values at the beginning of each frame

               backward_on = 0;

               right_on = 0;

               left_on = 0;

               jump_on = 0;

               run_on = 0;

               // set the proper variables if their corresponding keys are pressed

               if(key_w)

                       forward_on = 1;

               if(key_s)

                       backward_on = 1; 

               if(key_a)

                       left_on = 1;

               if(key_d)

                       right_on = 1; 

               if(key_space)

                       jump_on = 1;    

               if(key_shift)

                       run_on = 1;    

               // key input end

               if (key_q)

                       camera.pan -= 5 * time_step;

               if (key_e)

                       camera.pan += 5 * time_step;

 

               vec_set(camera.x, my.x);

               // accelerate camera's pan and tilt angles depending on mouse_force.x and mouse_force.y in order to create a smooth camera

               camera.pan -= accelerate (camera_h_speed, t_camera_h * (mouse_force.x), t_camera_h_frict);

               camera.tilt += accelerate (camera_v_speed, t_camera_v * (mouse_force.y), t_camera_v_frict);

               camera.tilt = clamp(camera.tilt, -90, 90); // limit the tilt angle of the camera to -90... 90 degrees

               my.pan = camera.pan;

 

               // player's horizontal speed (forward / backward / sideways) movement uses acceleration and friction as well

               horizontal_speed.x = (horizontal_speed.x > 0) * maxv(horizontal_speed.x - time_step * t_friction, 0) + (horizontal_speed.x < 0) * minv(horizontal_speed.x + time_step * t_friction, 0);

               if(forward_on)

               {

                       horizontal_speed.x += time_step * t_fwdbk_accel;

                       horizontal_speed.x = minv(horizontal_speed.x, time_step * t_player_speed  * (1 + run_on));

               }   

               if(backward_on)

               {

                       horizontal_speed.x -= time_step * t_fwdbk_accel;

                       horizontal_speed.x = maxv(horizontal_speed.x, -(time_step * t_player_speed * (1 + run_on)));

               }   

               horizontal_speed.y = (horizontal_speed.y > 0) * maxv(horizontal_speed.y - time_step * t_friction, 0) + (horizontal_speed.y < 0) * minv(horizontal_speed.y + time_step * t_friction, 0);

               if(left_on)

               {

                       horizontal_speed.y += time_step * t_side_accel;

                       horizontal_speed.y = minv(horizontal_speed.y, time_step * t_player_speed * (1 + run_on));

               }

               if(right_on)

               {

                       horizontal_speed.y -= time_step * t_side_accel;

                       horizontal_speed.y = maxv(horizontal_speed.y, -(time_step * t_player_speed * (1 + run_on)));

               }           

               // disable the friction, allow smooth gliding along the surfaces

               move_friction = 0;

               vec_set(temp.x, my.x);

               temp.z -= 10000;

               current_height = c_trace(my.x, temp.x, IGNORE_ME | IGNORE_PASSABLE | USE_BOX | GLIDE); // compute the distance between player's origin and the floor below its feet

               if(current_height < (t_disttoground * 0.97)) // if it is smaller than the default value (64 quants) push the player upwards a bit (resilience) - 0.97 gives the hysteresis

               {

                       vertical_speed.z = t_resilience * time_step;

               }

               else

               {

                       if(current_height > t_disttoground) // if it is bigger than the default value (64 quants), move the player downwards

                       {

                               vertical_speed.z -= t_fallspeed * time_step;

                       }

                       else // sitting properly on the floor?

                       {

                               vertical_speed.z = 0; // then don't do anything on the z axis

                       }

               }   

               if((jump_on) && (current_height < t_disttoground)) // jumping while player's feet are placed on the floor?

               {

                       vertical_speed.z = t_jump * 0.25; // push the player upwards

               }

               // this c_move instruction does all the job, moving the player in the direction given by horizontal_speed (forward, backward, sideways) and vertical_speed (on the z axis)

               c_move (my, horizontal_speed.x , vertical_speed.x, IGNORE_PASSABLE | USE_BOX | GLIDE);

               // player movement end

               wait(1);

       }

       camera.z -= 30; // bring the camera closer to the floor

       camera.roll = 40; // and rotate its view (the player is dead here)

}

 

function got_scanned()

{

       while (event_type == EVENT_SCAN)

       {

               animation_mode = 1; // "talk"

               wait (1);

       }

       animation_mode = 0; // "stand"

}

 

action my_enemies() // attach this action to your enemies

{

       reset (my, SHOW);

       my.emask |= ENABLE_SCAN; // make the entity sensitive to scanning

       my.event = got_scanned;

       while (1)

       {

               anim_percentage += 3 * time_step;

               // use your own animation code here

               if (animation_mode == 1)

               {

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

               }

               else

               {

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

               }

               wait (1);

       }

}

 

 

Q: How do I fade out my soundtrack after the player clicks the "Start" game button, before loading the level?

A: Here's an example.

 

var game_started = 0;

var track_volume = 100;

var soundtrack_handle;

 

BMAP* menu_png = "menu.png";

 

BMAP* start1_png = "start1.png";

BMAP* start2_png = "start2.png";

BMAP* exit1_png = "exit1.png";

BMAP* exit2_png = "exit2.png";

 

BMAP* pointer_tga = "pointer.tga";

 

STRING* level1_wmb = "level1.wmb";

 

function init_game();

function start_game();

function exit_game();

 

PANEL* main_pan =

{

       layer = 10;

       bmap = menu_png;

       pos_x = 0;

       pos_y = 0;

       button (250, 10, start2_png, start1_png, start2_png, start_game, NULL, NULL);

       button (250, 50, exit2_png, exit1_png, exit2_png, exit_game, NULL, NULL);

       flags = SHOW;

}

 

function game_startup()

{

       var track_volume = 100; // initial sound volume, put your prefered value here

       soundtrack_handle = media_play("soundtrack.mp3", NULL, track_volume);

       mouse_mode = 2;

       mouse_map = pointer_tga;

       while (1)

       

               vec_set(mouse_pos, mouse_cursor);

               wait(1);

       }

}

 

function start_game()

{

       reset(main_pan, SHOW);

       while (track_volume > 0) // the game has started, so decrease the volume

       {

               media_tune(soundtrack_handle, track_volume, 100, 0);

               track_volume -= 2 * time_step; // 2 gives the volume decrease speed

               wait (1);

       }

       media_stop (soundtrack_handle); // stop the sound for good

       // level_load (level1_wmb); // load the first game level here

}

 

function exit_game()

{

       sys_exit(NULL);        

}

 

 

Q: I'd need some code for a little bunny that jumps for several seconds, rests for several seconds, and can avoid obstacles. Is it possible to do that?

A: Sure, see for yourself!

 

var distance_covered = 0;

 

action my_bunny()

{

       var anim_percentage;

       var jumping_interval = 0;

       var random_interval;

       while (1)

       {

               if (jumping_interval == 0)

               {

                       // sets the number of jumping seconds before changind the direction

                       random_interval = 5 + random(3);

               }

               // "10" controls the jumping speed

               distance_covered = c_move (my, vector(10 * time_step, 0, 0), nullvector, GLIDE);

               // use your own rabbit animation name below

               ent_animate(my, "rockrun", anim_percentage, ANM_CYCLE);

               // "6" controls the animation speed

               anim_percentage += 6 * time_step;

               // increase jumpung_interval by 1 each second

               jumping_interval += time_step / 16;

               // the rabbit has jumped more than random_interval in a direction? Then it's time to change the direction!

               if (jumping_interval > random_interval)

               {

                       // let the bunny rest for a while

                       while (jumping_interval > 0)

                       {

                               // decrease jumping_interval by 1 each second

                               jumping_interval -= time_step/16;

                               ent_animate(my, "stand", anim_percentage, ANM_CYCLE);

                               // "6" controls the animation speed

                               anim_percentage += 6 * time_step;

                               wait (1);

                       }

                       // add -90...+90 degrees to the pan angle

                       my.pan += 90 - random(180);

               }

               // the rabbit got stuck?

               if (distance_covered < 1) // the value returned by c_move is really small

               {

                       // then add 120...+240 degrees to its pan angle        (about 180 degrees, should get the rabbit out of trouble)

                       my.pan += 120 + random(120);

               }

               wait (1);

       }

}

 

PANEL* distance_pan =

{

       layer = 15;

       digits(100, 20, "Distance covered per frame: %.f", *, 1, distance_covered);        

       flags = SHOW;

}

 

 

Q: How do I reduce the size of my game? Right now, the published version has over 500MB!

A: It all comes down to the size of the textures that are used for the levels and models in your game. Most mobile game developers start with texture sizes that are as small as possible, and then go up until their games look good enough. To give you a few examples, characters have 256x256 pixels skins, and level elements use 64x64 or 128x128 pixels textures. A little known trick is to reduce texture depth; use RIOT to convert your textures to 8 bits (256 colors). Good luck!

 

 

Q: The player has to control 3 team members. How do I code it, so that a player becomes active and starts moving forward when it is clicked? When one of the other team members is clicked, the first team member should stop and the second member should start moving, etc.

A: Place your 3 team members in the level, and then attach them all the "team_members" action below.

 

BMAP* arrow_pcx = "arrow.pcx";

 

function init_startup()

{

       // allow the player to click the team members even if they are 10,000 quants away from its model

       mouse_range = 10000;

       // set the desired x y z values for the camera

       vec_set(camera.x, vector (200, -300, 300));

       camera.pan = 90; // set the proper camera.pan angle

       camera.tilt = -40; // set the proper camera.tilt angle

}

 

// standard mouse code

function mouse_startup()

       mouse_mode = 1;

       mouse_map = arrow_pcx;

       while (1)

       

         vec_set(mouse_pos, mouse_cursor);

               wait(1);

       }

}

 

function team_control()

{

       player = my;

       my.skill1 = 99; // set a unique value for skill1

       var walk_percentage;

       if (my.skill1 == 99) // if this is the active team member

       {

               while (player == my) // this loop will only run for the entity that was clicked

               {

                       c_move (my, vector(3 * time_step, 0, 0), nullvector, GLIDE);                        

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

                       walk_percentage += 3 * time_step; // "3" controls the animation speed                        

                       wait (1);

               }

               my.skill1 = 0; // the current team member has changed, so let's reset skill1 now

       }

}

 

action team_members() // attach this action to your team members

{

       my.emask |= ENABLE_CLICK; // make the entity sensitive to mouse clicking

       my.event = team_control; // this function will run when the player clicks one of the team members

}

 

 

Q: How do I code 5 weapons that can be selected by pressing the 1...5 buttons on the keyword?

A: There you go.

 

var active_weapon = 1; // ranges from 1 to 5, depending on the current weapon

 

ENTITY* weapon1_ent =

{

       type = "weapon1.mdl"; // weapon model

       pan = 0; // weapon angle

       x = 55; // 55 quants ahead of the view, play with this value

       y = -20; // 20 quants towards the right side of the screen, play with this value

       z = -20; // 20 quants below, play with this value

       pan = 2; // weapon's pan angle (you can also use tilt and roll)

}

 

ENTITY* weapon2_ent =

{

       type = "weapon2.mdl"; // weapon model

       pan = 0; // weapon angle

       x = 60; // 60 quants ahead of the view, play with this value

       y = 15; // 15 quants towards the left side of the screen, play with this value

       z = -18; // 18 quants below, play with this value

       pan = -3; // weapon's pan angle (you can also use tilt and roll)

}

 

ENTITY* weapon3_ent =

{

       type = "weapon3.mdl"; // weapon model

       pan = 0; // weapon angle

       x = 60; // 60 quants ahead of the view, play with this value

       y = 15; // 15 quants towards the left side of the screen, play with this value

       z = -18; // 18 quants below, play with this value

       pan = -3; // weapon's pan angle (you can also use tilt and roll)

}

 

ENTITY* weapon4_ent =

{

       type = "weapon4.mdl"; // weapon model

       pan = 0; // weapon angle

       x = 60; // 60 quants ahead of the view, play with this value

       y = 15; // 15 quants towards the left side of the screen, play with this value

       z = -18; // 18 quants below, play with this value

       pan = -3; // weapon's pan angle (you can also use tilt and roll)

}

 

ENTITY* weapon5_ent =

{

       type = "weapon5.mdl"; // weapon model

       pan = 0; // weapon angle

       x = 60; // 60 quants ahead of the view, play with this value

       y = 15; // 15 quants towards the left side of the screen, play with this value

       z = -18; // 18 quants below, play with this value

       pan = -3; // weapon's pan angle (you can also use tilt and roll)

}

 

function gun_startup()

{

       while (1)

       {

               if (key_1)

               {

                       weapon1_ent.flags2 = VISIBLE;

                       weapon2_ent.flags2 = ~VISIBLE;

                       weapon3_ent.flags2 = ~VISIBLE;

                       weapon4_ent.flags2 = ~VISIBLE;

                       weapon5_ent.flags2 = ~VISIBLE;                                                

                       active_weapon = 1;

               }

               if (key_2)

               {

                       weapon1_ent.flags2 = ~VISIBLE;

                       weapon2_ent.flags2 = VISIBLE;

                       weapon3_ent.flags2 = ~VISIBLE;

                       weapon4_ent.flags2 = ~VISIBLE;

                       weapon5_ent.flags2 = ~VISIBLE;

                       active_weapon = 2;

               }

               if (key_3)

               {

                       weapon1_ent.flags2 = ~VISIBLE;

                       weapon2_ent.flags2 = ~VISIBLE;                        

                       weapon3_ent.flags2 = VISIBLE;

                       weapon4_ent.flags2 = ~VISIBLE;

                       weapon5_ent.flags2 = ~VISIBLE;                                                

                       active_weapon = 3;

               }

               if (key_4)

               {

                       weapon1_ent.flags2 = ~VISIBLE;

                       weapon2_ent.flags2 = ~VISIBLE;

                       weapon3_ent.flags2 = ~VISIBLE;                                                

                       weapon4_ent.flags2 = VISIBLE;

                       weapon5_ent.flags2 = ~VISIBLE;                        

                       active_weapon = 4;

               }

               if (key_5)

               {                        

                       weapon1_ent.flags2 = ~VISIBLE;

                       weapon2_ent.flags2 = ~VISIBLE;

                       weapon3_ent.flags2 = ~VISIBLE;

                       weapon4_ent.flags2 = ~VISIBLE;                                                                        

                       weapon5_ent.flags2 = VISIBLE;

                       active_weapon = 5;

               }

               wait (1);

       }

}

 

function gun_code()

{

       while (1)

       {

               if (active_weapon == 1)

               {

                       // put the code for your first weapon here

                       wait (1);

               }

               if (active_weapon == 2)

               {

                       // put the code for your second weapon here

                       wait (1);

               }

               if (active_weapon == 3)

               {

                       // put the code for your third weapon here

                       wait (1);

               }

               if (active_weapon == 4)

               {

                       // put the code for your fourth weapon here

                       wait (1);

               }

               if (active_weapon == 5)

               {

                       // put the code for your fifth weapon here

                       wait (1);

               }

               wait (1);

       }

}

 

 

Q: How do I create a patrolling entity that has a working flashlight attached to its helmet?

A: Here's an example.

 

ENTITY* dummy;

 

function headlight() // attaches a flashlight to the patrolling entity

{

       set(my, PASSABLE);

       vec_set(d3d_spotlightcone, vector(25, 80, 4)); // play with these values

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

       my.lightrange = 300; // on a range of up to 300 quants

       my.flags2 |= SPOTLIGHT;

       while (1)

       {

                 // play with the numerical values, they set the position of the headlight (x, y, z)

                 // make them match player's head/helmet coords

            vec_set (my.x, vector (10, 0, 50));

            vec_rotate (my.x, you.pan);

            vec_add (my.x, you.x);

            my.pan = you.pan;

            wait (1);

       }

}

 

action patroller() // simple path patrolling movement code

{

       var walk_percentage;

       var distance = 0;

       var previous_pan;

       var following_pan;

       var min_speed = 1;

       var max_speed = 3;

       var walking_speed;

       VECTOR last_pos[3];

       VECTOR direction[3];

       ent_create("headlight.mdl", nullvector, headlight); // create the headlight model

       // create a dummy entity that will move on the path

       dummy = ent_create(NULL, nullvector, NULL);

       // make sure to name your path this way

       path_set(dummy, "path_001");

       while(1)

       {

               previous_pan = my.pan;

               // place the dummy entity on the path

               path_spline(dummy, my.x, distance);

               distance += walking_speed * time_step;

               // let the npc look ahead

               vec_diff(direction, my.x, last_pos);

               vec_to_angle(my.pan, direction);

               vec_set(last_pos, my.x);

               wait(1);

               following_pan = my.pan;

               // sudden direction change during the last frame? Then lower the speed of the npc!

               if (abs(following_pan - previous_pan) > 1)

               {

                    walking_speed -= 4 * time_step;

               }

               else

               {

                    walking_speed += 2 * time_step;

               }               

               // don't allow the walking speed to exceed the specified min / max limits

               walking_speed = clamp(walking_speed, min_speed, max_speed);

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

               walk_percentage += 3 * time_step; // "3" controls the animation speed

       }

}

 

 

Q: I am building my levels using models. How do I create a function that writes down the coordinates for all their vertices to a file?

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

 

STRING* temp_str = "#20";

 

VECTOR temp;

 

action entity_coords()

{

       var filehandle_write, i = 0;

       filehandle_write = file_open_write("vertexcoords.txt");        

       while (i < ent_vertices(my))

       {

               vec_for_vertex (temp, my, i);

               file_var_write(filehandle_write, i);

               file_str_write(filehandle_write, ", ");

               str_for_num(temp_str, temp.x);

               file_str_write(filehandle_write, temp_str);

               file_str_write(filehandle_write, ", ");

               str_for_num(temp_str, temp.y);

               file_str_write(filehandle_write, temp_str);

               file_str_write(filehandle_write, ", ");

               str_for_num(temp_str, temp.z);

               file_str_write(filehandle_write, temp_str);

               // move on to the following row

               file_asc_write (filehandle_write, 13); // write the following strings on a new line

               file_asc_write (filehandle_write, 10); // using asc(13) = carriage return + asc(10) = line feed

               i++;

       }

       // all the data has been written, so let's close the text file now

  file_close(filehandle_write);

}

 

PANEL* debug_pan =

{

       pos_x = 0;    

       pos_y = 0;   

       digits (15, 20, 3, _a4font, 1, temp[0]);

       digits (15, 40, 3, _a4font, 1, temp[1]);

       digits (15, 60, 3, _a4font, 1, temp[2]);

       flags = SHOW;

}