Torque 2D/GenreTutorials/AsteroidsPlayer

From TDN

Sadly, because of my day-job and my final exams i don't have time to write this tutorial right now, but i want to share what i did so i will just post the source of the game here, so maybe someone else can write a tutorial around it, or i will write one when I'm done with my finals (around july).

The source is ugly, comments are in german and there are many hacks where I just didn't know any better, for this was my learning project ;) So if you see something you could do better, just change it...thats what a wiki is for ;)

have fun!

The Source

main.cs

package retroids
{
   
   function loadKeybindings()
   {
      Parent::loadKeybindings();
      exec("./gameScripts/defaultBind.cs");
   }
   
	// Start-up.
   function onStart()
   {
      Parent::onStart();
      echo("\n--------- Initializing GAME: retroids ---------");
      
      // Load Client Scripts.
      exec("./gameScripts/game.cs");
      
      // Initialise Client.
      initializeGame();
   }
	
	// Shutdown.
   function onExit()
   {
      // Call Parent.
      Parent::onExit();
   }
	
};

activatePackage(retroids);

game.cs

//-----------------------------------------------------------------------------
// Torque 2D. 
// Copyright (C) GarageGames.com, Inc.
//-----------------------------------------------------------------------------

// --------------------------------------------------------------------
// Initialise Client.
// --------------------------------------------------------------------
function initializeGame()
{
	// Initialise Base Client.
	InitBaseClient();
	
	// Key-Bindings.
	// LEVIN: Auskommentieren für Release
	GlobalActionMap.bind(keyboard, tilde, ToggleConsole);
	GlobalActionMap.bindCmd(keyboard, "alt enter", "", "toggleFullScreen();");
	
		
	// Initialise Canvas.
	// LEVIN: Hier den Fenster-Namen ändern
	SetCanvasTitle("Retroids");

	// StandardCursor laden und abschalten
	// mehr Infos unter http://www.garagegames.com/mg/forums/result.thread.php?qt=28399
	Canvas.setCursor(DefaultCursor);
	Canvas.cursorOff();

	// Load-up Datablocks.	
	exec("~/data/content/datablocks.cs");
	
	// Schriften laden
	exec("~/data/content/profiles.cs");
	
	// Load-up GUIs.
	exec("~/gui/mainScreenGui.gui");
	exec("~/gui/splashScreen.gui");		
	exec("~/gui/menuGui.gui");	
	exec("~/gui/optionsGui.gui");
	exec("~/gui/optionsGui.cs");
	
	// Player laden
	exec("./player.cs");
	
	// Splashscreen anzeigen
	loadGarageGames();
	
}

// --------------------------------------------------------------------
// Destroy Client.
//
// Here we destroy the SceneGraph.
// --------------------------------------------------------------------
function destroyClient()
{
	// Destroy fxSceneGraph2D.
	if ( isObject(t2dSceneGraph) )
		t2dSceneGraph.delete();	
}

// -----------------------------------------
// Globals
// -----------------------------------------
 $gameInfo = new ScriptObject();
 $gameInfo.level = 0;
 $gameInfo.lives = 0;
 $gameInfo.score = 0;
 
 $gameConstants = new ScriptObject();
 $gameConstants.nebulaLayer = 10;
 $gameConstants.playerLayer = 0;
 $gameConstants.playerGroup = 0;
 $gameConstants.bulletsLayer = 0;
 $gameConstants.asteroidsLayer = 1;
 $gameConstants.asteroidsGroup = 1;
 $gameConstants.playerAssetsLayer = 2;
 
 
 


// -----------------------------------------
// Game functions
// -----------------------------------------
function initGame()
{
   if ( isObject(t2dSceneGraph) )
      t2dSceneGraph.delete();	  
   new t2dSceneGraph(t2dSceneGraph);  
   sceneWindow2D.setSceneGraph( t2dSceneGraph );  
   sceneWindow2D.setCurrentCameraPosition( "0 0 100 75" );
   
   createPlayer();
	  initLevel("1");
	  updateLivesLabel();
	  
   %background = new t2dStaticSprite() { scenegraph = t2dSceneGraph; };
   %background.setPosition("0 0");
   %background.setSize("100 75");
   %background.setImageMap(starsImageMap);
   %background.setLayer(31);	
	  
   %nebula = new t2dParticleEffect() { scenegraph = t2dSceneGraph; };
		 %nebula.loadEffect("~/data/particles/ast_clouds.eff");
		 %nebula.setPosition((-40 + (getRandom() * 80)) SPC (-25 + (getRandom() * 50)));
   %nebula.setLayer($gameConstants.nebulaLayer);
   %nebula.playEffect();
   
	  
 //t2dSceneGraph.setDebugOn( 0 ); // Debug Info
	//t2dSceneGraph.setDebugOn( 1 ); // Bounding Boxes
	//t2dSceneGraph.setDebugOn( 2 ); // Mounting Points
	//t2dSceneGraph.setDebugOn( 3 ); // Particle
	//t2dSceneGraph.setDebugOn( 5 ); // Kollisions Polygone
}

function initLevel(%lvl)
{
	newPlayer();
	$gameInfo.level = %lvl;
	
	showLevelLabel();
	

	
	if (%lvl ==  1) {
		createAsteroid(1, -40, -30);
		createAsteroid(1, 40, 30);
	}	
	if (%lvl ==  2) {
		createAsteroid(1, -40, -30);
		createAsteroid(1, -40, 30);
		createAsteroid(1, 40, 30);
	}
	if (%lvl ==  3) {
		createAsteroid(1, -40, -30);
		createAsteroid(1, 40, 30);
		createAsteroid(1, -40, 30);
		createAsteroid(1, 40, -30);
	}
	if (%lvl == 4) {
   backToMenu(true);	   
	}
	
}

function backToMenu(%gameOver) 
{
   if (!%gameOver) {
      t2dSceneGraph.setScenePause( true );
      showResumeButton();      
   } else {
      hideResumeButton();      
   }
   Canvas.setContent(menuGui);
}



function createAsteroid(%size, %posX, %posY)
{
	%asteroid = new t2dStaticSprite() { scenegraph = t2dSceneGraph; };
	%asteroid.setPosition(%posX SPC %posY);
	%asteroid.setLinearVelocity((-20 + (getRandom() * 40)) SPC (-20 + (getRandom() * 40)));
	%asteroid.setAngularVelocity((-20 + (getRandom() * 40)));
	%asteroid.setMaxLinearVelocity(15 + (%size * 5));
	%asteroid.setMaxAngularVelocity(180);
	%asteroid.tag = "Asteroid" @ %size;
	
	%asteroid.setSize(10 / %size SPC 10 / %size);
	

	%type = getRandom() * 4;
	// echo("Asteroid - size" SPC %size SPC "type" SPC %type SPC "created");
	
	
	if (%size == 1) 
	{
		%asteroid.setImageMap(asteroidImageMap, %type);
	}
	if (%size == 2)
	{
		%asteroid.setImageMap(asteroid2ImageMap, %type);	
	}
	if (%size == 3)
	{
		%asteroid.setImageMap(asteroid3ImageMap, %type);
	}
	
	%asteroid.setWorldLimit(NULL, "-60 -47.5 60 47.5", true);
	
	%asteroid.setGraphGroup($gameConstants.asteroidsGroup);
	%asteroid.setLayer($gameConstants.asteroidsLayer);
	
	%asteroid.setCollisionActive(true, true);
	%asteroid.setCollisionPhysics(true, true);
	%asteroid.setCollisionMaterial(asteroidMaterial);
	%asteroid.setCollisionPolyPrimitive(8);
	%asteroid.setCollisionResponse(rigid);
	%asteroid.setCollisionGroups($gameConstants.playerGroup, $gameConstants.asteroidsGroup);
	%asteroid.setCollisionCallback(false);
}


function t2dSceneObject::onWorldLimit(%this, %limitMode, %limit)
{
	//if (%this == $player) 
	//{
		if (%limit $= "top")
		{
			%this.setPositionY(37.5);
		} // top
		if (%limit $= "bottom")
		{
			%this.setPositionY(-37.5);
		} // bottom
		if (%limit $= "right")
		{
			%this.setPositionX(-50);
		} // right
		if (%limit $= "left")
		{
			%this.setPositionX(50);
		} // left


	//} // player
	// TODO: Eigene Positionen für die Asteroiden
}

function t2dSceneObject::onCollision(%srcCollisionObject, %dstCollisionObject, %srcRef, %dstRef, %collisionTime, %collisionNormal, %contactCount, %contactPoints)
{
	// echo("Kollision " @ %srcCollisionObject.tag SPC %dstCollisionObject.tag);
	if (%srcCollisionObject.tag $= "Bullet") 
	{
		%explosion = new t2dParticleEffect() { scenegraph = t2dSceneGraph; };
		%explosion.loadEffect("~/data/particles/ast_explosion.eff");
		%explosion.setPosition(%srcCollisionObject.getPosition());
		%explosion.playEffect();
		%explosion.setEffectLifeMode(kill, 3);
		
		if (%dstCollisionObject.tag $= "Asteroid1") 
		{
				createAsteroid(2, %dstCollisionObject.getPositionX(), %dstCollisionObject.getPositionY());
				createAsteroid(2, %dstCollisionObject.getPositionX(), %dstCollisionObject.getPositionY());
		}
		if (%dstCollisionObject.tag $= "Asteroid2") 
		{
				createAsteroid(3, %dstCollisionObject.getPositionX(), %dstCollisionObject.getPositionY());
				createAsteroid(3, %dstCollisionObject.getPositionX(), %dstCollisionObject.getPositionY());
		}		
		
		%srcCollisionObject.safeDelete();
		%dstCollisionObject.safeDelete();
		
		// überprüfen ob noch Gegner da sind
		%enemiesList = t2dSceneGraph.pickRect("-100 -100", "100 100", BIT(1));
		%enemiesCount = getWordCount(%enemiesList);

		echo("Gegner: " SPC %enemiesCount);
		
		// Wenn nicht, nächstes Lvl starten
		if (%enemiesCount == 0) 
		{
			
			echo ("Level geschafft");
			
			schedule(1000, 0, "initLevel", $gameInfo.level + 1);
		}
		
	} // Src Bullet
	
	if (%srcCollisionObject.tag $= "Player") 
	{
		killPlayer();	
	}
}


player.cs

// ---------------------
// Player-Konstanten
// ---------------------
$playerInfo = new ScriptObject();
$playerInfo.isAlive = true;
$playerInfo.canFire = true;
$playerInfo.cooldownTime = 400;
$playerInfo.recoverTime = 3000;

// ---------------------
// Player-Funktionen
// ---------------------
function createPlayer() {

	$player = new t2dStaticSprite() { scenegraph = t2dSceneGraph; };
	$player.setImageMap(playershipImageMap);
	$player.setSize("5 3.5");
	$player.setPosition("0 0");
	
	$player.setWorldLimit(NULL, "-56 -43.5 56 43.5", true);
	$player.setMaxLinearVelocity(50);
	
	$player.setLayer($gameConstants.playerLayer);
	$player.setGraphGroup($gameConstants.playerGroup);
	
	$player.setCollisionPolyCustom( 4, "-0.8 0 -0.45 -0.8 0.79 0 -0.45 0.8" );
	//$player.setCollisionPolyCustom( 4, "-1 0 -0.1 -0.6 0.98 0.15 -0.1 0.7" );
	$player.setCollisionActive( true, false );
	$player.setCollisionCallback( true );
	$player.setCollisionPhysics(true, true);
	$player.setCollisionMaterial(playerMaterial);
	$player.setCollisionGroups($gameConstants.asteroidsGroup);
	$player.tag = "Player";
	
	$gameInfo.lives = 3;

	moveMap.push();
	
	%thruster = new t2dParticleEffect() { scenegraph = t2dSceneGraph; };
	%thruster.loadEffect("~/data/particles/ast_thrust.eff");
	%thruster.mount( $player, "-0.5 0", 0, true );
	%thruster.setRotation( $player.getRotation() );
	%thruster.setLayer($gameConstants.playerAssetsLayer);
	
	$player.thruster = %thruster;
	
	%shield = new t2dParticleEffect() { scenegraph = t2dSceneGraph; };
	%shield.loadEffect("~/data/particles/ast_shield.eff");
	%shield.setLayer($gameConstants.playerAssetsLayer);
	%shield.mount( $player );
	
	$player.shield = %shield;
}

function killPlayer()
{
   // Explosion abspielen
   %explosion = new t2dParticleEffect() { scenegraph = t2dSceneGraph; };
   %explosion.loadEffect("~/data/particles/ast_hexplosion.eff");
   %explosion.setPosition($player.getPosition());
   %explosion.setLinearVelocity(($player.getLinearVelocityX() / 2) SPC ($player.getLinearVelocityY() / 2));
   %explosion.playEffect();
   
   // Player deaktivieren  
   $playerInfo.isAlive = false;
   $player.setEnabled(false);
      
   // Ein Leben abziehen
   $gameInfo.lives = $gameInfo.lives - 1;
	
	
   if ($gameInfo.lives != 0) {
      // Wenn noch leben da, in 2 Sekunden wiederbeleben
      updateLivesLabel();
      $playerSchedule = schedule( 2000, 0, "newPlayer" );
   } else {
      // Game over anzeigen und nach 2 Sekunden ins Menü schmeissen
      showGameOverLabel(); 
      schedule(2000, 0, "backToMenu", true);
   }
}

function newPlayer()
{
	$player.setPosition("0 0");
	$player.setAngularVelocity(0);
	$player.setRotation(-90);
	$player.setLinearVelocity("0 0");
	
	$playerInfo.isAlive = true;
	$player.setCollisionSuppress(true);
	$player.setEnabled(true);
	
	$player.shield.playEffect();
	
	$playerCSchedule = schedule( $playerInfo.recoverTime, 0, "activatePlayerCollision" );
}

function activatePlayerCollision()
{
	$player.setCollisionSuppress(false);
	$player.shield.stopEffect(true, false);
}

function thrust()
{
	$player.setImpulseForcePolar($player.getRotation() + 90, 3);
	$thrustSchedule = schedule( 20, 0, "thrust" );
}

function playerFire()
{
	
	if ($playerInfo.isAlive && $playerInfo.canFire) {
	   
	   // echo ($playerCanFire);
	   setPlayerCanFire(false);
	   
		%bullet = new t2dStaticSprite() { scenegraph = t2dSceneGraph; };
		
		%bullet.setLifeTime(3);
		%bullet.setWorldLimit(kill, "-60 -47.5 60 47.5", false);
		%bullet.tag = "Bullet";
		%bullet.setSize("1 1");
		
		%bullet.setPosition($player.getPosition());
		%bullet.setLinearVelocityPolar($player.getRotation() + 90, 20);
		%bullet.setLinearVelocityX(%bullet.getLinearVelocityX() + $player.getLinearVelocityX());
		%bullet.setLinearVelocityY(%bullet.getLinearVelocityY() + $player.getLinearVelocityY());
		
		%bullet.setLayer($gameConstants.bulletsLayer);
		%bullet.setGraphGroup($gameConstants.playerGroup);
		 
		%bullet.setCollisionGroups($gameConstants.asteroidsGroup);
		%bullet.setCollisionActive(true, false);
		%bullet.setCollisionCallback(true);
		
		%bulletEffect = new t2dParticleEffect() { scenegraph = t2dSceneGraph; };
		%bulletEffect.loadEffect("~/data/particles/ast_bullet.eff");
		%bulletEffect.setPosition($player.getPosition());
		%bulletEffect.mount(%bullet, "0 0", 0, true);
		
		%bulletEffect.setEffectLifeMode(kill, 3);
	
		%bulletEffect.playEffect();
		
		schedule($playerInfo.cooldownTime, 0, "setPlayerCanFire", true );
	} 	
	
	$fireSchedule = schedule($playerInfo.cooldownTime + 50, 0, "playerFire" );
}

function setPlayerCanFire(%flag)
{
   $playerInfo.canFire = %flag;   
}

function playerFireStop()
{
	if ( isEventPending($fireSchedule) ) 
	{
		cancel( $fireSchedule );
	}
}

function playerUp()
{ 
	
	// Start Player Thruster.
	thrust();
	$player.thruster.playEffect();
}
	
function playerUpStop()
{ 
	if ( isEventPending($thrustSchedule) ) 
	{
		cancel( $thrustSchedule );
		$player.thruster.stopEffect(true, false);
	}
	
}

function playerDown()
{ 
	// Set the player moving down. 
	$player.setImpulseForcePolar($player.getRotation() - 90, 1);
	$playerDownSchedule = schedule( 100, 0, "playerDown" );
}
	
function playerDownStop()
{ 
	if ( isEventPending($playerDownSchedule) )
		cancel( $playerDownSchedule );
}


function playerLeft()
{ 
	// Set the player moving down. 
	$player.setAngularVelocity( -270 );
}
	
function playerLeftStop()
{ 
	// If we're moving down then nullify any downward movement. 
	if ( $player.getAngularVelocity() < 0 ) 
		$player.setAngularVelocity( 0 );

}

function playerRight()
{ 
	// Set the player moving down. 
	$player.setAngularVelocity( 270 );
}
	
function playerRightStop()
{ 
	// If we're moving down then nullify any downward movement. 
	if ( $player.getAngularVelocity() > 0 ) 
		$player.setAngularVelocity( 0 );
}

defaultBind.cs

	new ActionMap(moveMap);
	moveMap.bindCmd(keyboard, "w", "playerUp();", "playerUpStop();");
	moveMap.bindCmd(keyboard, "s", "playerDown();", "playerDownStop();");
	moveMap.bindCmd(keyboard, "a", "playerLeft();", "playerLeftStop();");
	moveMap.bindCmd(keyboard, "d", "playerRight();", "playerRightStop();");
	moveMap.bindCmd(keyboard, "up", "playerUp();", "playerUpStop();");
	moveMap.bindCmd(keyboard, "down", "playerDown();", "playerDownStop();");
	moveMap.bindCmd(keyboard, "left", "playerLeft();", "playerLeftStop();");
	moveMap.bindCmd(keyboard, "right", "playerRight();", "playerRightStop();");
	moveMap.bindCmd(keyboard, "space", "playerFire();", "playerFireStop();");
	moveMap.bindCmd(keyboard, "escape", "backToMenu(false);", "");


In game.cs - initalizeGame() there is a function-call loadGarageGames(); this shows the GG-splashscreen, then the TenebraeGames-splashscreen and then opens the mainMenu. Source for the GUI's is not included, as this is not the purpose of this tutorial. But basically all the menu does is: Canvas.setContent(mainScreenGui); initGame();