Welcome, Guest! Login | Register

TriAPI BreakOut [Print this Article]
Posted by: X-0ut
Date posted: Mar 21 2003
User Rating: N/A
Number of views: 5567
Number of comments: 0
Description: Hud game
TriAPI BreakOut
This tutorial is meant to follow on from omega's Ortho drawing tutorial, you should have completed that before attempting this. This tut can be considered cut&paste friendly, its hardly ground breaking and just basically shows an example of what can be done with orthogonal triAPI. This game will include only one level, yet the game is endless, when all blocks are destroyed or the ball falls out of reach the game will reset. Also, I have not included anyway for this game to be triggered on/off (the game will automatically be on), I'll leave that up to you. A good place to use this game would be while in spectator mode, or maybe triggered by some map entity in a solo game.

Ok here it is :

Put this code in hud.h, bottom of the CHud class:
 CODE  

////////////////////////
// arkanoid clone   //
////////////////////////
    bool    bBlockOutStarted;//Game Started?
    HSPRITE  hBlockSprite;//sprite of blocks and bat
    HSPRITE  hBallSprite;//Ball sprite
   
    void    UpdateGame( void );//main update function
    void    RenderGame( void );//all drawing will be done here
    void    InitGame( void );
    float blocksize_x;
    float blocksize_y;
    float batsize_x;
    float batsize_y;
    float bat_x;//x position of the bat
    float bat_y;//y
////////////////////////


Next open Input.cpp and find the CL_AdjustAngles function, add the following code at the very bottom of the it:
 CODE  

//Bat control//
//using a boolean operation
    if(in_right.state & 1)
        gHUD.bat_x<ScreenWidth-(gHUD.blocksize_x*2) ?
        (gHUD.bat_x +=gHUD.m_flTimeDelta * 250) :
        (gHUD.bat_x = ScreenWidth-(gHUD.blocksize_x*2));
    if(in_left.state & 1)
        gHUD.bat_x>gHUD.blocksize_x ?
        (gHUD.bat_x -= gHUD.m_flTimeDelta * 250) :
        (gHUD.bat_x = gHUD.blocksize_x);

In entity.cpp find the function HUD_TempEntUpdate, now paste the following code just BEFORE this line: if ( !*ppTempEntActive ) :
 CODE  

    static bool bInitGame = false;
    bInitGame? gHUD.UpdateGame():gHUD.InitGame(),bInitGame=true;


Now in omega's drawortho function place this line of code:
 CODE  

    gHUD.RenderGame();


Now finally the code for the BreakOut game. It's not too lengthy really, but add a new cpp file to your project named BreakOut.cpp.
Paste this into the file:
 CODE  

///////////////////////////////
// Blockout written by X-0ut //
///////////////////////////////
#include "hud.h"
#include "cl_util.h"
#include "triangleapi.h"

void BallCollide( void );
void ResetGame( void );
/////////////////////////////////////
// Global array for a single stage //
// just an example to start with   //
/////////////////////////////////////
int Stage[1][10][10]=  //one stage with a 10x10 grid
{  
    1,2,3,4,5,5,4,3,2,1,
    2,1,2,3,4,4,3,2,1,2,
    3,2,1,2,3,3,2,1,2,3,
    4,3,2,1,2,2,1,2,3,4,
    5,4,3,2,1,1,2,3,4,5,
    5,4,3,2,1,1,2,3,4,5,
    4,3,2,1,2,2,1,2,3,4,
    3,2,1,2,3,3,2,1,2,3,
    2,1,2,3,4,4,3,2,1,2,
    1,2,3,4,5,5,4,3,2,1
};
//each constant will act as a different color for the blocks
// a constant of 0 will mean the block has been destroyed

float ball_x,ball_y;//ball position
float sp_x,sp_y;//ball speed
float ballsize;

void CHud::InitGame( void )
{
    gHUD.blocksize_x = ScreenWidth/12;
    gHUD.blocksize_y = ScreenHeight/20;
    gHUD.batsize_x = ScreenWidth/13;
    gHUD.batsize_y = ScreenHeight/40;
    bat_x= ScreenWidth/2;
    bat_y= ScreenHeight - gHUD.blocksize_y;
    ballsize = ScreenWidth /100;
    sp_x = 80;sp_y =-80;
    ball_x = bat_x+ballsize;
    ball_y = (bat_y - (ballsize*5));
}

void CHud::UpdateGame( void )
{
    //add the speed to the ball//
    ball_x += gHUD.m_flTimeDelta * sp_x;
    ball_y += gHUD.m_flTimeDelta * sp_y;
   
    BallCollide();
}

void CHud::RenderGame( void )
{
    ////Draw the bat////

    gEngfuncs.pTriAPI->SpriteTexture(
        (struct model_s *)gEngfuncs.GetSpritePointer(SPR_Load("sprites/dot.spr")) ,
        0);
    gEngfuncs.pTriAPI->CullFace( TRI_NONE );
    gEngfuncs.pTriAPI->Begin(TRI_QUADS);
    gEngfuncs.pTriAPI->RenderMode(kRenderNormal);
    gEngfuncs.pTriAPI->Color4f(1,1,1,1);
    gEngfuncs.pTriAPI->TexCoord2f(0.0f, 1.0f);
    gEngfuncs.pTriAPI->Vertex3f(bat_x, bat_y, 0); //top left
    gEngfuncs.pTriAPI->TexCoord2f(0.0f, 0.0f);
    gEngfuncs.pTriAPI->Vertex3f(bat_x, bat_y - batsize_y, 0); //bottom left
    gEngfuncs.pTriAPI->TexCoord2f(1.0f, 0.0f);
    gEngfuncs.pTriAPI->Vertex3f(bat_x + batsize_x , bat_y - batsize_y, 0); //bottom right
    gEngfuncs.pTriAPI->TexCoord2f(1.0f, 1.0f);
    gEngfuncs.pTriAPI->Vertex3f(bat_x + batsize_x, bat_y, 0); //top right
    gEngfuncs.pTriAPI->End();
    ////Draw the blocks////
    gEngfuncs.pTriAPI->SpriteTexture(
        (struct model_s *)gEngfuncs.GetSpritePointer(SPR_Load("sprites/vp_parallel.spr")) ,
        0);
    for(int y=0;y<10;y++){
        for(int x=0;x<10;x++){
            gEngfuncs.pTriAPI->CullFace( TRI_NONE );
            gEngfuncs.pTriAPI->Begin(TRI_QUADS);
            gEngfuncs.pTriAPI->RenderMode(kRenderNormal);
            switch(Stage[0][y][x])
            {
            case 1: gEngfuncs.pTriAPI->Color4f(1,0,0,1);break;
            case 2: gEngfuncs.pTriAPI->Color4f(1,1,0,1);break;
            case 3: gEngfuncs.pTriAPI->Color4f(0,1,0,1);break;
            case 4: gEngfuncs.pTriAPI->Color4f(0,1,1,1);break;
            case 5: gEngfuncs.pTriAPI->Color4f(0,0,1,1);break;
            case 6: gEngfuncs.pTriAPI->Color4f(1,0,1,1);break;
            case 7: gEngfuncs.pTriAPI->Color4f(0.5f,0,0,1);break;
            case 8: gEngfuncs.pTriAPI->Color4f(0,0.5f,0,1);break;
            case 9: gEngfuncs.pTriAPI->Color4f(0,0,0.5f,1);break;
            }
            if(Stage[0][y][x]!=0)
            {//only render if its not been hit
                gEngfuncs.pTriAPI->TexCoord2f(0.0f, 1.0f);
                gEngfuncs.pTriAPI->Vertex3f(blocksize_x*(x+1), blocksize_y*(y+2), 0); //top left
                gEngfuncs.pTriAPI->TexCoord2f(0.0f, 0.0f);
                gEngfuncs.pTriAPI->Vertex3f(blocksize_x*(x+1), (blocksize_y*(y+2)) - blocksize_y, 0); //bottom left
                gEngfuncs.pTriAPI->TexCoord2f(1.0f, 0.0f);
                gEngfuncs.pTriAPI->Vertex3f((blocksize_x*(x+1)) + blocksize_x , (blocksize_y*(y+2)) - blocksize_y, 0); //bottom right
                gEngfuncs.pTriAPI->TexCoord2f(1.0f, 1.0f);
                gEngfuncs.pTriAPI->Vertex3f((blocksize_x*(x+1)) + blocksize_x, blocksize_y*(y+2), 0); //top right
            }
            gEngfuncs.pTriAPI->End();
            gEngfuncs.pTriAPI->RenderMode(kRenderNormal);
        }
    }
    ////Draw the ball////
    gEngfuncs.pTriAPI->SpriteTexture(
        (struct model_s *)gEngfuncs.GetSpritePointer(SPR_Load("sprites/dot.spr")) ,
        0); //use hotglow, or any other sprite for the texture
    gEngfuncs.pTriAPI->CullFace( TRI_NONE );
    gEngfuncs.pTriAPI->Begin(TRI_QUADS);
    gEngfuncs.pTriAPI->RenderMode(kRenderNormal);
    gEngfuncs.pTriAPI->Color4f(1,1,1,1);
    gEngfuncs.pTriAPI->TexCoord2f(0.0f, 1.0f);
    gEngfuncs.pTriAPI->Vertex3f(ball_x, ball_y, 0); //top left
    gEngfuncs.pTriAPI->TexCoord2f(0.0f, 0.0f);
    gEngfuncs.pTriAPI->Vertex3f(ball_x, ball_y - ballsize, 0); //bottom left
    gEngfuncs.pTriAPI->TexCoord2f(1.0f, 0.0f);
    gEngfuncs.pTriAPI->Vertex3f(ball_x + ballsize , ball_y - ballsize, 0); //bottom right
    gEngfuncs.pTriAPI->TexCoord2f(1.0f, 1.0f);
    gEngfuncs.pTriAPI->Vertex3f(ball_x + ballsize, ball_y, 0); //top right  
    gEngfuncs.pTriAPI->End();
}

void BallCollide( void )
{
    bool Hitx =false,Hity=false;//hit flag
    bool BlocksLeft=false;
    //check collision with block//
    for(int y=0;y<10;y++)
    {
        for(int x=0;x<10;x++)
        {
            if(Stage[0][y][x]!=0){
                //save this for later//
                //there is still block(s) left//
                BlocksLeft=true;
                //check right side//
                if((ball_x+(ballsize/2) > (gHUD.blocksize_x *(x+1))+(gHUD.blocksize_x-(gHUD.blocksize_x/10))) &&
                    (ball_x+(ballsize/2) < (gHUD.blocksize_x *(x+1))+gHUD.blocksize_x) &&
                    (ball_y-(ballsize/2) < gHUD.blocksize_y *(y+2)) &&
                    (ball_y-(ballsize/2) > (gHUD.blocksize_y *(y+2))-gHUD.blocksize_y))
                {
                    Stage[0][y][x] = 0;
                    Hitx=true;
                }
                //check left side//
                if((ball_x+(ballsize/2) > gHUD.blocksize_x *(x+1)) &&
                    (ball_x+(ballsize/2) < (gHUD.blocksize_x *(x+1))+(gHUD.blocksize_x/10)) &&
                    (ball_y-(ballsize/2) < gHUD.blocksize_y *(y+2)) &&
                    (ball_y-(ballsize/2) > (gHUD.blocksize_y *(y+2))-gHUD.blocksize_y))
                {
                    Stage[0][y][x] = 0;
                    Hitx=true;
                }
                //check bottom side//
                if((ball_x+(ballsize/2) > gHUD.blocksize_x *(x+1)) &&
                    (ball_x+(ballsize/2) < (gHUD.blocksize_x *(x+1))+gHUD.blocksize_x) &&
                    (ball_y-(ballsize/2) < gHUD.blocksize_y *(y+2)) &&
                    (ball_y-(ballsize/2) > (gHUD.blocksize_y *(y+2))-(gHUD.blocksize_y/10)))
                {
                    Stage[0][y][x] = 0;
                    Hity=true;
                }
                //check top side//
                if((ball_x+(ballsize/2) > gHUD.blocksize_x *(x+1)) &&
                    (ball_x+(ballsize/2) < (gHUD.blocksize_x *(x+1))+gHUD.blocksize_x) &&
                    (ball_y-(ballsize/2) > (gHUD.blocksize_y *(y+2))-gHUD.blocksize_y) &&
                    (ball_y-(ballsize/2) < (gHUD.blocksize_y *(y+2))-(gHUD.blocksize_y-(gHUD.blocksize_y/10))))
                {
                    Stage[0][y][x] = 0;
                    Hity=true;
                }
            }
        }
    }
    //check bat//
    //leftside
    if(ball_x+(ballsize/2) > gHUD.bat_x && ball_x+(ballsize/2) < gHUD.bat_x+(gHUD.batsize_x/4) &&
        ball_y-(ballsize/2) > gHUD.bat_y-gHUD.batsize_y && ball_y-(ballsize/2) < gHUD.bat_y)
    {
        Hity=true;
        sp_x>0?Hitx=true,sp_x+=5,sp_y+=5:sp_x-=5,sp_y-=5;
    }
    else if(ball_x+(ballsize/2) > gHUD.bat_x+(gHUD.batsize_x/4) && ball_x+(ballsize/2) < gHUD.bat_x+(gHUD.batsize_x/2) &&
        ball_y-(ballsize/2) > gHUD.bat_y-gHUD.batsize_y && ball_y-(ballsize/2) < gHUD.bat_y)
    {
        Hity=true;
        sp_x>0?Hitx=true,sp_x+=10,sp_y+=10:sp_x-=10,sp_y-=10;
    }
    //rightside
    if(ball_x+(ballsize/2) < gHUD.bat_x+(gHUD.batsize_x-(gHUD.batsize_x/4)) && ball_x+(ballsize/2) > gHUD.bat_x+(gHUD.batsize_x/2) &&
        ball_y-(ballsize/2) > gHUD.bat_y-gHUD.batsize_y && ball_y-(ballsize/2) < gHUD.bat_y)
    {
        Hity=true;
        sp_x<0?Hitx=true,sp_x-=5,sp_y-=5:sp_x+=5,sp_y+=5;
    }
    else if(ball_x+(ballsize/2) < gHUD.bat_x+gHUD.batsize_x && ball_x+(ballsize/2) > gHUD.bat_x+(gHUD.batsize_x-(gHUD.batsize_x/4)) &&
        ball_y-(ballsize/2) > gHUD.bat_y-gHUD.batsize_y && ball_y-(ballsize/2) < gHUD.bat_y)
    {
        Hity=true;
        sp_x<0?Hitx=true,sp_x-=10,sp_y-=10:sp_x+=10,sp_y+=10;
    }
   
   
    if(Hitx)
        sp_x -= ((sp_x)*2);
    if(Hity)
        sp_y -= ((sp_y)*2);
   
    //check edges of screen//
    if(ball_x<gHUD.blocksize_x)
        sp_x -= (sp_x*2);
    if(ball_x+(ballsize*2)>ScreenWidth-gHUD.blocksize_x)
        sp_x -= (sp_x*2);
    if(ball_y-(ballsize*2)<0+gHUD.blocksize_y)
        sp_y -= (sp_y*2);
    if(ball_y-(ballsize)>ScreenHeight)
        ResetGame();
   
    //Any blocks left?//
    if(!BlocksLeft)//you could call the next level here//
        ResetGame();
}

void ResetGame( void )
{
    gHUD.blocksize_x = ScreenWidth/12;
    gHUD.blocksize_y = ScreenHeight/20;
    gHUD.batsize_x = ScreenWidth/13;
    gHUD.batsize_y = ScreenHeight/40;
    gHUD.bat_x= ScreenWidth/2;
    gHUD.bat_y= ScreenHeight - gHUD.blocksize_y;
    sp_x = 80;
    sp_y =-80;
    ball_x = gHUD.bat_x+ballsize;
    ball_y = (gHUD.bat_y - (ballsize*5));
    Stage[1][10][10]=
        1,2,3,4,5,5,4,3,2,1,
        2,1,2,3,4,4,3,2,1,2,
        3,2,1,2,3,3,2,1,2,3,
        4,3,2,1,2,2,1,2,3,4,
        5,4,3,2,1,1,2,3,4,5,
        5,4,3,2,1,1,2,3,4,5,
        4,3,2,1,2,2,1,2,3,4,
        3,2,1,2,3,3,2,1,2,3,
        2,1,2,3,4,4,3,2,1,2,
        1,2,3,4,5,5,4,3,2,1;
}

To move the bat left and right make sure you have +left & +right bound to a set of keys, alternatively you could change the keys that move the bat ( the part we added in input.cpp).

Rate This Article
This article has not yet been rated.

You have to register to rate this article.
User Comments

No User Comments

You must register to post a comment. If you have already registered, you must login.

Latest Articles
3rd person View in Multiplayer
Half-Life 2 | Coding | Client Side Tutorials
How to enable it in HL2DM

By: cct | Nov 13 2006

Making a Camera
Half-Life 2 | Level Design
This camera is good for when you join a map, it gives you a view of the map before you join a team

By: slackiller | Mar 05 2006

Making a camera , Part 2
Half-Life 2 | Level Design
these cameras are working monitors that turn on when a button is pushed.

By: slackiller | Mar 04 2006

Storing weapons on ladder
Half-Life 2 | Coding | Snippets
like Raven Sheild or BF2

By: British_Bomber | Dec 24 2005

Implementation of a string lookup table
Half-Life 2 | Coding | Snippets
A string lookup table is a set of functions that is used to convert strings to pre-defined values

By: deathz0rz | Nov 13 2005


Latest Comments
knock knock
General | News
By: omega | Dec 22 2016
 
knock knock
General | News
By: MIFUNE | Oct 10 2015
 
New HL HUD Message System
Half-Life | Coding | Shared Tutorials
By: chbrules | Dec 31 2011
 
knock knock
General | News
By: Whistler | Nov 05 2011
 
Particle Engine tutorial part 4
Half-Life | Coding | Client Side Tutorials
By: darkPhoenix | Feb 18 2010
 
Particle Engine tutorial part 2
Half-Life | Coding | Client Side Tutorials
By: darkPhoenix | Feb 11 2010
 
Particle Engine tutorial part 3
Half-Life | Coding | Client Side Tutorials
By: darkPhoenix | Feb 11 2010
 
Game Movement Series #2: Analog Jumping and Floating
Half-Life 2 | Coding | Shared Tutorials
By: mars3554 | Oct 26 2009
 
Particle Engine tutorial part 5
Half-Life | Coding | Client Side Tutorials
By: Deadpool | Aug 02 2009
 
Particle Engine tutorial part 5
Half-Life | Coding | Client Side Tutorials
By: Persuter | Aug 02 2009
 

Site Info
297 Approved Articless
8 Pending Articles
3940 Registered Members
0 People Online (8 guests)
About - Credits - Contact Us

Wavelength version: 3.0.0.9
Valid XHTML 1.0! Valid CSS!