Game Development Community

BUG: wrong level loaded

by Pedro Vicente · in iTorque 2D · 08/14/2011 (12:52 pm) · 10 replies

Build: iTorque 1.4.1

Platform: Tried in Windows only; complete project attached.

Issue:

While trying to extend this resource to work with 3 levels I found some unexpected behavior. At this moment I am not sure if it is an engine bug or some incorrect use of the function loadSceneGraph, shown in the resource

Torque Minimal Template -- Part 5. Levels and sound

In this post I present the complete source code for a project that reproduces the issue.

The project has 3 levels:

Main menu: shows 2 buttons; each button loads a level
Level_01: shows a button to return to main menu
Level_02: shows a button to return to main menu

Issue is that pressing the buttons on the levels, loads the other level instead of loading the main menu level; this happens only at a second pressing of the buttons; running the Torsion debugger shows that the OnMouseDown event is triggered, but it somehow loads the level_02 instead of the main menu level.

Loading the project this level shows up:


www.space-research.org/games/garage_games/127369_1.png

Pressing one button loads this level:

www.space-research.org/games/garage_games/127369_2.png

Pressing the other button loads this level:

www.space-research.org/games/garage_games/127369_3.png

Issue is that after some level switching the level_01 button (that should load the main menu level) starts loading the level_02

This is the code for the button class that loads the main menu level

function ButtonHome::onMouseDown( %this, %modifier, %worldPosition, %clicks )
{
   
   loadSceneGraph( MainMenuSceneGraph );

}


Download complete project from here




#1
08/14/2011 (1:09 pm)
file menu.cs

//---------------------------------------------------------------------------------------------
// menu.cs
//---------------------------------------------------------------------------------------------

// .....................................................................................
function MainMenuSceneGraph::OnAdd(%this)
{
   createButton( %this, "Level_01_Button",  "ButtonPlayImageMap",  0,  0,   128, 128);
   createButton( %this, "Level_02_Button",  "ButtonLevelImageMap", 0,  300, 128, 128);
   %this.CreateBackground();
   makeTextObject( %this, "I am in the Main menu");
}

// .....................................................................................
function MainMenuSceneGraph::CreateBackground( %this )
{
    %obj = new t2dStaticSprite() 
    { 
        scenegraph = %this; 
    };
    %obj.setVisible( true );
    %obj.setLayer( 20 );
    %obj.setImageMap( "BackgroundImageMap" );
    %obj.setSize( 768, 1024 );
}
#2
08/14/2011 (1:12 pm)
file level_01.cs

//---------------------------------------------------------------------------------------------
// level_01.cs
//---------------------------------------------------------------------------------------------

// .....................................................................................
function SceneGraphLevel_01::OnAdd(%this)
{
   createButton( %this, "ButtonHome", "ButtonHomeImageMap", 0,  0, 128, 128);
   %this.CreateBackground();
   makeTextObject( %this, "I am in Level 1");
}

// .....................................................................................
function SceneGraphLevel_01::CreateBackground( %this )
{
    %obj = new t2dStaticSprite() 
    { 
        scenegraph = %this; 
    };
    %obj.setVisible( true );
    %obj.setLayer( 20 );
    %obj.setImageMap( "BackgroundImageMap" );
    %obj.setSize( 768, 1024 );
}
#3
08/14/2011 (1:14 pm)
file level_02.cs

//---------------------------------------------------------------------------------------------
// level_02.cs
//---------------------------------------------------------------------------------------------

// .....................................................................................
function SceneGraphLevel_02::OnAdd(%this)
{
   %this.CreateBackground();
   createButton( %this, "ButtonHome", "ButtonHomeImageMap", 0, 0, 128, 128);
   makeTextObject( %this, "I am in Level 2");
   
}

// .....................................................................................
function SceneGraphLevel_02::CreateBackground( %this )
{
    %obj = new t2dStaticSprite() 
    { 
        scenegraph = %this; 
    };
    %obj.setVisible( true );
    %obj.setLayer( 20 );
    %obj.setImageMap( "BackgroundImageMap" );
    %obj.setSize( 768, 1024 );
}
#4
08/14/2011 (1:15 pm)
file main.cs PART1

// main.cs
// (c) Pedro Vicente
// iTorque2D, Torque2D minimal template
// Notes: folders are 
// /data/images -- where we store images
// /data/fonts  -- store fonts
// /scripts     -- game script code


function createButton( %scenegraph_obj, %class, %image_map, %xpos, %ypos, %xsize, %ysize )
{
    %obj = new t2dStaticSprite() 
    { 
        scenegraph = %scenegraph_obj; 
        class = %class;
        useMouseEvents = "1";
    };
    %obj.setVisible( true );
    %obj.setImageMap( %image_map );
    %obj.setPosition( %xpos, %ypos );	
    %obj.setSize( %xsize, %ysize );
}


// .......................................................................................
function makeTextObject( %scenegraph_obj, %text)
{
    %obj = new t2dTextObject() 
    { 
        scenegraph      =  %scenegraph_obj;
        text            = "";
        textAlign       = "Center";
        font            = "Times New Roman Bold";
        hideOverflow    = false;
        autoSize        = true;
        Visible         = true;
        
        blendIgnoreTextureAlpha = "0";
        wordWrap = "0";
        hideOverflow = "0";
        aspectRatio = "1";
        lineSpacing = "0";
        characterSpacing = "0";
        autoSize = "1";
        filter = "1";
        integerPrecision = "1";
        noUnicode = "0";
        hideOverlap = "0";        
        
    };
    %fontsize = 48;
    %obj.removeAllFontSizes();
    %obj.addFontSize( %fontsize );
    %obj.LineHeight = %fontsize + 10;  
    %obj.setBlendColor( 0.0, 0.0, 0.0, 1.0 );
    %obj.setSize( 40 );
    %obj.setLayer( 5 );
    %obj.setVisible( true );
    %obj.setPosition( 0, -200 );
    %obj.text = %text;
    return %obj;
}



function setScreenModeWindows()
{
   if( $platform $= "windows" ) 
   {
      if ( $pref::iDevice::ScreenOrientation  == $iDevice::constant::Landscape )
      {
         if( $platform_simul $= "ipad" ) 
         setScreenMode( 1024, 768, 32, false );
         else
         setScreenMode( 960, 640, 32, false );
      }
      if ( $pref::iDevice::ScreenOrientation  == $iDevice::constant::Portrait )
      {
         if( $platform_simul $= "ipad" ) 
         setScreenMode( 768, 1024, 32, false );
         else
         setScreenMode( 640, 960, 32, false );
      }
   }
}

function initCanvas(%name)
{
   if (!createCanvas(%name)) 
   {
      quit();
      return;
   }

}

function resetCanvas()
{
   if (isObject(Canvas))
   {
      Canvas.repaint(); 
   }
}

dbgSetParameters( 6060, "password", false );
setRandomSeed();

$pref::Video::displayDevice        = "OpenGL";
$Gui::fontCacheDirectory           = expandFilename("data/fonts");
$iDevice::constant::iPhone         = 0;
$iDevice::constant::iPad           = 1;
$iDevice::constant::iPhone4        = 2;
$iDevice::constant::Landscape      = 0;
$iDevice::constant::Portrait       = 1;
$pref::iDevice::iAdOnTop           = 1;
$pref::iDevice::ScreenOrientation  = $iDevice::constant::Portrait;
$platform_simul                    = "iphone";
$musicStreamHandle                 = 0;
$Game::UsesAudio                   = 1;
$is_iDevice                        = false;
$debug_mode                        = true;

///
/// Audio
///

$pref::Audio::driver = "OpenAL";
$pref::Audio::forceMaxDistanceUpdate = 0;
$pref::Audio::environmentEnabled = 0;
$pref::Audio::masterVolume   = 0.8;

exec("scripts/audio.cs");


if( $platform $= "iphone" )
{
   $pref::iDevice::DeviceType          = $iDevice::constant::iPhone;
}
else if( $platform $= "iphone4" )
{
   $pref::iDevice::DeviceType          = $iDevice::constant::iPhone4;
}
else if( $platform $= "ipad" )
{
   $pref::iDevice::DeviceType          = $iDevice::constant::iPad;
}


new GuiCursor(DefaultCursor)
{
   hotSpot = "4 4";
   renderOffset = "0 0";
   bitmapName = "data/images/cursor";
};

initCanvas("Game");

// Start up the audio system.
if( $Game::UsesAudio )
   initializeOpenAL();

// Set a default cursor.
Canvas.setCursor(DefaultCursor);
Canvas.showCursor();
#5
08/14/2011 (1:17 pm)
file main.cs PART2

//---------------------------------------------------------------------------------------------
// GuiDefaultProfile is a special profile that all other profiles inherit defaults from. It
// must exist.
//---------------------------------------------------------------------------------------------
new GuiControlProfile (GuiDefaultProfile)
{
   tab = false;
   canKeyFocus = false;
   hasBitmapArray = false;
   mouseOverSelected = false;

   // fill color
   opaque = true;
   fillColor = "0 0 0";
   fillColorHL = "244 244 244";
   fillColorNA = "244 244 244";

   // border color
   border = 1;
   borderColor   = "40 40 40 100";
   borderColorHL = "128 128 128";
   borderColorNA = "64 64 64";

   // font
   fontType = "Arial";
   fontSize = 14;

   fontColor = "0 0 0";
   fontColorHL = "32 100 100";
   fontColorNA = "0 0 0";
   fontColorSEL= "80 80 80";

   // bitmap information
   bitmap = "";
   bitmapBase = "";
   textOffset = "0 0";

   // used by guiTextControl
   modal = true;
   justify = "left";
   autoSizeWidth = false;
   autoSizeHeight = false;
   returnTab = false;
   numbersOnly = false;
   cursorColor = "0 0 0 255";

   // sounds
   soundButtonDown = "";
   soundButtonOver = "";

};

new GuiControl(mainScreenGui) 
{
   canSaveDynamicFields = "0";
   isContainer = "1";
   Profile = "GuiDefaultProfile";
   HorizSizing = "width";
   VertSizing = "height";
   Position = "0 0";
   canSave = "1";
   Visible = "1";
   hovertime = "1000";

   new t2dSceneWindow(sceneWindow2D) 
   {
      canSaveDynamicFields = "0";
      isContainer = "0";
      Profile = "GuiDefaultProfile";
      HorizSizing = "width";
      VertSizing = "height";
      Position = "0 0";
      canSave = "1";
      Visible = "1";
      tooltipprofile = "GuiDefaultProfile";
      hovertime = "1000";
      lockMouse = "0";
      useWindowMouseEvents = "1";
      useObjectMouseEvents = "1";
   };

};

//landscape
if ( $pref::iDevice::ScreenOrientation  == $iDevice::constant::Landscape )
{
   if( $platform $= "iphone" || $platform_simul $= "iphone")  
   {
      mainScreenGui.Extent = "480 320";
      sceneWindow2D.Extent = "480 320";
   }
   
   else if( $platform $= "ipad" || $platform_simul $= "ipad")  
   {
      mainScreenGui.Extent = "1024 768";
      sceneWindow2D.Extent = "1024 768";
   }
   else if( $platform $= "iphone4" || $platform_simul $= "iphone4") 
   {
      mainScreenGui.Extent = "960 640";
      sceneWindow2D.Extent = "960 640";
   }
}
//portrait
else if ( $pref::iDevice::ScreenOrientation  == $iDevice::constant::Portrait )
{
   if( $platform $= "iphone" || $platform_simul $= "iphone")  
   {
      mainScreenGui.Extent = "320 480";
      sceneWindow2D.Extent = "320 480";
   }
   
   if( $platform $= "ipad" || $platform_simul $= "ipad")  
   {
      mainScreenGui.Extent = "768 1024";
      sceneWindow2D.Extent = "768 1024";
   }
   else if( $platform $= "iphone4" || $platform_simul $= "iphone4") 
   {
      mainScreenGui.Extent = "640 960";
      sceneWindow2D.Extent = "640 960";
   }
}



Canvas.setContent(mainScreenGui);
setScreenModeWindows();

exec("scripts/datablocks.cs");
exec("scripts/level_01.cs");
exec("scripts/level_02.cs");
exec("scripts/menu.cs");
#6
08/14/2011 (1:23 pm)
file main.cs PART3

function loadSceneGraph( %scenegraph_name )
{
   
   %scenegraph = sceneWindow2D.getSceneGraph();
   
   if (isObject(%scenegraph))
   {
      %sceneObjectList = %sceneGraph.getSceneObjectList();
      // And finally, notify all the objects that they were loaded.
      for (%i = 0; %i < getWordCount(%sceneObjectList); %i++)
      {
         %sceneObject = getWord(%sceneObjectList, %i);
         if( %sceneObject.isMethod( "onLevelEnded" ) )
            %sceneObject.onLevelEnded(%sceneGraph);
      }
      
      // Notify the scenegraph that the level ended.
      if( %sceneGraph.isMethod( "onLevelEnded" ) )
         %sceneGraph.onLevelEnded(); 
         
      %scenegraph.clearScene(true);
   }
   
   
   if (isObject(%scenegraph))
   {
      if( isObject( %scenegraph.getGlobalTileMap() ) )
         %scenegraph.getGlobalTileMap().delete();
         
      %scenegraph.delete();
   }

   if ( $pref::iDevice::ScreenOrientation  == $iDevice::constant::Landscape )
   {
      if( $platform $= "ipad" || $platform_simul $= "ipad") 
      {

         %scenegraph = new t2dSceneGraph( %scenegraph_name ) 
         {
            cameraPosition = "0 0";    
            cameraSize = "1024 768";    
         };
      }
      else
      {
         %scenegraph = new t2dSceneGraph( %scenegraph_name ) 
         {
            cameraPosition = "0 0";    
            cameraSize = "960 640";    
         };          
      } 
   }
   else if ( $pref::iDevice::ScreenOrientation  == $iDevice::constant::Portrait )
   {
      if( $platform $= "ipad" || $platform_simul $= "ipad") 
      {

         %scenegraph = new t2dSceneGraph( %scenegraph_name ) 
         {
            cameraPosition = "0 0";    
            cameraSize = "768 1024";    
         };
      }
      else
      {
         %scenegraph = new t2dSceneGraph( %scenegraph_name ) 
         {
            cameraPosition = "0 0";    
            cameraSize = "640 960";    
         };          
      } 
      
      
   }


   sceneWindow2D.setSceneGraph(%scenegraph);
   %scenegraph.performPostInit();
   %cameraPosition = sceneWindow2D.getCurrentCameraPosition();
   %cameraSize = t2dVectorSub(getWords(sceneWindow2D.getCurrentCameraArea(), 2, 3),
                              getWords(sceneWindow2D.getCurrentCameraArea(), 0, 1));
                              
   if (%scenegraph.cameraPosition !$= "")
      %cameraPosition = %scenegraph.cameraPosition;
   if (%scenegraph.cameraSize !$= "")
      %cameraSize = %scenegraph.cameraSize;
      
   sceneWindow2D.setCurrentCameraPosition(%cameraPosition, %cameraSize);

}


loadSceneGraph( MainMenuSceneGraph );

   
//---------------------------------------------------------------------------------------------
// onExit
// Called when the engine is shutting down. 
//---------------------------------------------------------------------------------------------
function onExit()
{  
   %scenegraph = sceneWindow2D.getSceneGraph();
   %scenegraph.getGlobalTileMap().delete();
   %scenegraph.delete();
   
}
#7
08/14/2011 (4:40 pm)
file datablocks.cs

new t2dImageMapDatablock(BackgroundImageMap) 
{
      imageName = "data/images/bk_menu.png";
      imageMode = "FULL";
};


   
//---------------------------------------------------------------------------------------------
// buttons
//---------------------------------------------------------------------------------------------   


new t2dImageMapDatablock(ButtonHomeImageMap) 
{
      imageName = "data/images/button_home.png";
      imageMode = "FULL";
};


   
new t2dImageMapDatablock(ButtonPlayImageMap) 
{
      imageName = "data/images/button_play.png";
      imageMode = "FULL";
};

   
new t2dImageMapDatablock(ButtonLevelImageMap) 
{
      imageName = "data/images/button_level.png";
      imageMode = "FULL";
};
   
//---------------------------------------------------------------------------------------------
// audio
//---------------------------------------------------------------------------------------------      
  
new AudioDescription(SoundOnce)
{
   volume		= 1.0;
   type		   = 0;
   isLooping	= false;
   is3D		   = false;
};

new AudioProfile(beepSound)
{
   filename	   = "data/audio/beep.wav";
   description = "SoundOnce";
   preload 	   = true;
}; 

  
//---------------------------------------------------------------------------------------------
// button classes
//---------------------------------------------------------------------------------------------   


// .......................................................................................
function ButtonHome::onMouseDown( %this, %modifier, %worldPosition, %clicks )
{
   loadSceneGraph( MainMenuSceneGraph );
   alxPlay("beepSound"); 
}

// .......................................................................................
function Level_01_Button::onMouseDown( %this, %modifier, %worldPosition, %clicks )
{   
   loadSceneGraph( SceneGraphLevel_01 );
   alxPlay("beepSound"); 
}

// .......................................................................................
function Level_02_Button::onMouseDown( %this, %modifier, %worldPosition, %clicks )
{   
   loadSceneGraph( SceneGraphLevel_02 );
   alxPlay("beepSound"); 
}
#8
08/14/2011 (7:26 pm)
a little bit of Torsion debugging shows that the issue is when the "home" button is pressed, this code here is executed, which is OK

// .......................................................................................
function ButtonHome::onMouseDown( %this, %modifier, %worldPosition, %clicks )
{
   loadSceneGraph( MainMenuSceneGraph );
   alxPlay("beepSound"); 
}

But the issue is that the code below is *also* called, the code for the button that loads the level_02. Question is: why is this function being called ?

function Level_02_Button::onMouseDown( %this, %modifier, %worldPosition, %clicks )
{   
   loadSceneGraph( SceneGraphLevel_02 );
   alxPlay("beepSound"); 
}
#9
08/15/2011 (6:21 am)
Too much for me to debug here in the forum. I'll download the project to see if anything shows up in my debugging. I'm debugging two other users' projects right now, so I probably would not get to this today. If I do see something unusual from the forum, I will let you know.
#10
08/15/2011 (8:48 am)
Thanks Michael.
A solution that avoids this behavior was posted here
www.garagegames.com/community/forums/viewthread/127309/2#comment-814121

Many thanks to Daniel Liverance