TGB/BreakoutTutorial
From TDN
The following links can take you to other sections of the tutorial:
The Breakout Tutorial Part 1 - Making the SceneA Tetraweb Tutorial
Overview and Scope of ProjectThe purpose of this tutorial is to guide a TGB beginner or intermediate level user through the creation of a complete game with multiple levels, high scores, sound effects, particle effects and reasonably fun gameplay. Several things to note about this tutorial
Let's Get StartedCreate a new project, save it as Breakout.
Adding WallsClick on the Create tab and drag a Scene Object onto the scene view. (See fig. 1.2)
Again choose paste, to paste another copy of your left wall, and with it selected open its Scene Object section and set the following: X: 0.000, Y: -74.000, Width: 200.000, Height: 3.000. And now you have your top wall. Adding the Lost Ball TriggerFinally, click the Create tab and drag a Trigger onto the scene view (Fig 1.2 again)
You should now have a scene that looks like Figure 1.3. The walls are going to bounce the ball back onto the playing field and the trigger along the bottom is going to send a message when the ball enters it, letting us know that the ball is lost. Ship and ShieldTwbt_ship.zip Adding the Ship BaseNext, drag the shipbaseImageMap onto the scene view and double-click it to edit. Set the following in the Scene Object section. While in the Collision section let's set the collision polygon for our ship base. Hover the mouse over the base, click the first icon to edit the collision poly, and make it look as much as you can like figure 1.5. Click the selection tool along the top to exit edit mode and save your polygon. Finally, open the World Limits section and choose CLAMP from the dropdown. Then set the Min. Bounds to X: -95.175, Y: 50.000 and the Max. Bounds to X: 95.175, Y: 72.918 Adding the Shield ArchNow drag the ship_arcImageMap onto the scene view and double-click it to edit it. In the Scripting section, set the Name to theArch and the Class to paddleClass Now we will mount the shield. Select it and select the fourth icon when you mouse over it. (See fig. 1.6.5) Then attach the shield to the mount point you created. (See fig. 1.7) Next, we'll set the collision polygon for our shield. Hover the mouse over the shield, click the first icon to edit the collision poly, and make it look as much as you can like figure 1.8. Click the selection tool along the top to exit edit mode and save your polygon. The Scripting BeginsWe are going to make our first small steps into scripting now. By the end of this tutorial we will have written about a hundred functions spread across dozens of separate .cs files. These will all be pulled in with exec statements, and we want to organize it all so we don't have chaos.
function startGame(%level)
{
exec("~/exec.cs");
Now whenever we want to include another file with a group of functions we just add it to our exec.cs file.
exec("./gameScripts/base.cs");
Now create a new file in your /Breakout/game/gameScripts/ directory called base.cs. Add this code to it:
function baseClass::onLevelLoaded(%this, %scenegraph)
{
$thebase = %this;
%this.setDamping(4.8);
%this.setRestitution(1.0);
%this.setMaxAngularVelocity(0);
%this.setFriction(0.3);
%this.setCollisionResponse(CUSTOM);
%this.setMaxLinearVelocity(350);
}
We gave our base the class baseClass so when the level is loaded, this function will be run. The first line assigns the base to a global variable so we can always access it throughout the game. The next five lines modify the physics of how it responds to movement and collisions.
function paddleClass::onLevelLoaded(%this, %scenegraph)
{
%this.setRestitution(1.0);
%this.setCollisionResponse(CUSTOM);
%this.setMountInheritAttributes(true);
}
Note that we are setting the MountInheritAttributes field to true here. Primarily, we want this arch to be invisible if the base suddenly becomes invisible some time in our game. We could also have set this in the TGB editor; there is usually more than one way to do things in TGB. Moving with the MouseSave base.cs and then add the following two functions to game.cs right after the startGame function.
function sceneWindow2D::onMouseMove(%this, %modifier, %worldPosition, %mouseClicks){
movePaddle(%worldPosition);
}
function sceneWindow2D::onMouseDragged(%this, %modifier, %worldPosition, %mouseClicks){
movePaddle(%worldPosition);
}
Now whenever the mouse (or trackpad) is moved, it will call these functions. Our movePaddle function will take the %worldPosition variable, so lets write that now; you can add it right below the functions above in game.cs.
function movePaddle(%worldPosition) {
%newXPos = getword(%worldPosition,0);
if (%newXPos < 0) { %posmod=-1; } else { %posmod = 1; }
if (mAbs(%newXPos) > 65) %newXPos = %posmod * 65;
$thebase.setImpulseForce((%newXPos)*$vmod,0);
sceneWindow2D.setMousePosition("0 0");
}
Let's go over this line by line, then we are almost ready to finally test what we have so far. $thebase.setImpulseForce((%newXPos)*2.0,0); but that also seems like a pretty good number to have as a global variable, something we can change. We can imagine when we might want to make that $vmod 0.5, for example, and have our player moving through mud; or make it 10.0 and have them moving like they are on ice, barely able to control the base. Potentially fun stuff. $VMODSTANDARD = 2.0; $vmod = $VMODSTANDARD; //paddle speed factor Why two variables? We are following the convention of using UPPERCASE globals as constants. So $VMODSTANDARD will always be 2.0 throughout the game, whereas we may at some point modify $vmod. Conveniently, when we want to put $vmod back where it belongs, we can always use $VMODSTANDARD to reset $vmod equal to 2.0.
exec("./gameScripts/theLevels.cs");
Ready to TestMake sure everything is saved, all your scripts and your playlevel.t2d in the TGB level editor. Let's press the Play Level button and see what we have. Canvas.hidecursor(); and add this Canvas.showcursor(); to the end of the endGame function in the same file. (The showcursor call is not necessary in TGB 1.5 and higher, but it is in 1.13.)
sceneWindow2D.setMousePosition("0 0");
And while we are here, lets put in a more graceful way to exit, at least temporarily. Add this line to startGame right above movemap.push();
moveMap.bind("keyboard", "q", "quitgame");
This will call our quitgame function when you press the 'q' key. Add that function right after startGame in game.cs.
function quitgame(%val) {
if (%val)
quit();
}
The %val local variable tells you if it is a keypress or a keyrelease. Without the if (%val) line, this function would be called twice when the user presses the 'q' key; once when it is pressed and once when it is released.
One More ThingBefore we finish up with this Part 1 of our Breakout Tutorial, I want to add one more thing. One of the best aspects of using the TGB system is its wonderful particle effects engine. It really sets TGB apart and it enables you to turn good game ideas into polished products. I think the base should emit a shower of plasma when it moves, and stop emitting when it stops moving, so lets add that right now. Twbt_pe1.zip
%trail = new t2dParticleEffect() {
scenegraph = %scenegraph;
effectFile = "~/data/particles/basetrail.eff";
useEffectCollisions = "0";
effectMode = "INFINITE";
effectTime = "0";
size = "15.000 15.000";
};
%linkIndex = %trail.mount($thebase, "0.000 1.000");
%trail.playEffect(false);
$thebase.myTrail = %trail;
$thebase.myTrail.isplaying=true;
First, we load the new effect into the local variable %trail, adding a few settings. Then we use %trail.mount to attach the effect to the base, using our global variable $thebase that we set earlier. Then we play the effect, assign the local variable %trail to a new field in our base object called $thebase.myTrail so we can always access it. We also do the same with a new field that we make in our effect so we can easily keep track of whether it is playing or not with $thebase.myTrail.isplaying.
%this.setTimerOn(250); This will run an onTimer function every 250 milliseconds, or four times a seconds. Add this to the base.cs file, after the previous function.
function baseClass::onTimer(%this) {
%speed = getword(%this.getlinearVelocitypolar(),1);
if ( (%this.myTrail.isplaying==true) && (%speed < 5) ) {
%this.myTrail.stopEffect(true,false);
%this.myTrail.isplaying=false;
} else if ( (%speed > 5) && (%this.myTrail.isplaying==false) ) {
%this.myTrail.playeffect(false);
%this.myTrail.isplaying=true;
}
}
Going over this, first we get the current speed of our base using the getword method again with getlinearVelocitypolar. Now we do two tests; using our isplaying field, we see if the effect is playing and the speed is slow, below 5. If so, the next to lines stop the effect and set isplaying to false so we know it is stopped. The else test does the reverse, if the speed is faster than 5 and the effect is not playing we start it and set isplaying to true. ConclusionWell, we laid a lot of groundwork here, but we have a good deal of scripting ahead of us. The next part of this tutorial will get some stuff bouncing around. Thanks for reading, and feel free to post any comments or questions on the BreakoutTutorial Discussion Thread. Continue on to:
|
Categories: TGB | GameExample | Tutorial















