Buttons Hunter - The Game for AmiBroker 6.25

game
Tags: #<Tag:0x00007f2d7cfec328>

#1

Maybe this game is not the latest part of “Wolfenstein” and I’m not agent Blaskowitz, but as they say: “Even big things have small beginnings:wink:

… but seriously - recently I’ve enjoyed myself a (summer time) break from the trading - and because a break from trading doesn’t have to be a break from AmiBroker - I decided to try something different.

Because Amibroker is much more than just ordinary technical analysis software ( I tried to back up this statement in this thread: AmiBroker - much more … )

… and because I wanted to cope with some issues raised in this thread: GuiButtons for everyone

… and additionally because many users ask on a daily basis can “something” be done in AmiBroker, I decided to try to combine or merge all of those issues in one project showing, that even the least expected things can be done in AmiBroker by a regular user. If it was possible for me (I am just an average user) to make a game in AFL - what is definitely not the thing that AmiBroker was intended to be used for, probably everything that AmiBroker was meant to be used for, is possible :+1:

Game 5


This project might even have some practical applications. It might help to improve reaction time and mind-eye-hand-coordination - skills very important for a day-trader :wink: Additionally the game is very easy to hide at a workplace - as no one would expect a computer game hidden in one of AmiBrokers’ tabs :grinning:

The working title of this game is Buttons’ Hunter! for AmiBroker 6.25 :wink: If you have been hesitating whether to upgrade to the newest version of AmiBroker or not (at present only this version supports all Gui Buttons), now you have another reason to do so :wink:

The rules of the game are very simple. The user should hit as many buttons (3 types) as possible. The player can choose between 4 difficulty levels and has 5 lives. The buttons appear in random places and the player gradually has less and less time to do this. The results/scores of each player are saved and compared each time the game is over.

My main goal was to test the GUI Buttons introduced in AmiBroker 6.21 and 6.25 and try to check if it is possible to code a more complex and dynamic project (a game in this case) additionally making use of Gui Buttons, without any regular (unnecessary) refreshes. The most obvious and the easiest option would be to force AmiBroker to refresh the chart very often (i.e. 10 times per second ) using RequestTimedRefresh() and/or RequestMouseMoveRefresh() and execute some parts of the code conditionally (every n seconds or 1/n second) using GetPerformanceCounter(). But I wanted to achieve the same result without any unnecessary regular refreshes which are demanding for the CPU and which (if possible) should be avoided. In this case I used RequestTimedRefresh() unconditionally only in the intro. In the first part of the intro the chart is refreshed 10 times per second, in the second part - twice per second. During the game, the chart is refreshed only in two cases - when a new button appears or when the user interacts with the chart by clicking it. When the game is over, the chart is refreshed only when the user interacts with it (until the Start button is clicked again). This Start button also allows to quickly toggle between different parts of the game (for example you can skip the first and the second intro or finish the game at any moment).

Because as the game progresses, the refresh rate gradually increases and AmiBroker attempts to align refreshes to second boundary, I implemented some correcting mechanisms making use of GetPerformanceCounter() to be sure, that the next button will not appear too soon. I also used it to avoid situations in which one click would result in a loss of two lives what would happen when the user tries to click the button, but until he actually clicks it, it is already replaced by a new one. A life is lost when the target is missed or when it is not clicked at all. Such situation would meet both of the above criteria, but it would make the game much more difficult. In this version the user should be protected against such situation in the first 0.5 second after the appearance of the new button.

It is the first computer game I’ve ever made (I have no IT background) - so please be understanding… It is the first version (1.0.) I did my best to code it properly, but I am aware of the fact, that there still might be some small problems or things, that might have been solved differently. This code could use some additional improvements, but I may not have enough time to do it in the near future, so I decided to post it now - as it is, because “Gui Buttons” is a hot topic and some users may consider it worth taking a look at. Moreover I couldn’t check how this code looks like and how it behaves on Windows 10 (all my computers run Win 7). If you find any bugs or have suggestions please let me know. If some elements don’t look as expected ( you can compare it with my screenshots) please let me know. But I hope you will enjoy the game as it is now :slight_smile: I encourage other users to share some of their AFL “demos” …

If you like the idea of this non-standard approach of testing some features, you can like my post below with the code :slight_smile: (The first post in a new thread can only be voted on). If I have time and receive positive feedback I may implement some new features in the future. I will try to make it the best game for AmiBroker ever (it might be possible - especially taking into account, that the competition in this field is rather slim :grin: )

To be continued …


AmiBroker - much more than just ordinary technical analysis software
GuiButton Positioning at BarIndex and Price
GuiToggle() label assignment
#2

Game 4

Game 6

A short gameplay: https://youtu.be/SL8JcN6o6JU


Some additional notes:

  1. This game requires AmiBroker 6.25 (or a newer version)

  2. This code should be applied (or drag and dropped) to a “New Blank Chart”.

  3. It is strongly advised to have at least one SAPI (English or American) voice installed - because this code intensively makes use of the speech synthesis. User can select the voice using VoiceSelect(). At present speech rate for selected voice cannot be changed from AFL (maybe it will change in the future :wink: ) so the only option to increase the speech rate (which I recommend in this case) is via Windows (text to speech) settings.

  4. This code requires sub-second (down to 0.1 sec) RequestTimedRefresh resolution. More information in case of any problems:
    http://amibroker.com/guide/afl/requesttimedrefresh.html

  5. It is advised to turn off the chart’s crosshair by selecting --> View --> Crosshair Off

… and the code:

_SECTION_BEGIN( "Buttons Hunter" );

// --------- Buttons' Hunter ver. 1.0  for  AmiBroker 6.25  -----------------------
// --------- by  Miłosz Mazurkiewicz  ---------------------------------------------
/// @link http://forum.amibroker.com/t/buttons-hunter-the-game-for-amibroker-6-25/1834

// --------- Best palyed on GTX 1080 TI ... but any card will do ;-)  -------------
// --------- It is advised to select --> View --> Crosshair Off   -----------------
// --------- At least one English SAPI Voice installed is highly recommended  -----
// --------- Apply this code (drag and drop) to the New Blank chart  --------------
// --- ----- This code requires sub-second (down to 0.1 sec) RequestTimedRefresh resolution. More information:
/// @link http://amibroker.com/guide/afl/requesttimedrefresh.html

Version( 6.25 ); // AmiBroker 6.25 required to run this code
//VoiceSelect( 8 );  // If you have more than 1 SAPI voice installed, you can choose which voice is used

SetChartOptions( 0, chartDisableTooltips | chartDisableYAxisCursor | chartHideQuoteMarker, chartGrid0, 0, 0, 0 );
Contrast1 = Param( "Contrast 1", 0.1, 0.01, 1, 0.01 );
Contrast2 = Param( "Contrast 2", 0.15, 0.01, 1, 0.01 );
BestScoresReset = ParamTrigger( "Reset personal best scores", "Click to reset" );
MyChartID = GetChartID();
pxwidth = Status( "pxwidth" );
pxheight = Status( "pxheight" );
Counter = Nz( StaticVarGet( "Counter" + MyChartID ) );
ClicksCounter = Nz( StaticVarGet( "ClicksCounter" + MyChartID ) );
HitsCounter = Nz( StaticVarGet( "HitsCounter" + MyChartID ), 0 );
MissedCounter = Nz( StaticVarGet( "MissedCounter" + MyChartID ), 0 );
StageCounter1  = Nz( StaticVarGet( "StageCounter1" + MyChartID ), 1 );
StageCounter2  = Nz( StaticVarGet( "StageCounter2" + MyChartID ), 0 );
LivesCounter = Nz( StaticVarGet( "LivesCounter" + MyChartID ), 5 );
MyRed = ColorBlend( colorRed, colorOrange, 0.26 );
MyOrange = ColorBlend( colorYellow, colorOrange, 0.3 );
MyGreen = colorBrightGreen;
MyGrey = colorLightGrey;
GuiButtonClicked = 0;
GameOver = 0;
GameStart = 1;
ReadScore = 0;

procedure Ring( x, y, xShift, yShift, r1, r2, color )

{
    local x, y, xShift, yShift, r1, r2, color;
    GfxSelectSolidBrush( colorWhite );

    for( i = 0.80, j = 60; i > 0.05 AND j > 32; i -= 0.1, j -= 2 )
    {
        GfxSelectPen( colorBlend( colorWhite, colorGrey40, i ), 4 );
        GfxCircle( x + xShift, y + yShift, j );
    }

    GfxSelectSolidBrush( color );
    GfxCircle( x + xShift, y + yShift, r1 );
    GfxSelectSolidBrush( colorWhite );
    GfxCircle( x + xShift, y + yShift, r2 );
}

GfxSetOverlayMode( 2 );
GfxSetBkMode( 1 ); // transparent
GfxSelectSolidBrush( colorWhite );
GfxSelectPen( colorLightGrey, 2 );
GfxGradientRect( 1, 1, pxwidth, pxheight, colorWhite, ColorBlend( colorBlack, colorWhite, Contrast1 ) );

if( pxwidth > 1100 AND pxheight > 600 ) //  If the chart is not too small

{
    GfxRectangle( 1, 1, 233, 292 );
    GfxGradientRect( 3, 3, 231, 290, colorWhite, ColorBlend( colorGrey50, colorWhite, Contrast2 ) );
    GfxSelectPen( colorLightGrey, 1 );
    GfxRectangle( 11, 78, 32, 168 );
    GfxRectangle( 11, 172, 32, 196 );
    GuiButton( "Start", 1, 10, 25, 75, 25, 1 );
    GuiEdit( 3, 10, 55, 130, 20, 1 );
    GuiCheckBox( "", 5, 15, 174, 15, 19, 1 );
    id = GuiGetEvent( 0, 0 );
    event = GuiGetEvent( 0, 1 );
    StartButtonClicked = ( id == 1 && event == 1 );
    GfxSetTextColor( colorBlack );
    GfxSelectFont( "Tahoma", 9, 700 );

    Sound = Nz( StaticVarGet( "Sound" + MyChartID ), 1 );

    if( id == 5 && event == 1 )
    {
        if( Sound )
        {
            StaticVarSet( "Sound" + MyChartID, Sound = 0 );
            Say( "Sound off." );
        }

        else
        {
            StaticVarSet( "Sound" + MyChartID, Sound = 1 );
            Say( "Sound on." );
        }
    }

    if( Sound )
    {

        GuiSetCheck( 5, 1 );
        GfxSelectFont( "Tahoma", 9, 700 );
    }
    else
    {
        GuiSetCheck( 5, 0 );
        GfxSelectFont( "Tahoma", 9, 400 );
    }

    GfxTextOut( "Sound", 38, 176 );

    YourName = GuiGetText( 3 );

    if( YourName == "" )
    {
        GuiSetText( "Enter your name", 3 );
        YourName = "";
    }

    if( YourName == "Enter your name" ) YourName = "Anonymoususer";

    if( BestScoresReset ) StaticVarRemove( "BestResult" + MyChartID + YourName + "*" );

    RadioButton = Nz( StaticVarGet( "RadioButton" + MyChartID ), 6 ); //   ----------   Radio Buttons ---------------------------
    DifficultLevels = "Easy,250,Medium,200,Difficult,160,Insane,120";

    for( i = 1; i <= 4; i++ )
    {
        GuiRadio( "", 5 + i, 15, 60 + 22 * i, 13, 16, 1 );

        if( id == i + 5 && event == 1 AND StageCounter1 == 1 )  // If radio button is clicked
        {
            RadioButton = i + 5;
            StaticVarSet( "RadioButton" + MyChartID, RadioButton );
            DiffLevel = StrExtract( DifficultLevels, ( i - 1 ) * 2 );

            if( Sound ) Say( DiffLevel );
        }
    }

    for( i = 1; i <= 4; i++ )
    {
        if( RadioButton == i + 5 )
        {
            GuiSetCheck( i + 5, 1 );
            DiffLevel = StrExtract( DifficultLevels, ( i - 1 ) * 2 );

            if( i == 1 ) DiffColor = colorGreen;
            else
                if( i == 2 ) DiffColor = colorOrange;
                else
                    if( i == 3 ) DiffColor = colorRed;
                    else DiffColor = colorBlack;

            GfxSetTextColor( DiffColor );
            GfxSelectFont( "Tahoma", 10, 700 );

            if( StageCounter1 == 1 ) HowOften = StrToNum( StrExtract( DifficultLevels, ( i - 1 ) * 2 + 1 ) ) / 100;
            else HowOften = StrToNum( StrExtract( DifficultLevels, ( i - 1 ) * 2 + 1 ) ) / ( 100 + Counter );
        }
        else
        {
            GuiSetCheck( i + 5, 0 );
            GfxSetTextColor( ColorBlend( colorBlack, colorWhite, 0.25 ) );
            GfxSelectFont( "Tahoma", 9, 400 );
        }

        GfxTextOut( "" + StrExtract( DifficultLevels, ( i - 1 ) * 2 ), 37, 60 + 22 * i );
    }

//  ----------------------------------------------------------------------------------------
    if( NOT StageCounter1 == 1 OR( StageCounter1 == 1 AND StartButtonClicked ) )
    {
        if( StartButtonClicked )
        {
            switch( StageCounter1 )
            {
                case 1:  // Intro 1 start

                    StaticVarSet( "Counter" + MyChartID, Counter = 0 );
                    StaticVarSet( "HitsCounter" + MyChartID, HitsCounter = 0 );
                    StaticVarSet( "ClicksCounter" + MyChartID, ClicksCounter = 0 );
                    StaticVarSet( "StageCounter1" + MyChartID, StageCounter1 = 3 );
                    StaticVarSet( "LivesCounter" + MyChartID, LivesCounter = 5 );
                    StaticVarSet( "MissedCounter" + MyChartID, MissedCounter = 0 );
                    StaticVarSet( "WithoutClick" + MyChartID, 0 );
                    break;

                case 3:  // Intro 2 start

                    StaticVarSet( "StageCounter1" + MyChartID, StageCounter1 = 5 );
                    StaticVarSet( "StageCounter2" + MyChartID, StageCounter2 = 0 );
                    GameStart = 0;
                    break;

                case 5: // Game start

                    StaticVarSet( "StageCounter1" + MyChartID, StageCounter1 = 10 );
                    StaticVarSet( "StageCounter2" + MyChartID, StageCounter2 = 0 );
                    StaticVarSet( "LivesCounter" + MyChartID, LivesCounter = 5 );
                    GameStart = 0;

                    if( Sound ) Say( "Go!" );

                    break;

                case 10: // Game over

                    StaticVarSet( "StageCounter1" + MyChartID, StageCounter1 = 15 );
                    GameOver = 1;
                    break;

                case 15: // Return to Stage 1

                    StaticVarSet( "StageCounter1" + MyChartID, StageCounter1 = 1 );
                    GameOver = 1;
                    StaticVarSet( "RingColor" + MyChartID, MyGrey );

            }
        }

        if( StageCounter1 == 3 ) // ---------------------  I N T R O  1  --------------------------------------------

        {

            RequestTimedRefresh( 0.1, 1 );
            GuiSetText( "Intro 1 Stop", 1 );

            if( Status( "RedrawAction" ) )
            {
                Characters = "A,m,i,B,r,o,k,e,r,6,2,5,c,d,f,h,j,m,n,p,q,s,t,u,w,x,y,z,#,$,1,3,4,7,8,9,0";
                Phrases = "Excellence,Expertise,Stocks,Shares,Bonds,Technical Analysis,3D Optimization,Monte Carlo,Simulation,Walk-forward,Professional,Multi-threading,AmiBroker,Tomasz Janeczko,Algorythm,Quantitative Analysis,Performance,Optimization,Speed,Matrix,Investing,Stock Market,Forex,Commodities,NASDAQ,SP500,Backtesting,Exploration,Chart,Profit,Advantage,Traders,Quants,Futures,Custom Backtester,Portfolio-Level,Blazing fast,Smart Optimization";
                CharactersCount = StrCount( Characters, "," ); // Should be +1, but in my case, later I would need to substract 1
                PhrasesCount = StrCount( Phrases, "," ); //   -------  ''  ----------  ''  ----------- ''  --------------
                //         --------------------------------------   Phrases  ( Excellence etc. )
                GfxSetTextColor( ColorBlend( colorwhite, colorBlack, 0.5 ) );
                GfxSelectFont( "Arial", 25, 400 );

                PhraseNumber = round( mtRandom() * PhrasesCount );
                Phrase = StrExtract( Phrases, PhraseNumber );
                x = pxwidth / 2 - 330 + StageCounter2 * 3;

                if( x >= pxwidth / 2 - 48 )  x = pxwidth / 2 - 48;

                GfxTextOut( "" + Phrase, x, pxheight / 2 - 170 );

                //        --------------------------------------   Characters  ( A m i B r o k e r )
                GfxSetTextColor( ColorBlend( colorwhite, colorBlack, 0.8 ) );
                GfxSelectFont( "Arial", 40, 400 );
                GfxSetTextAlign( 6 );

                for( i = 1; i <= 9; i++ )
                {
                    CharNumber = round( mtRandom() * CharactersCount );

                    if( i * 10 + 100 >= StageCounter2 ) Char = StrExtract( Characters, CharNumber );
                    else Char = StrExtract( Characters, i - 1 );

                    x = pxwidth / 2 + i * 45 + 300 - StageCounter2 * 3.85;

                    if( x <= pxwidth / 2 + i * 45 - 80 ) x = pxwidth / 2 + i * 45 - 80;

                    GfxTextOut( "" + Char, x, pxheight / 2 - 125 );

                }

                GfxSetTextAlign( 0 | 0 );
                y = pxheight / 2 + 250 - StageCounter2 * 2.5;

                if( y <= pxheight / 2 ) y = pxheight / 2;

                Ring( pxwidth / 2, y, 0, 0, 44, 31, MyOrange );
                StageCounter2 ++;

            }

            StaticVarSet( "StageCounter2" + MyChartID, StageCounter2 );
        }

        if( StageCounter2 >= 210 )
        {
            GuiButton( "Start", 15, pxwidth / 2 - 24, pxheight / 2 - 10, 50, 22, 1 );

            if( id == 15 && event == 1 )
            {
                StaticVarSet( "StageCounter1" + MyChartID, StageCounter1 = 5 );
                StaticVarSet( "StageCounter2" + MyChartID, StageCounter2 = 0 );
                GameStart = 0;
            }

        }

        if( StageCounter1 == 5 )  // -----------------------------  I N T R O  2  --------------------------

        {

            RequestTimedRefresh( 0.5, 1 );
            GuiSetText( "Intro 2 Stop", 1 );

            if( Status( "RedrawAction" ) )
            {
                Text = "11,10,9,8,7,6,5,4,3,2,1,G,O,!";
                Char = StrExtract( Text, StageCounter2 );
                CharNumber = StrToNum( Char );

                if( Char == "G" OR Char == "O" OR Char == "!" )
                {
                    RingColor = MyGreen;
                    StaticVarSet( "LivesCounter" + MyChartID, 5 );
                }
                else
                    if( CharNumber < 4 )
                    {
                        RingColor = MyOrange;
                        StaticVarSet( "LivesCounter" + MyChartID, 4 );
                    }
                    else
                        if( CharNumber < 7 )
                        {
                            RingColor = MyRed;
                            StaticVarSet( "LivesCounter" + MyChartID, 2 );
                        }
                        else
                        {
                            RingColor = colorLightGrey;
                            StaticVarSet( "LivesCounter" + MyChartID, 0 );
                        }

                Ring( pxwidth / 2, pxheight / 2, 0, 0, 44, 31, RingColor );

                if( Sound )
                {
                    if( Char == "11" ) Say( "Prepare yourself for the game!", 1 );
                    else
                        if( Char == "6" ) Say( "Ready!", 1 );
                        else
                            if( Char == "3" ) Say( "Steady!", 1 );
                            else
                                if( Char == "G" ) Say( "Go !!!", 1 );
                }

                GfxSelectFont( "Arial", 40, 800 );
                GfxSetTextColor( colorGrey40 );
                GfxSetTextAlign( 6 );
                GfxTextOut( Char, pxwidth / 2, pxheight / 2 - 30 );
                GfxSetTextAlign( 0 | 0 );

                StageCounter2 ++;

                if( Char == "O" )
                {
                    StaticVarSet( "StageCounter1" + MyChartID, StageCounter1 = 10 );
                    StageCounter2 = 0;
                    GameStart = 0;

                }

                StaticVarSet( "StageCounter2" + MyChartID, StageCounter2 );

            }

        }

        if( StageCounter1 == 15 ) // --------------------------    G A M E  O V E R    ---------------

        {

            RequestTimedRefresh( 0.5, 1 );
            GuiSetText( "Stop", 1 );

            if( Status( "RedrawAction" ) )
            {
                Text = "G,A,M,E, ,O,V,E,R,,";
                Char = StrExtract( Text, StageCounter2 );

                if( StageCounter2 <= 2 ) RingColor = MyGreen;
                else
                    if( StageCounter2 <= 5 ) RingColor = MyOrange;
                    else
                        RingColor = MyRed;

                Ring( pxwidth / 2, pxheight / 2, 0, 0, 44, 31, RingColor );

                if( Sound ) if( Char == "G" ) ReadScore = 1;

                GfxSelectFont( "Arial", 40, 800 );
                GfxSetTextColor( colorGrey40 );
                GfxSetTextAlign( 6 );
                GfxTextOut( Char, pxwidth / 2, pxheight / 2 - 30 );
                GfxSetTextAlign( 0 | 0 );

                StageCounter2 ++;

                if( Char == "" )
                {
                    StaticVarSet( "StageCounter1" + MyChartID, StageCounter1 = 1 );
                    StaticVarSet( "RingColor" + MyChartID, MyGrey );
                    StageCounter2 = 0;
                    GameStart = 0;
                }

                StaticVarSet( "StageCounter2" + MyChartID, StageCounter2 );

            }

        }

        if( StageCounter1 == 10 AND GameStart AND NOT GameOver ) // -----------   G A M E   ------------------------------
        {
            GuiSetText( "Game Stop", 1 );
            PerformanceCounterBefore = Nz( StaticVarGet( "PerformanceCounterBefore" + MyChartID ) );
            PerformanceCounterNow = GetPerformanceCounter() / 1000;
            ElapsedSeconds =  PerformanceCounterNow - PerformanceCounterBefore;
            RequestTimedRefresh( HowOften, 1 );

            if( Status( "RedrawAction" ) AND ElapsedSeconds >= HowOften - 0.2 )
            {
                xRandom = Min( LastValue( Random() ) * pxwidth, pxwidth - 80 );
                yRandom = Min( LastValue( Random() ) * pxheight, pxheight - 80 );

                if( xRandom < 280 AND yRandom < 340 )
                {
                    xRandom += 280;
                    yRandom += 340;
                }

                if( Counter % 4 == 0 ) StaticVarSet( "ButtonType" + MyChartID, 3 ); // Radio
                else
                    if( Counter % 3 == 0 ) StaticVarSet( "ButtonType" + MyChartID, 2 ); // Checkbox
                    else StaticVarSet( "ButtonType" + MyChartID, 1 ); // Button

                WithoutClick = Nz( StaticVarGet( "WithoutClick" + MyChartID ) );

                PerformanceCounterMissedBefore = Nz( StaticVarGet( "PerformanceCounterMissedBefore" + MyChartID ) );
                PerformanceCounterMissedNow = GetPerformanceCounter() / 1000;
                ElapsedSecondsMissed =  PerformanceCounterMissedNow - PerformanceCounterMissedBefore;

                if( WithoutClick == 1 AND ElapsedSecondsMissed > 0.5 )
                {
                    {
                        LivesCounter --;
                        StaticVarSet( "LivesCounter" + MyChartID, LivesCounter );
                        MissedCounter++;
                        StaticVarSet( "MissedCounter" + MyChartID, MissedCounter );
                        StaticVarSet( "PerformanceCounterMissedBefore" + MyChartID, PerformanceCounterMissedNow );
                    }

                    if( Sound )
                    {
                        if( LivesCounter == 2 ) Say( "2 lives left!", 1 );
                        else
                            if( LivesCounter == 1 ) Say( "Last chance!", 1 );
                    }

                    if( LivesCounter == 0 )
                    {
                        if( Sound ) Say( "You're out of lives. ", 1 );

                        StaticVarSet( "StageCounter1" + MyChartID, StageCounter1 = 15 );
                        GameOver = 1;
                    }
                }

                Counter++;
                StaticVarSet( "Counter" + MyChartID, Counter );
                StaticVarSet( "FirstClick" + MyChartID, 1 );
                StaticVarSet( "RingColor" + MyChartID, colorLightGrey );
                StaticVarSet( "xRandom" + MyChartID, xRandom );
                StaticVarSet( "yRandom" + MyChartID, yRandom );
                StaticVarSet( "PerformanceCounterBefore" + MyChartID, PerformanceCounterNow );
                StaticVarSet( "WithoutClick" + MyChartID, 1 );
                StaticVarSet( "Hit" + MyChartID, 0 );

            }

            xRandom = StaticVarGet( "xRandom" + MyChartID );
            yRandom = StaticVarGet( "yRandom" + MyChartID );
            ButtonType = StaticVarGet( "ButtonType" + MyChartID );

            PerformanceCounterMissedBefore = Nz( StaticVarGet( "PerformanceCounterMissedBefore" + MyChartID ) );
            PerformanceCounterMissedNow = GetPerformanceCounter() / 1000;
            ElapsedSecondsMissed =  PerformanceCounterMissedNow - PerformanceCounterMissedBefore;

            if( id == Counter + 20 && event == 1 AND NOT GameOver ) // ----------------------    T A R G E T  H I T   ----------------------
            {
                if( StaticVarGet( "FirstClick" + MyChartID ) )
                {
                    HitTexts = "Great job ,Not bad ,Great!,Piece of cake!,Bull's eye!,Hit!,Excellent!,Target acquired!,Walk in the park!,Oh Yes!,You shoot like a pro!,You're the man,Terminated!,Damn you're good!";
                    MessageCount = StrCount( HitTexts, "," ); // Should be +1, but in my case I would need to substract 1 in the next line
                    MessageNumber = Round( mtRandom() * MessageCount );
                    Message = StrExtract( HitTexts, MessageNumber );

                    if( Sound )
                    {
                        if( MessageNumber > 1 ) Say( "" + Message, 1 );
                        else Say( "" + Message + YourName + "!", 1 );
                    }

                    GuiButtonClicked = 1;

                    if( LivesCounter < 5 ) LivesCounter++;

                    StaticVarSet( "LivesCounter" + MyChartID, LivesCounter );
                    HitsCounter++;
                    StaticVarSet( "HitsCounter" + MyChartID, HitsCounter );
                    ClicksCounter++;
                    StaticVarSet( "ClicksCounter" + MyChartID, ClicksCounter );
                    StaticVarSet( "FirstClick" + MyChartID, 0 );
                    StaticVarSet( "RingColor" + MyChartID, MyGreen );
                    StaticVarSet( "WithoutClick" + MyChartID, 0 );
                    StaticVarSet( "Hit" + MyChartID, 1 );

                }
                else  // Button clicked more than once
                {
                    if( Sound ) Say( "Don't click more than once!", 1 );

                    StaticVarSet( "RingColor" + MyChartID, MyOrange );
                }
            }
            else
                if( GetCursorMouseButtons() AND GuiButtonClicked == 0 AND NOT GameOver AND ElapsedSecondsMissed > 0.5 ) // -------------  T A R G E T  M I S S E D   ------------
                {

                    MissedTexts = "You've missed ,Shame on you ,Missed!,Overshoot!,Not good!,Target missed!,You've missed the target!,Overshoot!,Oh No!,No!,Fail,User Error,Bad luck!,Overshoot!";
                    MessageCount = StrCount( MissedTexts, "," ); // Should be +1, but in my case I would need to substract 1 in the next line
                    MessageNumber = Round( mtRandom() * MessageCount );
                    Message = StrExtract( MissedTexts, MessageNumber );

                    gcx  = Nz( GetCursorXPosition( 1 ) );
                    gcy  = Nz( GetCursorYPosition( 1 ) );

                    if( gcx > 240 OR gcy > 300 )

                    {

                        if( Sound )
                        {
                            if( MessageNumber > 1 ) Say( "" + Message, 0 );
                            else Say( "" + Message + YourName + "!", 0 );
                        }

                        GfxSelectPen( colorBlack, 1 );
                        GfxSelectSolidBrush( colorLightYellow );
                        GfxCircle( gcx, gcy, 20 );
                        GfxSelectSolidBrush( colorYellow );
                        GfxCircle( gcx, gcy, 12 );
                        GfxMoveTo( gcx, gcy - 25 );
                        GfxLineTo( gcx, gcy + 25 );
                        GfxMoveTo( gcx - 25, gcy );
                        GfxLineTo( gcx + 25, gcy );
                        GfxSelectSolidBrush( colorOrange );
                        GfxCircle( gcx, gcy, 5 );
                        ClicksCounter++;
                        StaticVarSet( "ClicksCounter" + MyChartID, ClicksCounter );

                        if( LivesCounter > 0 ) LivesCounter--;

                        StaticVarSet( "LivesCounter" + MyChartID, LivesCounter );
                        StaticVarSet( "PerformanceCounterMissedBefore" + MyChartID, PerformanceCounterMissedNow );

                        if( Sound )
                        {
                            if( LivesCounter == 2 ) Say( "2 lives left!", 1 );
                            else
                                if( LivesCounter == 1 ) Say( "Last chance!", 1 );
                        }

                        StaticVarSet( "RingColor" + MyChartID, MyRed );

                        if( LivesCounter == 0 )
                        {
                            Say( "You're out of lives! ", 1 );
                            StaticVarSet( "StageCounter1" + MyChartID, StageCounter1 = 15 );
                            GameOver = 1;
                        }

                        StaticVarSet( "WithoutClick" + MyChartID, 0 );
                        StaticVarSet( "Hit" + MyChartID, 0 );
                        MissedCounter++;
                        StaticVarSet( "MissedCounter" + MyChartID, MissedCounter );

                    }
                }

            RingColor = StaticVarGet( "RingColor" + MyChartID );

            switch( ButtonType )
            {
                case 3:  // Radio
                    GuiRadio( "", Counter + 20, xRandom, yRandom, 13, 16, 1 );
                    Ring( xRandom, yRandom, 5, 7, 44, 31, RingColor );
                    break;

                case 2:  // Checkbox
                    GuiCheckBox( "", Counter + 20, xRandom, yRandom, 15, 19, 1 );
                    Ring( xRandom, yRandom, 6, 8, 44, 31, RingColor );
                    break;

                default:  // Button
                    GuiButton( "Target", Counter + 20, xRandom, yRandom, 50, 22, 1 );

                    if( StaticVarGet( "Hit" + MyChartID ) ) GuiSetText( "Hit!", Counter + 20 );

                    Ring( xRandom, yRandom, 25, 9, 46, 33, RingColor );
            }
            
        }

    }

    GfxSelectFont( "Arial", 9, 700 );
    GfxSetTextColor( colorRed );
    GfxTextOut( "AmiBroker 6.25 - Buttons Hunter !", 14, 6 );

    if( MissedCounter == 0 ) accuracy = 100;
    else accuracy = round( ( HitsCounter + 1 ) / ( HitsCounter + MissedCounter + 1 ) * 100 );

    Score = HitsCounter - MissedCounter;

    if( ReadScore )
    {
        BestResult = StaticVarGet( "BestResult" + MyChartID + YourName + DiffLevel );
        Say( "Game over. Thanks for playing " + YourName + ". Your score is " + score + " points. ", 0 );

        if( IsNull( BestResult ) )
        {
            Say( "It was your first play on level " + DiffLevel, 0 );
            StaticVarSet( "BestResult" + MyChartID + YourName + DiffLevel, score, 1 );
        }
        else
            if( score > BestResult )
            {
                Say( "It's your best result on level " + DiffLevel + ". Congratulations.", 0 );
                StaticVarSet( "BestResult" + MyChartID + YourName + DiffLevel, score, 1 );
            }
            else
                if( score == BestResult ) Say( "Exactly the same as your best result on level " + DiffLevel , 0 );
                else
                {
                    WorseThan = BestResult - score;
                    Say( "" + WorseThan + " worse than your best result on level " + DiffLevel + ". Next time will be better" , 0 );
                }
    }

    x1 = 117;
    GfxSelectPen( ColorBlend( colorBlack, colorWhite, 0.65 ), 2 );
    GfxCircle( x1 + 75, 87, 13 );
    GfxCircle( x1 + 75, 119, 13 );
    GfxCircle( x1 + 75, 151, 13 );
    GfxCircle( x1 + 75, 183, 13 );
    GfxCircle( x1 + 75, 45, 18 );
    GfxSelectPen( ColorBlend( colorBlack, colorWhite, 0.5 ), 2 );
    GfxCircle( 92, 225, 18 );
    RingColor = Nz( StaticVarGet( "RingColor" + MyChartID ), colorLightGrey );;
    GfxSelectSolidBrush( RingColor );
    GfxSelectPen( ColorBlend( colorBlack, colorWhite, 0.7 ), 1 );
    GfxCircle( 190, 225, 25 );
    GfxSelectPen( RingColor, 2 );
    GfxSelectSolidBrush( colorWhite );
    GfxCircle( 190, 225, 18 );
    GfxSetTextAlign( 6 );
    GfxSetTextColor( colorBlack );
    GfxSelectFont( "Tahoma", 9, 700 );

    if( StageCounter1 == 3 ) RefreshInfo = 0.1;
    else
        if( StageCounter1 == 5 ) RefreshInfo = 0.5;
        else RefreshInfo = LastValue( Prec( HowOften, 2 ) );

    GfxTextOut( "" + RefreshInfo, x1 + 75, 37 );

    if( Counter < 100 ) GfxSelectFont( "Tahoma", 9, 700 );
    else GfxSelectFont( "Tahoma", 8.5, 700 );

    GfxTextOut( "" + Counter, x1 + 75, 80 );
    GfxTextOut( "" + ClicksCounter, x1 + 75, 112 );
    GfxSetTextColor( colorGreen );
    GfxTextOut( "" + HitsCounter, x1 + 75, 144 );
    GfxSetTextColor( colorRed );
    GfxTextOut( "" + MissedCounter, x1 + 75, 176 );
    GfxSetTextColor( colorBlack );
    GfxTextOut( "" + accuracy, 92, 218 );

    if( score > 0 ) ColorScore = colorGreen;
    else ColorScore = colorRed;

    GfxSelectFont( "Tahoma", 7, 400 );
    GfxSetTextColor( ColorBlend( colorBlack, colorWhite, 0.2 ) );
    GfxTextOut( "( % )", 40, 238 );
    GfxSelectFont( "Tahoma", 12, 700 );
    GfxSetTextColor( colorScore );
    GfxTextOut( "" + score, 191, 216 );
    GfxSelectFont( "Tahoma", 9, 400 );
    GfxSetTextColor( colorBlack );
    GfxSetTextAlign( 0 | 0 );
    GfxTextOut( "Refresh", x1, 35 );
    GfxTextOut( "Counter: ", x1, 80 );
    GfxTextOut( "Clicks: ", x1, 112 );
    GfxTextOut( "Hits: ", x1, 144 );
    GfxTextOut( "Missed: ", x1, 176 );
    GfxTextOut( "Accuracy: ", 13, 220 );
    GfxTextOut( "Score: ", 118, 220 );

    LivesCounter = Nz( StaticVarGet( "LivesCounter" + MyChartID ), 5 ); // ---------   L I V E S  ------------
    GfxSelectPen( colorLightGrey, 1 );

    for( i = 1 ; i <= 5; i++ )

    {

        if( StageCounter1 == 1 ) GfxSelectSolidBrush( ColorBlend( colorBlack, colorWhite, 0.7 ) );
        else
            if( i <= LivesCounter ) GfxSelectSolidBrush( MyGreen );
            else GfxSelectSolidBrush( MyRed );

        GfxRoundRect( 225 - i * 43, 260, 250 - i * 43, 272, 10, 10 );
    }

}

else

{
    GfxSetTextColor( colorBlack );
    GfxTextOut( "Buttons Hunter!  The chart is too small. Minimum size is 1100x600.", 10, 30 );
}

_SECTION_END();

Regards

Miłosz


GuiButtons for everyone
#3

Could I ask someone to take a screenshot (and post it here) of this game under Windows 10? I wonder how do the GUI buttons look like, do they stand out from the background etc. I think that “Predefined chart theme” sholudn’t have any impact in this case. It can be a screenshot similar to the one from my first post (with the start button in the middle of the screen) or any other with the “Target” button visible.

Thanks in advance :slight_smile:


By the way, if someone doesn’t like the messages spoken after each hit/miss, he/she can easily change them or add the new ones, editing just 1 line of code:

HitTexts = "Great job ,Not bad ,Great!,Piece of cake!,Bull's eye!,Hit!,Excellent!,Target acquired!,Walk in the park!,Oh Yes!,You shoot like a pro!,You're the man,Terminated!,Damn you're good!";

and:

MissedTexts = "You've missed ,Shame on you ,Missed!,Overshoot!,Not good!,Target missed!,You've missed the target!,Overshoot!,Oh No!,No!,Fail,User Error,Bad luck!,Overshoot!";

The first two (from each string variables) are later followed by the user name (if provided). The code should work properly no matter how many messages there are.


#4

Ami0625_Game_ButtonHunter

Environment Details:
Windows 10 Pro 64

AmiBroker > Tools > Customize > Appearance:
ToolBars & menus: Visual Studio 2010
Panes & tabs: Visual Studio 2010

Regards

Sanjiv Bansal


#5

Thanks a lot @Sumangalam :slight_smile:

It’s good to see, that the game looks exactly as I expected.

Regards