SRL Archive - Help and Support

Annoying Bug in Loop


WhoCares357

2008-08-18 00:08:22

I've wasted about an hour going over my script over and over and am yet to find the cause for my latest dilemma. I've learned that it's always easier to see someone's mistakes than one's own.

So my problem is as follows:

I used the tutrial by solemn wishes to get the basic idea of using bitmaps in SCAR. I then proceeded to make my first game, Ping Pong.

I lay down the basic structure of the game (make the ball bounce off the top/bottom walls, make the ball bounce off the paddles, etc.) but I ran into a very annoying problem. Before I go on any further, I'll show you the script. Do note that this is in very early development (so don't judge harshly :)).

program Pong;   //by WhoCares357

//custom types for objects
type
Ball = record
x1, y1: Integer; //position
speedX, speedY: Integer;
dirD, dirV: Boolean; //dirD = direction diagonal; dirV = direction vertical
//up/right = true
img: Integer;
end;

Paddle = record
x1, y1: Integer; //position
dirV: Boolean; //up = true
img: Integer;
end;

//var declarations
var
t_buffer: Integer;
ourBall: Ball;
ourPaddle: Array [0..1] of Paddle;
menu, gOver: Boolean;

label
startOver;


procedure SetupBackground;
begin
//set up window
DisplayDebugImgWindow(800, 600);
t_buffer := BitmapFromString(800, 600, '');
FastDrawClear(t_buffer, clblack);
end;


procedure SetupImages;
begin
//load images
ourBall.img := Loadbitmap(ScriptPath + 'ball.bmp');
ourPaddle[0].img := LoadBitmap(ScriptPath + 'paddle.bmp');
ourPaddle[1].img := LoadBitmap(ScriptPath + 'paddle.bmp');

//set transparencies
SetTransparentColor(ourBall.img, clblack);
SetTransparentColor(ourPaddle[0].img, clblack);
SetTransparentColor(ourPaddle[1].img, clblack);
end;


procedure SetupVars;
begin
//setup starter variables
ourBall.x1 := 400;
ourBall.y1 := 300;
ourPaddle[0].x1 := 2;
ourPaddle[0].y1 := 290;
ourPaddle[1].x1 := 794;
ourPaddle[1].y1 := 290;

ourBall.speedX := random(2) + 1;
ourBall.speedY := random(2) + 1;

ourBall.dirD := true;
ourBall.dirV := true;

gOver := false;
end;

//main loop
begin
SetupBackground;
SetupImages;

startOver:
SetupVars;
repeat
Wait(1);
until(IsKeyDown(Chr(32)));

//main game loop
while(gOver = false) do
begin
if IsArrowDown(0) then ourPaddle[1].y1 := ourPaddle[1].y1 - 3;
if IsArrowDown(2) then ourPaddle[1].y1 := ourPaddle[1].y1 + 3;

//check top/bottom wall hit
if (ourBall.y1 <= 1) then
ourBall.dirV := false;
if (ourBall.y1 >= 599) then
ourBall.dirV := true;

//check paddles; right/left walls hit
if (ourBall.x1 <= ourPaddle[0].x1 + 6) and (ourPaddle[0].y1 <= ourBall.y1) //[0]
and (ourPaddle[01].y1 + 50 >= ourBall.y1) then
begin
ourBall.dirD := false;
end else
if (ourBall.x1 <= 1) then
begin
gOver := true;
end;

if (ourBall.x1 + 6 >= ourPaddle[1].x1) and (ourPaddle[1].y1 <= ourBall.y1) //[1]
and (ourPaddle[1].y1 + 50 >= ourBall.y1) then
begin
ourBall.dirD := false;
end else
if (ourBall.x1 <= 799) then
begin
gOver := true;
end;

//move ball according to directions
if ourBall.dirD then //diagonal
begin
ourBall.x1 := ourBall.x1 + ourBall.speedX;
end else
ourBall.x1 := ourBall.x1 - ourBall.speedX;
if ourBall.dirV then //vertical
begin
ourBall.y1 := ourBall.y1 - ourBall.speedY;
end else
ourBall.y1 := ourBall.y1 + ourBall.speedY;

//draw everything
SafeDrawBitmap(t_buffer, GetDebugCanvas, 0, 0); //background
FastDrawClear(t_buffer, clblack);
FastDrawSizeTransparent(ourBall.x1, ourBall.y1, ourBall.x1+5, //ball
ourBall.y1+5, ourBall.img, t_buffer);
FastDrawSizeTransparent(ourPaddle[0].x1, ourPaddle[0].y1, ourPaddle[0].x1+4, //left paddle
ourPaddle[0].y1+50, ourPaddle[0].img, t_buffer);
FastDrawSizeTransparent(ourPaddle[1].x1, ourPaddle[1].y1, ourPaddle[1].x1+4, //right paddle
ourPaddle[1].y1+50, ourPaddle[1].img, t_buffer);

end;

goto startOver;
end.

Okay, it's a lot so I'll break it down a bit:

//custom types for objects
type
Ball = record
x1, y1: Integer; //position
speedX, speedY: Integer;
dirD, dirV: Boolean; //dirD = direction diagonal; dirV = direction vertical
//up/right = true
img: Integer;
end;

Paddle = record
x1, y1: Integer; //position
dirV: Boolean; //up = true
img: Integer;
end;

//var declarations
var
t_buffer: Integer;
ourBall: Ball;
ourPaddle: Array [0..1] of Paddle;
menu, gOver: Boolean;

I just set up some custom "types" for the ball and paddle. Then I set up the variables. t_buffer is the buffer for the background bitmap.

label
startOver;

I set up a label here to use it in the main game loop later. I use this to have the script go back to the beginning when it's game over.

procedure SetupBackground;
begin
//set up window
DisplayDebugImgWindow(800, 600);
t_buffer := BitmapFromString(800, 600, '');
FastDrawClear(t_buffer, clblack);
end;


procedure SetupImages;
begin
//load images
ourBall.img := Loadbitmap(ScriptPath + 'ball.bmp');
ourPaddle[0].img := LoadBitmap(ScriptPath + 'paddle.bmp');
ourPaddle[1].img := LoadBitmap(ScriptPath + 'paddle.bmp');

//set transparencies
SetTransparentColor(ourBall.img, clblack);
SetTransparentColor(ourPaddle[0].img, clblack);
SetTransparentColor(ourPaddle[1].img, clblack);
end;

Those two just set up the background and all the images (the ball and two paddles).

procedure SetupVars;
begin
//setup starter variables
ourBall.x1 := 400;
ourBall.y1 := 300;
ourPaddle[0].x1 := 2;
ourPaddle[0].y1 := 290;
ourPaddle[1].x1 := 794;
ourPaddle[1].y1 := 290;

ourBall.speedX := random(2) + 1;
ourBall.speedY := random(2) + 1;

ourBall.dirD := true;
ourBall.dirV := true;

gOver := false;
end;

This procedure simply defines the starting positions of the ball and the paddle. It also defines the speed (amount of pixels to move per frame) for the ball as well as the direction the ball is heading in. And you probably guessed right that gOver stands for Game Over. I use this later to restart the game.

//main loop
begin
SetupBackground;
SetupImages;

Just calls the procedures to set up background/images.

  startOver:
SetupVars;
repeat
Wait(1);
until(IsKeyDown(Chr(32)));

I define the position of the label I created earlier (this is where it will start when the ball hits the left/right wall). I call the procedure I created earlier to set up all the global variables. Finally, I have it wait until space is pressed.

//main game loop
while(gOver = false) do

Self explanatory (if not game over then do stuff).

    if IsArrowDown(0) then  ourPaddle[1].y1 := ourPaddle[1].y1 - 3;
if IsArrowDown(2) then ourPaddle[1].y1 := ourPaddle[1].y1 + 3;

Monitors up and down arrow key to move the paddle (ourPaddle[1] is the player and ourPaddle[0] is the computer btw).

    //check if top/bottom wall is hit
if (ourBall.y1 <= 1) then
ourBall.dirV := false;
if (ourBall.y1 >= 599) then
ourBall.dirV := true;

//check if paddles are hit or right/left walls are hit
if (ourBall.x1 <= ourPaddle[0].x1 + 6) and (ourPaddle[0].y1 <= ourBall.y1) //[0]
and (ourPaddle[0].y1 + 50 >= ourBall.y1) then //paddle hit?
begin
ourBall.dirD := false;
end else
if (ourBall.x1 <= 1) then //else wall is hit?
begin
gOver := true;
end;

//check if paddles are hit or right/left walls are hit
if (ourBall.x1 + 6 >= ourPaddle[1].x1) and (ourPaddle[1].y1 <= ourBall.y1) //[1]
and (ourPaddle[1].y1 + 50 >= ourBall.y1) then //paddle hit?
begin
ourBall.dirD := false;
end else
if (ourBall.x1 <= 799) then //else wall is hit?
begin
gOver := true;
end;

//move ball according to directions
if ourBall.dirD then //diagonal
begin
ourBall.x1 := ourBall.x1 + ourBall.speedX;
end else
ourBall.x1 := ourBall.x1 - ourBall.speedX;
if ourBall.dirV then //vertical
begin
ourBall.y1 := ourBall.y1 - ourBall.speedY;
end else
ourBall.y1 := ourBall.y1 + ourBall.speedY;

The comments should explain each part.

    //draw everything
SafeDrawBitmap(t_buffer, GetDebugCanvas, 0, 0); //background
FastDrawClear(t_buffer, clblack);
FastDrawSizeTransparent(ourBall.x1, ourBall.y1, ourBall.x1+5, //ball
ourBall.y1+5, ourBall.img, t_buffer);
FastDrawSizeTransparent(ourPaddle[0].x1, ourPaddle[0].y1, ourPaddle[0].x1+4, //left paddle
ourPaddle[0].y1+50, ourPaddle[0].img, t_buffer);
FastDrawSizeTransparent(ourPaddle[1].x1, ourPaddle[1].y1, ourPaddle[1].x1+4, //right paddle
ourPaddle[1].y1+50, ourPaddle[1].img, t_buffer);

This just draws everything over again.

  end;

goto startOver;

This is the part where it goes to the place we defined startOver. This is supposed to happen only after the while loop fails (if gOver = true).

However, instead of starting over only when gOver = true, it starts over every single time. The problem is rather simple but I've looked over this many times and cannot find the problem. If anyone has any ideas, please comment.

PS The two images are in the attachment. Just save the script somewhere and place the two images in the same folder as the script.

WhoCares357

2008-08-18 12:43:13

I figured it out. I had a problem where SCAR checked to see if the ball hit the right/left walls. I messed up the coordinates.

Now I just have to figure out the ai :).