Totem Ball Game

De DigiWiki.

(Différences entre les versions)
 
Ligne 3 : Ligne 3 :
* Placez le script gametotem.lsl dans un cube nomée "gametotem"
* Placez le script gametotem.lsl dans un cube nomée "gametotem"
* Placez la shpere "gameball" dans l'inventaire du cube "gametotem"
* Placez la shpere "gameball" dans l'inventaire du cube "gametotem"
-
* Cliquer sur le cube "fametotem" pour démarrer le jeu
+
* Cliquer sur le cube "gametotem" pour démarrer le jeu
gametotem.lsl
gametotem.lsl

Version actuelle en date du 19 mai 2015 à 23:45

  • Placez le script gameball.lsl dans une sphere nomée "gameball"
  • Prendre la shpere "gameball" dans votre inventaire
  • Placez le script gametotem.lsl dans un cube nomée "gametotem"
  • Placez la shpere "gameball" dans l'inventaire du cube "gametotem"
  • Cliquer sur le cube "gametotem" pour démarrer le jeu

gametotem.lsl

// gametotem.lsl
 
// game_field_size defines the range of the game perimeter
integer game_field_size = 10;
// the list of balls we have spawned, so we know who to clean up
list balls = [];
// a function to spawn one ball
spawn_ball(integer is_red) {
  // turn physics off, so the totem isn't shifted around
  llSetStatus(1, FALSE);
  // spawn a new object, "gameball" must be in this object's inventory 
  llRezObject("gameball", llGetPos()+<0,0,1>, 
    <-3+llFrand(6),-3+llFrand(6),1>, ZERO_ROTATION, is_red);
  llSetStatus(1, TRUE);
}
// a function to sends a message using the private channel
send_message(key child_id, string message) {
  llShout(1235, (string)child_id+" "+message);
}
 
// function to cleanup all the balls we have spawned
despawn_balls() {
  integer i;
  for(i = 0; i < llGetListLength(balls); i++) {
    send_message(llList2Key(balls, i), "die");
  }
}
// function to reset our scanner and gameballs
reset() {
  // stop a previous sensor if there was one
  llSensorRemove();
 
  // cleanup any previous balls that might be around
  despawn_balls();
 
  // spawn 3 red balls, and 3 blue balls
  spawn_ball(TRUE);
  spawn_ball(TRUE);
  spawn_ball(TRUE);
  spawn_ball(FALSE);
  spawn_ball(FALSE);
  spawn_ball(FALSE);
 
  // set a green message over the totem's head
  llSetText("Let the game begin!", <0,255,0>, 1.0);
 
  // turn on our sensor that actually runs the game logic every 1.0 sec
  llSensorRepeat("","",ACTIVE,200.0, 3.1415926, 1.0);
}
 
default {
  state_entry() {
    llSetText("Touch me to start.", <255, 255,255>, 1.0);
  }
 
  on_rez(integer param) {
    llSetText("Touch me to start.", <255, 255,255>, 1.0);
  }
  // touching the totem turns the game on and off.  
  touch(integer total) {
    llSetText("Starting...", <255, 255,255>, 1.0);
    state started;
  }
}
 
state started {
  state_entry() {
    reset();
  }
 
 
  // object_rez is fired to notify us that 
  // llRezObject successfully spawned a new child
  object_rez(key child_id) {
    // keep track of the new child, for later clean up
    balls += child_id;
  }
  // touching the totem turns the game on and off.
  touch(integer total) {
    // clean up any spawned balls
    despawn_balls();
    llSetText("Touch me to start.", <255,255,255>, 1.0);
    // switch to the default 'stopped' state
    state default;
  }
  sensor(integer total) {
    integer blue_count = 0;
    integer red_count = 0;
    integer i;
    for(i = 0; i < total; i ++) {
      string name = llDetectedName(i);
      if( name == "redgameball" || name == "bluegameball" ) {
        vector pos = llGetPos();
        float dist = llVecDist(pos, llDetectedPos(i));
        if( dist > game_field_size ) {
          // send a message out on the game channel: "reset"
          // all the nearby listen events will fire
          // but the key filter in gameball's listen handler
          // makes sure the only the correct ball resets
          send_message((string)llDetectedKey(i),"reset "
            +(string)(pos.x)+" "+(string)pos.y+" "+(string)pos.z);
        }
      }
    }
    // check the victory condition
    for(i = 0; i < total; i ++) {
      if( llDetectedName(i) == "redgameball" ) {
        red_count++;
      } else if( llDetectedName(i) == "bluegameball" ) {
        blue_count++;
      }
    }
    if( red_count == 0 ) {
      llSetText("Blue wins! Touch to reset.", <255,0,0>, 1.0);
      llSensorRemove();
    } else if( blue_count == 0 ) {
      llSetText("Red wins! Touch to reset.", <255,0,0>, 1.0);
      llSensorRemove();
    }
  }
}

gameball.lsl

// gameball.lsl
 
// last_collide will serve as a marker to help us enforce game rules
string last_collide = "";
 
// this keeps track of our listening key, 0 means not listenting, > 0 
// is a unique identifier
integer listen_id = 0;
 
// reset is called to clean up our variables
// and make sure we are properly listening
reset_listener () {  
  // if we had a listener already, remove it first
  if (listen_id > 0) {
    llListenRemove (listen_id);
    listen_id = 0;
  }
  // now register a listener for channel 1235  
  listen_id = llListen (1235, "", "", ""); 
 
}
 
// reset position is used by the listen event handler
// it moves us back into the game, using llSetPos ()
reset_position (float x, float y, float z) {
  // turn off physics while we teleport the object
  llSetStatus (1, FALSE);
  // if physics is on, you can't use llSetPos ()
  // since you must create and apply forces to account for any movement
  // but with it off, we can simply set the position without fuss.
  llSetPos (<x, y, z+2>); // start 3 meters above the game totem
  // turn physics back on and drop the ball on the totem
  llSetStatus (1, TRUE); 
}
 
// reset the ball's current color, this is used by listen, in reaction to a reset message
// implement critical game logic as well, since it determines if colors should swap based 
// on who hit who last
reset_color () {
  // if the last collision was 
  // a game ball of some kind but not our own color
  if ((last_collide == "redgameball" || last_collide == "bluegameball")
    && llGetObjectName () != last_collide ) {
    // swap our color
    if (llGetObjectName () == "redgameball") {
      llSetColor (<0, 0, 255>, ALL_SIDES);
      llSetObjectName ("bluegameball");
    } else if (llGetObjectName () == "bluegameball") {
      llSetColor (<255, 0, 0>, ALL_SIDES);
      llSetObjectName ("redgameball");
    }
  }
}
 
default { 
  // when the gameball is created enforce some standards on the ball
  state_entry () {
    // the object we are attached to must be a regulation size
    llSetPrimitiveParams ([PRIM_SIZE, <.6,.6,.6>]);
    // and must be a 90% hollow sphere
    llSetPrimitiveParams ([PRIM_TYPE, PRIM_TYPE_SPHERE, 
      0, // holeshape
      <0.0, 1.0, 0.0>, // cut
      90.0, // hollow
      <0.0, 0.0, 0.0>, // twist
      <0.0, 1.0, 0.0> // dimple
    ]);
 
    if (llGetObjectName () == "Object") {           
      llSetObjectName ("gameball");
    }
 
    // it must obey physical laws
    llSetStatus (1, TRUE);
 
    // it must use a blank texture 
    // from lswiki: this is the key of the 'Blank' texture
    llSetTexture ("5748decc-f629-461c-9a36-a35a221fe21f", ALL_SIDES);
    // attach our listener
    reset_listener ();
    // forget about previous collisions
    last_collide = "";
 
  }
 
  // when the ball is created
  on_rez (integer start_param) {
    // use the optional start_param to determine which color
    reset_listener ();
    // forget about previous collisions
    last_collide = "";
 
    if (start_param == 0) {
      llSetColor (<0, 0, 255>, ALL_SIDES);
      llSetObjectName ("bluegameball");
    } else {
      llSetColor (<255, 0, 0>, ALL_SIDES);
      llSetObjectName ("redgameball");
    }
  }
  // when the ball collides with something
  collision_start (integer total_number) {
    string other = llDetectedName (0);
    // if we collided with some other gameball, write it down
    if (other == "redgameball" || other == "bluegameball") {
      last_collide = other;
    } else if (llDetectedType (0) & AGENT) {
      // if we collided with an agent, consider ourselves kicked.
      last_collide = (string) llDetectedKey (0);
      // this code gets a vector of magnitude 2, 
      // pointing away from the avatar that kicked us.
      vector kick_vector = llGetPos () - llDetectedPos (0);
      kick_vector.z = 0;
      kick_vector = llVecNorm (kick_vector)*2;
      // use this vector as a force vector and apply it to the ball
      llApplyImpulse (kick_vector, FALSE);
    }
  }
  // when the ball is touched by someone
  touch (integer total_number) {
    last_collide = "";
    vector kick_vector = llGetPos () - llDetectedPos (0);
    // scale to a fixed magnitude: 2 in the case of a touch
    kick_vector.z = 0;
    kick_vector = llVecNorm (kick_vector)*2;
    kick_vector.z = .1;
    llApplyImpulse (kick_vector, FALSE);
  }
  listen (integer channel, string name, key id, string message) {
    // llParseString2List will split the input message on spaces
    list cmdline = llParseString2List (message, [" "], [" "]);
    // the first param must be this object's key
    string k = llList2String (cmdline, 0);
    if (k == (string) llGetKey ()) {
      string s = llList2String (cmdline, 1);
      llWhisper (0, "Gameball received command: "+s);                
      if (s == "reset") {
        // if it is, then we need to reset
        float x = llList2Float (cmdline, 2);
        float y = llList2Float (cmdline, 3);
        float z = llList2Float (cmdline, 4);
        reset_color ();
        reset_position (x, y, z);
        last_collide = ""; // reset the last collision
      }
      else if (s == "die") {
        llDie ();
      }
    }
  }
}
Outils personnels
  • Cette page a été consultée 1 986 fois.
donate
Google Ads