4D SYSTEMS FORUM HAS MOVED

Please navigate to http://forum.4dsystems.com.au

This forum is READ ONLY and is DISABLED, please use the new forum

PLEASE do not attempt to change your details. Email webmaster@4dsystems.com.au if you are having problems with the new forum

For all Tech Support, please use the Support Ticket System, from our website. http://www.4dsystems.com.au/support



4D SYSTEMS FORUM
New Posts
 
 
 


Reply
 
Author Comment
 
RadarLove

Registered: 09/03/12
Posts: 9
 #1 
So my group and I made a Radar Pong game. It uses the µVGA-II GFX2.

It looks good and works most times, but what can be done about the flickering of the paddles and the slowing way down when a sound plays? Other than those quirks it still works and is playable with the radar equipment. You can comment out the ard_input variable and use a random position for the paddles if you'd like to run the code as a demo. You might have to disable the media files such as pictures and sound too.

1.) How to fix paddle flickering?
2.) How to stop slow downs/lagging when a sound is playing? (Maybe a "2nd thread"?)


Code:

Quote:
#platform "uVGA-II_GFX2"
/*  4DGL Simple Pong Demo
*/
#inherit "4DGL_16bitColours.fnc"

#CONST
    TRIANGLE    3
    RECTANGLE   4
    PENTAGON    5
    HEXAGON     6
    LEFTCOLOR   0xF800
    RIGHTCOLOR  0xF800
    TOPCOLOR    DARKGREEN
    BOTTOMCOLOR DARKGREEN
#END

#constant WALL     20   // outer wall thickness

#CONST
    LEFTHIT     WALL
    RIGHTHIT    640-WALL
    TOPHIT      WALL
    BOTTOMHIT   480-WALL
#END

// constants for the viewport
#CONST
    windowXpos   WALL
    windowYpos   WALL
    windowWidth  640-WALL
    windowHeight 480-WALL
#END

// constant object definitions
#constant ERASEBALL     $ball_x, ball_y, 3, BLACK
#constant DRAWBALL      $ball_x, ball_y, 3, ball_color
#constant LEFTWALL      $0, 0, WALL , 480, LEFTCOLOR
#constant RIGHTWALL     $640-WALL , 0, 640, 480, RIGHTCOLOR
#constant TOPWALL       $0, 0, 640-WALL, WALL , TOPCOLOR
#constant BOTTOMWALL    $gfx_Rectangle(0, 480-WALL, 640, 480, BOTTOMCOLOR)

//----------------------------------------------------------------------------------------//
var ball_x, ball_y, ball_r, ball_color, ball_type;
var ard_input := 0;
var XSPEED, YSPEED;

// Set the color, width, height and min and max speed of paddles
var lpaddle_color := WHITE;
var rpaddle_color := DARKGREEN;
var lpaddle_width := 27;
var lpaddle_height := 110;
var rpaddle_width := 30;
var rpaddle_height := 120;
var minSpeed := 5;
var maxSpeed := 12;

// Set starting positions of paddles
var lpaddle_x1 := 30;
var lpaddle_y1 := 180;
var rpaddle_x1 := 570;
var rpaddle_y1 := 430;

// initialize the other coordinates for starting positions
var lpaddle_x2 := lpaddle_x1 + lpaddle_width;
var lpaddle_y2 := lpaddle_y1 + lpaddle_height;
var rpaddle_x2 := rpaddle_x1 + rpaddle_width;
var rpaddle_y2 := rpaddle_y1 + rpaddle_height;

var xdir, ydir, angle, lscore, rscore, games;
var targetX, targetY;
var Xcoords[6], Ycoords[6];
//----------------------------------------------------------------------------------------//

func resetGame()
    ball_type := 0;
    angle := 0;
    lscore := 0;
    rscore := 0;
    games++;
    SEED(sys_T());
    ball_type := ABS(RAND()%8);
    minSpeed := 5;
    maxSpeed := 12;
    loseScreen();
    splash();
    resetBall();
    drawWalls();
endfunc

func loseScreen()
    gfx_Set(CLIPPING, OFF);
    gfx_Set(PEN_SIZE, SOLID);       // clear the window
    gfx_Rectangle(0, 0, 640, 480, BLACK);

    var i := 0;

    repeat          // display scoreboard
        while(!media_Init());
            media_SetSector(0x003B,0x9D61);
            media_Image(0,0);
            while(!file_Mount())
            wend
            if(file_Exists("sadtrom.wav"))
                snd_Volume(100);
                file_PlayWAV("sadtrom.wav");
                while(snd_Playing());
            endif
            i++;
    until(i>1);
endfunc

func resetBall()
    angle := 0;
    ball_color := WHITE;                    // initial ball colour
    xdir := 1; ydir := 1;                   // initial ball direction
    ball_x := 320; ball_y := 240;           // initial ball position

    XSPEED := ABS(RAND()%100)/10;
    YSPEED := ABS(RAND()%100)/10;

    increaseSpeed();
    checkSpeed();

    gfx_Set(CLIPPING, OFF);                 // clear the window
    gfx_Set(PEN_SIZE, SOLID);
    gfx_Rectangle(0, 0, 640, 480, BLACK);

    drawWalls();
endfunc

func checkSpeed()
    if(XSPEED < minSpeed)
        XSPEED := minSpeed;
    endif
    if(YSPEED < minSpeed)
        YSPEED := minSpeed;
    endif

    if(XSPEED > maxSpeed)
        XSPEED := maxSpeed;
    endif
    if(YSPEED > maxSpeed)
        YSPEED := maxSpeed;
    endif
endfunc

func increaseSpeed()
    if(lscore >= 3)
        minSpeed := minSpeed + lscore;
        maxSpeed := maxSpeed + lscore;
    endif
endfunc

func drawPicPaddle()
    gfx_Set(CLIPPING, ON);
    while(!media_Init());
        media_SetSector(0x003B,0x98A4);
        media_Image(lpaddle_x1, lpaddle_y1);
    while(!media_Init());
        media_SetSector(0x003B,0x9895);
        media_Image(rpaddle_x1, rpaddle_y1);
    //gfx_Set(CLIPPING, OFF);
endfunc

func erasePicPaddle()
    gfx_Set(CLIPPING, ON);
    drawPaddle(lpaddle_x1, lpaddle_y1, lpaddle_x2, lpaddle_y2, BLACK);
    drawPaddle(rpaddle_x1, rpaddle_y1, rpaddle_x2, rpaddle_y2, BLACK);
    //gfx_Set(CLIPPING, OFF);
endfunc

func Score()
    var n, x, y, r;
    gfx_ClipWindow(ball_x-20, ball_y-20, ball_x+20, ball_y+20);
    gfx_Set(CLIPPING, ON);
    r := sys_T();

    // a really cheap looking explosion of dots
    n := -1000;
    SEED(r);
    while (n++<1000)
        x := ABS(RAND()%ball_x) + ball_x;
        y := ABS(RAND()%ball_y) + ball_y;
        gfx_PutPixel(x , y , RAND());
    wend

    // undraw the dots
    n := -1000;
    SEED(r);
    while (n++<1000)
        x := ABS(RAND()%ball_x) + ball_x;
        y := ABS(RAND()%ball_y) + ball_y;
        RAND();
        gfx_PutPixel(x , y , 0);
    wend

    gfx_Set(CLIPPING, OFF);
    drawWalls();

    gfx_ClipWindow(windowXpos, windowYpos, windowWidth, windowHeight);
endfunc

func drawWalls()
    gfx_Set(PEN_SIZE, SOLID);
    gfx_Rectangle(TOPWALL);     // Draw Top Wall
    BOTTOMWALL;                 // Draw Bottom Wall
    gfx_Rectangle(LEFTWALL);    // Draw Left Wall
    gfx_Rectangle(RIGHTWALL);   // Draw Right Wall
endfunc

func drawPaddle(var pad_x1, var pad_y1, var pad_x2, var pad_y2, var pad_color)
    gfx_Set(PEN_SIZE, SOLID);
    gfx_Rectangle(pad_x1, pad_y1, pad_x2, pad_y2, pad_color);
endfunc

func splash()
    gfx_Set(CLIPPING, OFF);
    gfx_Set(PEN_SIZE, SOLID);       // clear the window
    gfx_Rectangle(0, 0, 640, 480, BLACK);
    var i := 0;
    if(games%2)
        repeat          // display MITLL logo for a few seconds
            while(!media_Init());
                media_SetSector(0x003B,0x9401);
                media_Image(0,208);
                i++;
        until(i>20);
    else
        repeat          // display MSU logo for a few seconds
            while(!media_Init());
                media_SetSector(0x003B,0x94A2);
                media_Image(50,0);
                i++;
        until(i>20);
    endif
    gfx_Set(PEN_SIZE, SOLID);       // clear the window
    gfx_Rectangle(0, 0, 640, 480, BLACK);

        repeat          // display pong rules
            while(!media_Init());
                media_SetSector(0x003B,0x98B0);
                media_Image(0,0);
                i++;
        until(i>30);

    gfx_Set(PEN_SIZE, SOLID);       // clear the window
    gfx_Rectangle(0, 0, 640, 480, BLACK);
endfunc

func collision()
    if(ball_x <= LEFTHIT)
        ball_x := LEFTHIT;
        xdir := -xdir;
        rscore++;
        Score();
        resetBall();
    endif

    if(ball_x >= RIGHTHIT)
        ball_x := RIGHTHIT;
        xdir := -xdir;
        lscore++;
        Score();
        resetBall();
    endif

    if (ball_y <= TOPHIT)
        ball_y := TOPHIT;
        ydir := -ydir;

        SEED(sys_T());
        YSPEED := YSPEED + (RAND()%4);
        increaseSpeed();
        checkSpeed();
    endif

    if(ball_y >= BOTTOMHIT)
        ball_y := BOTTOMHIT;
        ydir := -ydir;

        SEED(sys_T());
        YSPEED := YSPEED + (RAND()%4);
        increaseSpeed();
        checkSpeed();
    endif
endfunc

func padCollision()
// left paddle collision detection
if(ball_y >= lpaddle_y1)
        if(ball_y <= lpaddle_y2)
            if(ball_x <= lpaddle_x2)
                ball_x := lpaddle_x2;
                xdir := -xdir;

// bounce sound
                file_PlayWAV("bighit.wav");
                while(snd_Playing());

                lscore++;
                SEED(sys_T());
                XSPEED := XSPEED + (RAND()%4);
                increaseSpeed();
                checkSpeed();
        endif
    endif
endif

// right paddle collision detection
if(ball_y >= rpaddle_y1)
    if(ball_y <= rpaddle_y2)
         if(ball_x >= rpaddle_x1)
            ball_x := rpaddle_x1;
            xdir := -xdir;

// bounce sound
            file_PlayWAV("bighit.wav");
            while(snd_Playing());

            rscore++;
            SEED(sys_T());
            XSPEED := XSPEED + (RAND()%4);
            increaseSpeed();
            checkSpeed();
        endif
    endif
endif
endfunc

// Displays various counters, score, debug information
func UpdateCounter()
/*
    gfx_MoveTo(100, 160);
    txt_Set(TEXT_COLOUR, RED);
    to(GFX); putstr("ard_input: ");
    to(GFX); putnum(DEC3, ard_input);

    gfx_MoveTo(100, 175);
    txt_Set(TEXT_COLOUR, RED);
    to(GFX); putstr("lpaddle_y1: ");
    to(GFX); putnum(DEC3, lpaddle_y1);

    gfx_MoveTo(100, 190);
    txt_Set(TEXT_COLOUR, RED);
    to(GFX); putstr("XSPEED: ");
    to(GFX); putnum(DEC2, XSPEED);

    gfx_MoveTo(100, 205);
    txt_Set(TEXT_COLOUR, RED);
    to(GFX); putstr("YSPEED: ");
    to(GFX); putnum(DEC2, YSPEED);
*/
    // update scores
    gfx_MoveTo(80, 350);
    txt_Set(TEXT_COLOUR, lpaddle_color);
    txt_Set(TEXT_OPACITY, OPAQUE);
    txt_Set(TEXT_BOLD, ON);
    txt_Set(TEXT_WIDTH, 4);
    txt_Set(TEXT_HEIGHT, 4);
    to(GFX); putnum(DEC3, lscore);

    gfx_MoveTo(480, 350);
    txt_Set(TEXT_COLOUR, rpaddle_color);
    to(GFX); putnum(DEC3, rscore);
    txt_Set(TEXT_BOLD, OFF);
    txt_Set(TEXT_WIDTH, 1);
    txt_Set(TEXT_HEIGHT, 1);
endfunc

//----------------------------------------------------------------------------------------//
// Builds a polygon with a number of sides determined by var "sides"
// around the current origin. The distance from the origin to the
// equidistent vertices from origin determined
// by var "distance". var "angle" is the starting angle for the
// first virtices. Draws the polygon in color var "colr"
// NB make sure the array is big enough for the required number of sides
//----------------------------------------------------------------------------------------//
func MakePolygon(var angle2, var sides, var distance, var colr)
    var index, step;
    index := 0;
    step := 360/sides;                 // work out the step size
    while (sides < 360)                // until we do a complete polygon
        gfx_Orbit(angle2, distance);
        Xcoords[index] := targetX;     // build a polygon in the matrix
        Ycoords[index] := targetY;
        index++;
        angle2 := angle2 + step;
        sides := sides + step;
    wend
    gfx_Polygon(index, Xcoords, Ycoords, colr);
endfunc
//----------------------------------------------------------------------------------------//

//----------------------------------------------------------------------------------------//
func main()
    SEED(sys_T());
    bus_Set(1);
    gfx_OrbitInit(&targetX, &targetY);
    file_Mount();
    snd_Volume(100);

    splash();

    // preset the clipping area, activated later...
    gfx_ClipWindow(windowXpos, windowYpos, windowWidth, windowHeight);
    gfx_Cls();

    // draw initial objects and init score
    drawWalls();
    resetBall();
    lscore := 0;
    rscore := 0;

    repeat
        pause(12);                      // there is no vsync control, pause

        if(lscore >= 10)
            resetGame();
        endif
        if(rscore >= 10)
            resetGame();
        endif

        ard_input := bus_Read();

        UpdateCounter();

        // undraw ball and paddles
        erasePicPaddle();

        switch
            case(ball_type == 0)
                gfx_MoveTo(ball_x, ball_y);                 // using the balls origin
                MakePolygon(angle, TRIANGLE, 10, BLACK);    // undraw old triangle

            case(ball_type == 1)
                gfx_MoveTo(ball_x, ball_y);                 // using the balls origin
                MakePolygon(angle, RECTANGLE, 10, BLACK);   // undraw old rectangle

            case(ball_type == 2)
                gfx_MoveTo(ball_x, ball_y);                 // using the balls origin
                MakePolygon(angle, PENTAGON, 10, BLACK);    // undraw old rectangle

            case(ball_type == 3)
                gfx_MoveTo(ball_x, ball_y);                 // using the balls origin
                MakePolygon(angle, HEXAGON, 10, BLACK);     // undraw old rectangle

            default:
                if(ball_type >= 4)
                    gfx_Set(PEN_SIZE, SOLID);
                    gfx_Circle(ERASEBALL);                  // erase the ball
                endif
        endswitch

        // move  ball to new position
        ball_x := ball_x + xdir * XSPEED;                   // move to new X pos
        ball_y := ball_y + ydir * YSPEED;                   // move to new Y pos
        collision();
        padCollision();

        angle := angle + 10;                                // step to new angle

        // move paddles to new positions
/*
        // left paddle AI is random
        lpaddle_y1 := lpaddle_y1 - (RAND()%40);
        lpaddle_x2 := lpaddle_x1 + lpaddle_width;
        lpaddle_y2 := lpaddle_y1 + lpaddle_height;
*/
        // get new position from arduino
        //lpaddle_y1 := 10*ard_input;

    switch
        case((ard_input >= 14) && (ard_input < 22))
            lpaddle_y1 := 20;
        case((ard_input >= 22) && (ard_input < 30))
            lpaddle_y1 := 130;
        case((ard_input >= 30) && (ard_input < 37))
            lpaddle_y1 := 240;
        case(ard_input >= 37)
            lpaddle_y1 := 350;
        default:
    endswitch

        lpaddle_x2 := lpaddle_x1 + lpaddle_width;
        lpaddle_y2 := lpaddle_y1 + lpaddle_height;
/*
        if(lpaddle_y1 <= TOPHIT)
            lpaddle_y1 := TOPHIT;
            lpaddle_y2 := TOPHIT + lpaddle_height;
        endif
        if(lpaddle_y2 >= BOTTOMHIT)
            lpaddle_y2 := BOTTOMHIT;
            lpaddle_y1 := BOTTOMHIT - lpaddle_height;
        endif
*/
        // right paddle AI ALWAYS WINS!!!
        rpaddle_y1 := ball_y - rpaddle_height/2;
        rpaddle_x2 := rpaddle_x1 + rpaddle_width;
        rpaddle_y2 := rpaddle_y1 + rpaddle_height;

        if(rpaddle_y1 <= TOPHIT)
            rpaddle_y1 := TOPHIT;
            rpaddle_y2 := TOPHIT + rpaddle_height;
        endif
        if(rpaddle_y2 >= BOTTOMHIT)
            rpaddle_y2 := BOTTOMHIT;
            rpaddle_y1 := BOTTOMHIT - rpaddle_height;
        endif

        // redraw ball and paddles
        switch
            case(ball_type == 0)
                gfx_MoveTo(ball_x, ball_y);                     // using the balls origin
                MakePolygon(angle, TRIANGLE, 10, ball_color);   // draw triangle

            case(ball_type == 1)
                gfx_MoveTo(ball_x, ball_y);
                MakePolygon(angle, RECTANGLE, 10, ball_color);  // draw rectangle

            case(ball_type == 2)
                gfx_MoveTo(ball_x, ball_y);
                MakePolygon(angle, PENTAGON, 10, ball_color);   // draw rectangle

            case(ball_type == 3)
                gfx_MoveTo(ball_x, ball_y);
                MakePolygon(angle, HEXAGON, 10, ball_color);    // draw rectangle

            default:
                if(ball_type >= 4)
                    gfx_Set(PEN_SIZE, SOLID);
                    gfx_Circle(DRAWBALL);                       // draw the ball
                endif
        endswitch

        //drawPaddle(lpaddle_x1, lpaddle_y1, lpaddle_x2, lpaddle_y2, lpaddle_color);
        //drawPaddle(rpaddle_x1, rpaddle_y1, rpaddle_x2, rpaddle_y2, rpaddle_color);

    drawPicPaddle();
    forever
endfunc
//----------------------------------------------------------------------------------------//



ESPsupport

Avatar / Picture

Moderator
Registered: 27/01/09
Posts: 5,854
 #2 

Unfortnately, since I don't have your images, or sound files I can't work out exactly what is causing your problems, but I think I can hazzard a couple of good guesses.

 

1. You are erasing the old paddles, doing heaps of calculations, drawing new paddles and then pausing for a bit. Reorder that to doing heaps of calculations, erasing the old paddles, drawing new paddles and then pausing for a bit. The idea is to keep the image static for the longest possible period of time.

 

2. There is only one Picaso Processor, so a second thread wont help, actually there is effectively already a sound thread, which is why you can do anything at all whilst sound is playing. The old pong games would lock up whilst they played a sound, this always seemd the ugliest part of the game to me.

 

The amount of 'slowdown' will be affected by the complexity of your wav file. If it is 44khz stereo 16bit, it will take 22x more effort to play than a 8khz mono 8 bit wav file. Have a look at what you are using and see if it can be simplified easily and still sound good.

 

The other possiblity is to build it into your program. A complex thing to do would be to try and manage a continuing sound effect, that changes when needed.

 

A simpler method would be to change the delay loop, eg

    if (snd_Playing())

        pause(2);         // sound playing, short pause

    else

        pause(12) ;      // no sound, long pause
    endif

I have no idea about the values, it will depend on the compexity of your wav files.

 

Also note, there is a disp_Sync() command that might be of use to you in this, although I'd only use it if it was definitely needed.

 

This looks really good, maybe could use an ADC0804 to replace the Arduino for use in another project  Even better, if you could wait a little while Diablo16 wouldn't even need the extra chip http://4d.websitetoolbox.com/post?id=5817069

 


__________________
Mark
RickCortese

Registered: 18/10/11
Posts: 6
 #3 
Still a bit of a rookie with 4d programming so I may be off in my assumptions.

You use erase ~6 places, this seems to repeat as you move the ball and paddles. A quicker way to do it: Let's say you are moving an object like a paddle vertically. Instead of erasing the previous paddle you just define the top and bottom of the paddle as the same color as the back ground and the distance moved. Let's say you only move 1 vertical pixel, you would have your paddle defined as
bbb
ccc
ccc
ccc
ccc
ccc
bbb
where c is the color you want your paddle and b is the background color. Now as you move your paddle up or down it becomes self erasing. Of course you need to have the background part as wide as your biggest move or it will leave streaks.
Likewise for the ball you would use something like
bbbb
bccb
bccb
bccb
bbbb
There will be a slight glitch/indentation when the ball and paddle over lap but speed will improve and program should be shorter. If you are already doing this, my apologies. Kind of hard to tell w/o seeing the actual graphics.

Rick
Previous Topic | Next Topic
Print
Reply

Quick Navigation:

Powered by Website Toolbox - Create a Website Forum Hosting, Guestbook Hosting, or Website Chat Room for your website.