Case study 2: Door and Switch

From Open Surge Wiki
Jump to: navigation, search

Door and Switch

In this example, we will be creating a custom door that deactivates whenever a player is touching it's switch. We will be studying two different examples of this object, written by separate coders, and the differences between them.

PLEASE NOTE : A basic understanding of the scripting language and the format of sprite files is needed to continue beyond this point.

The blue door in the game


Example 1

The Sprite

In this example, we will be using an image, created by Celdecea. We will be creating a sprite sheet that allows us to use it in game.

The Image

Blue door.png

The Sprite File

...
// Blue Door
sprite "SD_BLUE_DOOR"
{
   source_file     "images/blue_door.png"
   source_rect     0 0 264 64
   frame_size      24 64
   hot_spot        12 0
   // closed
   animation 0
   {
       repeat      FALSE
       fps         1
       data        0
   }
   // Opening
   animation 1
   {
       repeat      FALSE
       fps         20
       data        1 2 3 4 5 6 7 8 9 10
   }
   // Open
   animation 2
   {
       repeat      FALSE
       fps         8
       data        10
   }
   // Closing
   animation 1
   {
       repeat      FALSE
       fps         20
       data        9 8 7 6 5 4 3 2 1 0
   }
}
sprite "SD_BLUE_BUTTON"
{
   source_file     "images/blue_door.png"
   source_rect     288 0 32 14
   frame_size      32 7
   hot_spot        16 7
   // Up
   animation 0
   {
       repeat      FALSE
       fps         1
       data        0
   }
   // Down
   animation 1
   {
       repeat      FALSE
       fps         1
       data        1
   }
}
...

The Object

Now that we have our sprite defined, it's time to use the game's scripting engine to build an object capable of using it. Save the following as blue_door.obj:

...
// =====================================
// Open Surge
// Version: 0.2.0
// File: blue_door.obj
// Required: Bleeding Edge 616
// Coded by: lunarrush
// =====================================
object "blue_door"
{
 requires 0.2.0
 state "main"
 {
   set_animation "SD_BLUE_DOOR" 0
   set_zindex 0.5
   set_obstacle TRUE
 }
 state "opening"
 {
   set_animation "SD_BLUE_DOOR" 1
   set_obstacle FALSE
   on_animation_finished "open"
 }
 state "open"
 {
   set_animation "SD_BLUE_DOOR" 2
 }
 state "closing"
 {
   set_animation "SD_BLUE_DOOR" 3
   set_obstacle TRUE
   on_animation_finished "main"
 }
}
object "blue_button"
{
 requires 0.2.0
 state "main"
 {
   set_animation "SD_BLUE_BUTTON" 0
   observe_active_player
   set_zindex 0.5
   on_player_collision "open_door"
 }
 state "open_door"
 {
   set_animation "SD_BLUE_BUTTON" 1
   observe_current_player
   change_closest_object_state "blue_door" "opening"
   change_state "keep_open"
 }
 state "keep_open"
 {
   on_player_rect_collision -16 -7 16 7 "keep_open"
   change_state "close_door"
 }
 state "close_door"
 {
   set_animation "SD_BLUE_BUTTON" 0
   change_closest_object_state "blue_door" "closing"
   change_state "main"
 }
}
...

Why the Code Works

  • The door object is a solid object most of the time because of set_obstacle TRUE. We do not want it to impede the player's movement when their teammate is standing on the button though.
  • We use observe_current_player in the blue_button object so that when the player changes who they are controlling the button will not change to observing that player. The observed player is the only one who can activate this object, so it is important that we do not change this after the object has been activated.
    • We use observe_active_player to clear this state when the player who originally stepped on the switch leaves it so that a new player may activate the switch.
  • We use on_player_rect_collision to keep the collision system from attempting to resense the player's collision whenever they move, which prevents animation bugs in the door.

Example 2

The Sprite

In this example, we will examine the same object, coded by somebody else.

The Image

Blue door.png

The Sprite File

...
// -----------------------------------------------------
// blue_door.spr
// A blue door. Step on the closest blue switch to open it.
//
// Author: Alexandre (graphics by Celdecea)
// Version: 0.1
// Date: 2010-08-29
// -----------------------------------------------------
sprite "Blue Door"
{
   source_file         "images/blue_door.png"
   source_rect         0 0 288 64
   frame_size          24 64
   hot_spot            0 0
   // closed
   animation 0
   {
       repeat          FALSE
       fps             64
       data            9 8 7 6 5 4 3 2 1 0
   }
   // open
   animation 1
   {
       repeat          FALSE
       fps             64
       data            0 1 2 3 4 5 6 7 8 9
   }
}
sprite "Blue Switch"
{
   source_file         "images/blue_door.png"
   source_rect         288 0 32 14
   frame_size          32 7
   hot_spot            16 7
   // not pressed
   animation 0
   {
       repeat          TRUE
       fps             8
       data            0
   }
   // pressed
   animation 1
   {
       repeat          TRUE
       fps             8
       data            1
   }
}
...

The Object

This can also be saved as blue_door.obj in the objects folder of your open surge directory.

...
// -----------------------------------------------------
// blue_door.obj
// A blue door. Step on the closest blue switch to open it.
//
// Author: Alexandre (graphics by Celdecea)
// Version: 0.1
// Date: 2010-08-29
// -----------------------------------------------------
object "Blue Door"
{
   requires 0.1.4
   state "main"
   {
       set_animation "Blue Door" 0
       change_state "closed"
   }
   state "closed"
   {
       set_animation "Blue Door" 0
       set_obstacle TRUE
   }
   state "open"
   {
       set_animation "Blue Door" 1
       set_obstacle FALSE
   }
}
object "Blue Switch"
{
   requires 0.1.4
   state "main"
   {
       set_animation "Blue Switch" 0
       change_state "not pressed"
   }
   state "not pressed"
   {
       // if any player touches this switch, jump to "pressing"
       observe_all_players
       on_player_rect_collision -4 -3 4 0 "pressing"
   }
   state "pressing"
   {
       set_animation "Blue Switch" 1
       play_sample "switch"
       play_sample "open door"
       change_closest_object_state "Blue Door" "open" // this opens the door
       change_state "pressed"
   }
   state "pressed"
   {
       // if the player who pressed the switch leaves, jump to "unpressing"
       on_player_rect_collision -4 -3 4 0 "pressed"
       change_state "unpressing"
   }
   state "unpressing"
   {
       set_animation "Blue Switch" 0
       play_sample "close door"
       change_closest_object_state "Blue Door" "closed" // this closes the door
       change_state "not pressed"
   }
}
...

Why the Code Works

  • Instead of using 4 animations for the blue door, this only uses two and the principal that a false animation will not repeat itself unless it is called again.
  • The blue door uses fewer states because it does not need to jump between animations as often.
  • observe_all_players allows this switch to be observing every player at the same time, therefore this is the way Alexandre mitigated the fact that the active player was subject to change.
  • Alexandre uses a rect hitbox, the same as we did in our previous example.
  • Alexandre uses sound effects.

What we've learned

  • How to use state changing to communicate data between two objects.
  • The importance of the 'observed' player.
  • When to use on_player_rect_collision.
  • That there is more than one solution to the same problem.