|
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.
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 }
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; }
|