Questions from the forum

Top  Previous  Next

Q: I need a "waving grass" effect. I know it is changing the entity pan if I remember well, but I don't know the whole code. If you can help me, I would be very grateful!

A: Here's a more modern way of using a waving grass effect; it utilizes a predefined material.

 

#include <mtlFX.c> // you need to include this file

 

//Variable1: x Wind

//Variable2: y Wind

//Variable3: Oscillation speed

//Variable4: not used

 

action animated_grass() // add this action to your grass, trees, etc.

{

  my.material = mtl_animTree;

  mtl_setup(50, 50, 50, 50);

}

 

 

 

 

Q: I want to have a panel that allows the user to enter his name, and then displays it on the main menu,

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

 

BMAP* pointer_tga = "pointer.tga";

 

STRING* name_str = "Please Input Your Name";

STRING* displayed_str = "#50";

 

function input_name();

 

TEXT* input_txt =

{

       pos_x = 300;

       pos_y = 50;

       layer = 20;

       string(name_str);

       flags = SHOW;

}

 

TEXT* name_txt =

{

       pos_x = 400;

       pos_y = 350;

       layer = 10;

       string(displayed_str);

}

 

PANEL* main_pan = // used for the main panel, add your new / save / load etc buttons here

{

       bmap = "main.tga";

       pos_x = 280;

       pos_y = 40;

       layer = 5; // appears below the name input panel and text

       flags = SHOW;

}

 

PANEL* input_pan = // used for the text input box (as a background)

{

       bmap = "input.tga";

       pos_x = 280;

       pos_y = 40;

       layer = 10;

       flags = SHOW;

}

 

function input_startup()

{

       wait (-5); // wait for 5 seconds

  str_cpy(name_str, "                    "); // and then reset the input string

       inkey(name_str); // time to input player's name

       reset(input_pan, SHOW); // hide the input panel

       reset (input_txt, SHOW); // hide the input text

       str_cpy(displayed_str, "Welcome ");

       str_cat(displayed_str, name_str);

       set(name_txt, SHOW);

}

 

function mouse_startup()

       mouse_mode = 2;

       mouse_map = pointer_tga;

       while (1)

       

               vec_set(mouse_pos, mouse_cursor);

               wait(1);

       }

}

 

 

 

Q: Is there any way to add an action to a terrain entity that was already loaded? The name of the terrain is small.hmp

A: Sure thing!

 

STRING* temp_str = "                    ";

 

ENTITY* my_terrain;

 

function terrain_startup()

{

       while (!key_t) {wait (1);} // press the "T" key to detect and use the small.hmp terrain

       while (key_t) {wait (1);}

       you = ent_next(NULL); // retrieve the first entity

       while (you) // run this loop for as long as there are entities left in the level

       {

               str_for_entfile(temp_str, you); // get the entity file name

               if (str_cmpi(temp_str, "small.hmp")) // the entity is named small.hmp?

               {

                       my_terrain = you;

                       my_terrain.ambient = -100; // Then darken the terrain! Use your own code here

               }

               wait (-2);

               you = ent_next(you); // move on to the next entity

       }

}

 

TEXT* message_txt =

{

       pos_x = 200;

       pos_y = 20;

       string(temp_str);

       flags = SHOW;

}

 

 

 

Q: Is it possible to change the texture of a wmb entity at run time?

A: The wmb entities are compiled, so you can't change their textures. Use models to achieve what you want.

 

 

 

Q: My enemy dies when it is hit with a bullet. However, it will also die if the player is running into it or if a fellow enemy touches it.

A: Your enemy is sensitive to all the EVENT_IMPACT and / or EVENT_ENTITY events. You need to set a unique value for your bullets' skills, and then check for that particular value in the collision check function, just like below.

 

function got_shot()

{

       // didn't collide with a bullet? Then nothing should happen (the bullet's skill30 was set to 1234 in the function that creates it)

       if (you.skill30 != 1234) {return;}

       // the rest of your enemy damage code should go here

       ....

}

 

 

Q: In the map editor I created 5 enemies that use the same action. The problem is that if one enemy dies the rest die too.

A: You are using a single, global variable for the health of your enemies, so when it reaches zero everyone dies. Use local variables (variables included in the enemy action, not outside it) or entity skills to store the health of the enemies.

 

 

 

Q: I am looking for a way to draw lines, pixels and shapes on bitmaps during run time. Basically I am looking for a way to draw on objects. Can anyone help me out with this please?

A: Here's an example that makes use of a code snippet from the manual. Be sure to learn more about  pixel_to_bmap before creating your own code.

 

BMAP* my_bitmap;

 

void bmap_drawborder(BMAP* bmap, COLOR* color, var alpha)

{  

       var pixel = pixel_for_vec(color, alpha, bmap_lock(bmap,0));  

       var width = bmap_width(bmap);  

       var height = bmap_height(bmap);  

       var i;  

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

       {     

               pixel_to_bmap(bmap, i, 0, pixel);     

               pixel_to_bmap(bmap, i, height - 1, pixel);  

       }  

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

       {     

               pixel_to_bmap(bmap, 0, i, pixel);     

               pixel_to_bmap(bmap, width - 1, i, pixel);  

       }  

       bmap_unlock(bmap);  

}

 

function paint_startup()

{

       wait (-2); // wait for 2 seconds

       my_bitmap = bmap_create("options.pcx"); // use your own bitmap here

       PANEL* my_panel = pan_create(NULL, 0);

       my_panel.bmap = my_bitmap;

       set(my_panel, SHOW);        

       wait (-3); // display the initial bitmap for 3 seconds, and then draw a blueish border around it

       bmap_drawborder(my_bitmap, vector(250, 200, 80), 100); // use your own BGR colors and alpha values here

}

 

 

 

Q: Mouse_ent seems to show a lot of info about the sprite or model its over but not the type. I need to click on and remove only a randomly created sprite entity during game play and not be able to remove models, etc.

A: Heres a fully functional example:

 

STRING* name_str = "                    ";

STRING* temp_str = "                    ";

 

var string_length;

 

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 != NULL) && (mouse_left == 1)) // the mouse touches an entity and the player has clicked the left mouse button?

               {

                       str_for_entfile(name_str, mouse_ent); // get the entity file name

                       string_length = str_len(name_str);

                       str_clip(name_str, string_length - 3); // keep the last 3 characters from the file name (its extension)

                       if (str_cmpi(name_str, "pcx") || str_cmpi(name_str, "tga")) // add as many sprite extensions as needed here

                       {

                               ent_remove(mouse_ent); // remove the sprite        

                       }

               }

               wait (1);

       }

}

 

 

 

Q: How can I disable the buttons of a PANEL?

A: There are a few methods that can be used for this purpose; pick the one that works best for you:

- Place tiny transparent panels that have a higher layer value over the buttons that need to be disabled;

- Use pan_setbutton to modify the behavior of the desired buttons, setting functionClick to NULL.

 

 

 

Q: Is there a possibility to let a path emit particles?

A: No, but you can use an invisible entity that emits particles and moves on a path.

 

var cam_speed = 1; // initial speed

var dist_to_node;

var current_node = 1;

var angle_difference = 0;

var temp_angle;

var pos_node; // stores the position of the node

 

BMAP* fire_tga = "fire.tga";

 

ENTITY* dummy_ent;

 

function move_dummy()

{

       set(my, PASSABLE | INVISIBLE);

       while (1)

       {

               vec_set (my.x, you.x);

               wait (1);

       }

}

 

function move_target()

{

       while(1)

       {

               cam_speed = minv(15, cam_speed + 5 * time_step); // 15 gives the movement speed

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

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

               if(my.pan != dummy_ent.pan)

               {

                       angle_difference = ang(dummy_ent.pan - my.pan);

                       my.pan += angle_difference * 0.2 * time_step;

               }

               wait(1);

       }

}

 

function fade_fire(PARTICLE *p)

{

       p.alpha -= 4 * time_step; // fade out the fire particles

       if (p.alpha < 0)

               p.lifespan = 0;

}

function fire_effect(PARTICLE *p)

{

       set (my, PASSABLE);

       p->vel_x = 5 - random(10);

       p->vel_y = 5 - random(10);

       p->vel_z = 10 - random(20);

       p.alpha = 50 + random(50);

       p.bmap = fire_tga;

       p.size = 15; // gives the size of the flame particles

       p.flags |= (BRIGHT | MOVE);

       p.event = fade_fire;

}

 

action dummy_entity() // attach this action to the invisible entity that will follow the path

{       

       set (my, INVISIBLE); // uncomment this line to hide the moving entity

       dummy_ent = ent_create ("dummy.mdl", nullvector, move_dummy);

       move_target();

       result = path_scan(me, my.x, my.pan, vector(360, 180, 1000));

       if (!result) {return;}

       path_getnode (my, 1, pos_node, NULL);

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

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

       while (1)

       {

               dist_to_node = vec_dist(my.x, pos_node);

               if(dist_to_node < 300) // 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);

               }

            effect(fire_effect, 5, my.x, nullvector);

               wait(1);

       }

}