Fragen aus dem Forum

Top  Previous  Next

F: Ich möchte, dass meine Feinde nur dann angreifen wenn sie den Player sehen können. Wie kann ich soetwas berechnen?

A: Hier ist ein Feind, der sich im Kreis bewegt und einen Alarmsound abspielt, wenn er den Player sehen kann.

 

SOUND* alarm_wav = "alarm.wav";

 

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

{        

       var movement_speed = 20; // movement speed

       VECTOR temp, players_sensor;

       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;

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

       }

}

 

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

{

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

       var alarm_handle, walk_percentage = 0;

       while (1)

       {

               // scans a sector that's got 120 degrees horizontally, 60 degrees vertically and a length of 1000 quants

               // the player will be detected only if its action includes this line of code: "player = my;" (without the quotes)

               if ((c_scan(my.x, my.pan, vector(120, 60, 1000), IGNORE_ME) > 0) && (you == player))

               {

                       if (!snd_playing(alarm_handle)) // the alarm sound isn't playing already?

                       {

                               alarm_handle = snd_play(alarm_wav, 70, 0); // then let's play it!

                       }

               }

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

               my.pan += 1 * time_step; // make the enemy rotate in a circle

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

               walk_percentage += 2 * time_step; // 2 controls the walk animation speed

               wait (1);

       }

}

 

 

F: Ich habe auf A7.82 upgegradet aber jetzt kriege ich einen Fehler mit Ihren Multiplayer-AUM-Workshops (Schiessen vom falschen Player aus). Wie kann ich das beheben?

A: Ihre Festplatte hat nicht genügend Zeit, sämtliche Quellen zu lesen. Ein Ersetzen der Anweisung "wait (-0.5);" durch ein "wait (-3);" in meinem Code sollte das Problem beheben. Eine etwas elegantere Lösung im Folgenden:

 

my = ent_create ("redsoldier.mdl", vector (100, 50, 40), move_players);

while (my.client_id != dplay_id) wait (1); // wait until the handle is ready

client_ent = handle(my);

 

 

F: Ich habe das Skript zum Rendern der Cube-Map auf der Wiki-Seite gefunden. Kann jemand erklären was es macht und wie es funktioniert?

A: Dieses Skript erstellt eine Sky-Cube-Bitmap indem es 6 Screenshots (die 6 Oberflächen eines Würfels) aus dem Level nimmt und zu einer einzigen .tga-Bitmap verschmelzt. Dann können Sie Ihren Sky-Cube mit einer einfachen "ent_createlayer"-Anweisung darstellen.

 

aum90_faq1

 

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 ("mylevel.wmb");

       wait (3);

       ent_createlayer("skycube+6.tga", SKY | CUBE | VISIBLE , 1);

}

 

 

F: Ich habe versucht, meiner Kamin-Entity einen Sound zu geben aber ich kann ihn nicht hören. Diesen Code verwende ich:

 

var fire_handle;

 

SOUND* fire = "fire.wav";

 

ENTITY* fireplace = "fireplace.mdl";

 

action my_fire()

{

       fire_handle = ent_playsound (fireplace, fire, 80);

}

 

A: Ihr Code hat ein kleines Problem: er spielt den Sound "fire.wav" nur einmal und wenn der Player nah an den Kamin herankommt, hört er für immer auf. Verwenden Sie den veränderten Code unten:

 

var fire_handle;

 

SOUND* fire = "fire.wav";

 

action my_fire() // attach this action to your fireplace entity

{

       fire_handle = ent_playloop(my, fire, 80);

}

 

 

F: Ich möchte gerne eine Taste drücken und dann soll ein animiertes Sprite auftauchen, durch seine sämtlichen Frames gehen und dann verschwinden. Wenn ich die Taste wieder drücke, soll sich das Ganze wiederholen.

A: Hier ist ein Beispiel:

 

function animated_sprite()

{

       set(my, BRIGHT);

       my.alpha = 100;

       my.frame = 1; // start with the first frame

       while (my.frame < 20) // change this value if your animated sprite doesn't contain 20 frames

       {

               my.frame += 1.2 * time_step; // 1.2 gives the animation speed

               wait (1);

       }

       // let's fade out the last animation frame (remove the "while" loop below if you don't want that to happen

       while (my.alpha > 0)

       {

               my.alpha -= 0.7 * time_step; // 0.7 gives the fade-out animation speed

       }

       ent_remove (my); // remove the sprite

}

 

function create_sprite()

{

       // creates the sprite 300 quants in front of the camera in this example; feel free to use your own values

       // use your own animated sprite here

       VECTOR sprite_offset;

       vec_set (sprite_offset.x, vector(300, 0, 0));

       vec_rotate (sprite_offset.x, camera.pan);

       vec_add (sprite_offset.x, camera.x);

       ent_create("muzzle+20.tga", sprite_offset.x, animated_sprite);

}

 

function init_startup()

{

       on_c = create_sprite; // press the "C" key to create the sprite

}

 

aum90_faq2

 

 

F: Ich möchte dass bestimmte NPCs den Player und andere Objekte mit ihren Köpfen und Augen verfolgen. Soll ich Vertex- oder Bonesanimationen nehmen?

A: Nehmen Sie Bones, damit ist das viel einfacher. Schauen Sie sich den Workshop "The Bone Collector" (script23_2.c) an. Sie finden ihn unter  http://tutorial.3dgamestudio.net dort sehen Sie ein gutes Beispiel.

 

 

F: Ich möchte meinem Player eine rotierende Entity zuweisen, sie muß aber Kollisionserkennung druchführen während sie sich um den Player dreht. Können Sie helfen?

A: Nehmen Sie den Schnipsel unten - damit geht es.

 

ENTITY* dummy_ent;

 

// the function below moves the "real" rotating entity towards the position of the dummy entity (if possible)

function rotate_guard()

{

       proc_mode = PROC_LATE;

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

       VECTOR offset_speed;

       while (1)

       {

               vec_diff(offset_speed.x, dummy_ent.x, my.x);

               // normalize the speed with which the "real" entity follows the dummy entity, play with 10

               vec_normalize(offset_speed, 10 * time_step);

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

               my.pan = dummy_ent.pan;                

               wait (1);

       }

}

 

// the function below creates a dummy entity that rotates around the player at all times, penetrating the walls, etc

function rotate_around_player()

{

//        set (my, INVISIBLE | PASSABLE); // make the dummy entity invisible and passable

       ent_create("guard.mdl", my.x, rotate_guard); // use your own model here

       var rotation_angle;

       VECTOR my_speed, temp;

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

       my.emask |= (ENABLE_IMPACT | ENABLE_ENTITY);

       while (1)

       {

               my.x = player.x - 250 * cos(rotation_angle);

               my.y = player.y - 250 * sin(rotation_angle);

               my.z = player.z + 30; // play with 30

               rotation_angle += 0.5 * time_step;

               vec_set(temp.x, player.x);

               vec_sub(temp.x, my.x);

               vec_to_angle(my.pan, temp);

               wait (1);

       }

}

 

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

{        

       var movement_speed = 20;

       VECTOR temp, players_sensor;

       set (my, INVISIBLE);

       player = my;

       dummy_ent = ent_create("dummy.mdl", nullvector, rotate_around_player); // put this line inside your player action

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

               camera.pan = my.pan;

               camera.tilt += 5 * mouse_force.y * time_step;

               vec_set (temp.x, my.x);

               temp.z -= 10000;

               temp.z = -c_trace (my.x, temp.x, IGNORE_ME | IGNORE_PASSABLE | USE_BOX) - 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);

       }

}

 

 

F: Es ist zwar selten aber das Spielefenster geht völlig grundlos in den Hintergrund, es geschieht auch dann, wenn ich mein Game im Vollbildmodus laufen lasse. Warum passiert das?

A: Eine andere Anwendung übernimmt die Kontrolle. Für gewöhnlich ist das Ihr Antivirusprogramm, das nicht leise vor sich hin updatet sondern ein kleines Fenster erscheinen läßt, welches Ihr Spiel in den Hintergrund schickt. Schalten Sie das Antivirusprogramm vorübergehend ab und prüfen Sie, ob dies das Problem löst. Ist es das nicht, müssen Sie dasselbe solange mit allen Applikationen machen, die im Hintergrund laufen bis sie die Schuldige gefunden haben und dann entfernen / ersetzen Sie diese.

 

F: Ich möchte gerne ein NPC-Skript in mein RPG-Level integrieren. Kann mir irgendjemand ein Beispiel geben?

A: Hier das Beispiel eines NPCs, das herumläuft, für eine Weile stehen bleibt und sich dann wieder bewegt. Es kann Wänden ausweichen und gibt ein paar Tipps wenn der Player sich ihm nähert.

 

// use a wave file that contains something like "Stay away from the red rabbit, stranger!"

SOUND* advice_wav = "advice.wav";

 

action my_npc()

{

       VECTOR front_pos;

       var distance_covered = 0;

       var sound_once = 1;

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

       while (1)

       {

               vec_set(front_pos.x, vector(50, 0, 0)); // compute a position that's placed 50 quants in front of the player

               // rotate "front_pos" in the direction (angles) given by the entity

               vec_rotate(front_pos.x, my.pan);

               vec_add(front_pos.x, my.x); // add the resulting vector to entity's position

               // front_pos isn't touching any walls and the player didn't move 500 quants without pausing yet?

               if ((c_content(front_pos.x, 0) == 1) && (distance_covered < 500))

               {

                       // 5 gives the movement speed

                       distance_covered += c_move(my, vector(5 * time_step, 0, 0), nullvector, IGNORE_PASSABLE | GLIDE);

                       my.skill22 += 5 * time_step; // 5 gives the "walk" animation speed

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

                       // if the player is closer than 150 quants to the npc and advice_wav wasn't played yet

                       if ((vec_dist(player.x, my.x) < 150) && (sound_once == 1))

                       {

                               sound_once = 2; // don't allow the sound to be played more than once per walking cycle

                               ent_playsound(my, advice_wav, 50);

                       }

               }

               else // the player is close to a wall or it has moved more than 500 quants?

               {

                       sound_once = 1; // reset sound_once

                       distance_covered = 0; // reset distance_covered!

                       my.skill99 = 0;

                       while (my.skill99 < 5) // the npc stays in front of the wall for 5 seconds

                       {

                               my.skill99 += time_step / 16;

                               ent_animate(my, "stand", my.skill22, ANM_CYCLE);

                               my.skill22 += 3 * time_step; // 3 gives the "stand" animation speed

                               wait (1);

                       }

                       my.skill99 = my.pan;

                       my.skill99 += random(180); // and then adds a random pan angle to its initial pan, in order to avoid the wall

                       while (my.pan < my.skill99) // rotate the npc towards the direction given by its new pan angle

                       {

                               my.pan += 10 * time_step;

                               wait (1);

                       }

               }

               wait (1);

       }

}

 

 

F: Ich würde gerne wissen, wie ich die Koordinaten eines Punktes auf der Oberfläche einer Entity bekommen kann, wenn mit der linken Maustaste draufgeklickt wurde.

A: Bitte schön:

 

VECTOR hit_coords;

 

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

       }

}

 

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

{        

       var movement_speed = 20;

       VECTOR temp, players_sensor;

       set (my, INVISIBLE);

       player = my;

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

               camera.pan = my.pan;

               camera.tilt += 5 * mouse_force.y * time_step;

               vec_set (temp.x, my.x);

               temp.z -= 10000;

               temp.z = -c_trace (my.x, temp.x, IGNORE_ME | IGNORE_PASSABLE | USE_BOX) - 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);

       }

}

 

function getcoords_startup()

{

       VECTOR pos1, pos2;

       while (1)

       {

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

               while (mouse_left) {wait (1);}

               beep();

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

               // now "hitvertex" holds the coordinates of the closest vertex to the hit point

               if (mouse_ent) // the mouse has clicked an entity?

                       vec_for_vertex(hit_coords, mouse_ent, hitvertex); // then get the xyz coordinates of "hitvertex"

               wait (1);

       }

}

 

PANEL* coords_pan = // displays the xyz coordinates of "hitvertex"

{

       layer = 15;

       digits(50, 20, 6 ,* , 1, hit_coords.x);

       digits(50, 40, 6 ,* , 1, hit_coords.y);

       digits(50, 60, 6 ,* , 1, hit_coords.z);

       flags = SHOW;

}