need help with this program

BlitzMax Forums/BlitzMax Programming/need help with this program

Sanjit(Posted 2016) [#1]
hey im making a game called textanoid
code:
'Set application and Graphics
AppTitle="Textanoid2"
Graphics 620,475


'Set the handle to the center of images


AutoMidHandle True

Type TPaddle
Field x,y

End Type


Type TBall
Field x,y 'the coordinates
Field directionx, directiony 'the velocities of the ball
Field xv
Field yv


End Type

Const BLOCKSTRING:String = "XXXXXXXX"
Const paddleimage:String = LoadImage("/Users/sanjitsingh/Downloads/Data/post-13646-0-51208800-1427011572.png")
Global ballimage = LoadImage("/Users/sanjitsingh/Downloads/Data/ball.png")
Const BLOCKROWS = 3
Const BLOCKCOLUMNS = 7
Const BLOCKXGAP = 85
Const BLOCKYGAP = 32
Const BLOCKXORIGIN = 16
Const BLOCKYORIGIN = 8
Global BLOCKHEIGHT = TextHeight(BLOCKSTRING)
Global BLOCKWIDTH = TextWidth(BLOCKSTRING)
Global PADDLEWIDTH = TextWidth(paddleimage)
Global PADDLEHEIGHT = TextHeight(paddleimage)
Global BALLWIDTH = TextWidth(ballimage)
Global BALLHEIGHT = TextHeight(ballimage)
Const X_RANDOM_FACTOR = 2
Const Y_RANDOM_FACTOR = 1
Const STARTX = 300
Const STARTY = 340



'Initialization
'Seed the random Generator
SeedRnd MilliSecs()
'Initialize the score
Global score = 0
'The number of total block hits
Global blockhits = 0
'The level the player is on
Global level = 1

'Create an array of blocks
Global blocks[BLOCKROWS, BLOCKCOLUMNS]

'Create a new ball
Global ball:TBall = New TBall
'Create a new paddle
Global player:TPaddle = New TPaddle



'Initialize the new level
NewLevel()

Function NewLevel()
For rows=0 To BLOCKROWS- 1
For cols=0 To BLOCKCOLUMNS - 1

'Set block to existing(1)
blocks[rows,cols] = 1
Next
Next
ResetLevel()
End Function

Function ResetLevel()
ball.x = 320
ball.y = 150
ball.directiony = 4
ball.directionx = Rand(-5,5)

'Make the ball move in a random direction
ball.xv = Rand(LEVEL_START_XV_MIN, LEVEL_START_XV_MAX)
ball.yv = Rand(LEVEL_START_YV_MIN, LEVEL_START_YV_MAX)

player.x = STARTX
player.y = STARTY
Delay 500
End Function

'Game Loop
While Not KeyDown(KEY_ESCAPE)
Cls




DrawHUD()
TestInput()
Collide()
DrawBlocks()
DrawPaddle()
DrawBall()
CheckBall()



Flip
Wend


Function DrawHUD()
DrawText "Level: " + level, 0, 440 'writes the level
DrawText "Score: " + score, 0, 450 'writes the score
DrawText "Block Hits: " + blockhits, 0, 460 'writes the block hits
End Function



Function TestInput()

'hit Esc
If KeyDown(KEY_ESCAPE)
'quit the game
End

'hits left arrow
ElseIf KeyDown(KEY_LEFT)
'move paddle left
player.x = player.x - 10

'hits right arrow
ElseIf KeyDown(KEY_RIGHT)
'move paddle right
player.x = player.x + 10

EndIf

If KeyHit(KEY_P)
'make screen blank
Cls
DrawText "Press 'P' to Unpause Game",400,300

Flip

'wait for player to unpause
While Not KeyHit(KEY_P)
Wend
EndIf

End Function

Function collide()
'If ball hits human player, reflect it away from him and vary its velocity and direction
If ImagesCollide(ballimage, ball.x,ball.y,0,player1image,60,player1.y,0)
ball.xv = -ball.xv + Rand(-X_RANDOM_FACTOR,X_RANDOM_FACTOR)
ball.yv = ball.yv + Rand(-Y_RANDOM_FACTOR,Y_RANDOM_FACTOR)
EndIf



Function DrawBlocks()


x = BLOCKXORIGIN
y = BLOCKYORIGIN
'This variable creates a new level if there are no blocks
Local moveToNewLevel = 0


'For all the rows
For rows = 0 To BLOCKROWS - 1
'reset rows position
x = BLOCKXORIGIN




For cols = 0 To BLOCKCOLUMNS - 1


'if the block exists, draw it on the screen
If (blocks[rows,cols] = 1) Then
DrawText BLOCKSTRING, x, y
moveToNewLevel = moveToNewLevel + 1

End If

'Move over to the next block
x = x + BLOCKXGAP

Next
'Move to the next column
y = y + BLOCKYGAP

Next
If moveToNewLevel = 0

level = level + 1
NewLevel()
EndIf

End Function


Function DrawPaddle()
'Draw the paddle
DrawText (paddleimage, player.x, player.y)
End Function

Function DrawBall()
'draw ball
DrawImage (ballimage,ball.x, ball.y)
End Function


Function CheckBall()
'move and draw ball
UpdateBall()

'Check and see if ball hit anything
CheckBallWithPaddle()
CheckBallWithBlocks()
CheckBallWithWalls()
End Function









Function UpdateBall()
'Move the ball to the left or right
ball.x = ball.x + ball.directionx

'Move the ball up or down
ball.y = ball.y + ball.directiony



End Function


Function CheckBallWithPaddle()
If ball.x >= player.x And ball.x <= player.x + PADDLEWIDTH And ball.y + BALLHEIGHT >= player.y And ball.y + BALLHEIGHT <= player.y + PADDLEHEIGHT

ball.directiony = -ball.directiony + Rand(-3,3)
EndIf
End Function



Function CheckBallWithBlocks()
'y is the first row
y = BLOCKYORIGIN

For rows = 0 To BLOCKROWS - 1

'Reset x to first block of column
x = BLOCKXORIGIN


'For every column of blocks
For cols = 0 To BLOCKCOLUMNS - 1'

'If it exists
If blocks[rows,cols]

'If the ball hit the block, delete the block
If ball.x >= x And ball.x <= x + BLOCKWIDTH And ball.y >= y And ball.y <= y + BLOCKHEIGHT

blocks[rows,cols] = 0 'Delete block

ball.directiony = -ball.directiony + Rand(-2,2) ' Reverse its direction and add randomizer

score = score + 75

blockhits = blockhits + 1

'It can't hit mre than one block, so leave function
Return

EndIf
EndIf

'move to next column
x = x + BLOCKXGAP
Next

'move to next row
y = y + BLOCKYGAP
Next

End Function


Function CheckBallWithWalls()
'if ball hits the left wall, reverse its direction and add randomizer
If ball.x <= 0
ball.directionx = -ball.directionx + Rand(-2,2)

'if ball hits top wall, reverse its direction and add randomizer
ElseIf ball.y <= 0
ball.directiony = -ball.directiony + Rand(-2,2)

'if it hits right wall, reverse its direction and add randomizer
ElseIf ball.x >= 640 - BALLWIDTH
ball.directionx = -ball.directionx + Rand(-2,2)

'If ball hits lower wall, dock points for missing ball
ElseIf ball.y >= 480
score = score - 200

'reset the level
ResetLevel()
EndIf
End Function



the main point of this code is for the game to hit the brick but when I use my paddle image it will just go through the paddle. basically when the ball is falling the paddle is supposed to hit the ball back. but when it falls on the paddle it doesnt fall on it it only goes through the paddle and paddle doesnt reflect the ball back to its target. can somebody please help. I just need it to work with my image paddle. thank you so much.


Midimaster(Posted 2016) [#2]
This can have some reasons:

1. The coordinates are not correct. As you switched on AUTOMIDIHANDLE the object are not from PLAYER.X to PLAYER.X+PADLLEWIDTH but from PLAYER.X - PADLLEWIDTH/2 to PLAYER.X+PADLLEWIDTH/2



2.The ball is too fast. If the ball speed is higher than the paddles height, it can go trough within one loop. Example:

Take this situation:
PADDLEHEIGHT=3, PLAYER.Y=100, BALL.DIRECTIONY=4 BALL.Y=101
In this moment the ball is above the paddle. But in the next round it will be at 104. And now it is below, but was never inside the paddle.

I say it again: Please use the forum codes to structure your code for us.

Your code has some bugs:

1.Your function Function collide() has no End function

2.It is not possible to convert images to strings. And it is not possible to load something into a CONSTANT:
Const paddleimage:String = LoadImage("/Users/sanjitsingh/Downloads/Data/post-13646-0-51208800-1427011572.png")

better this way:
Global PaddleImage:TImage = LoadImage("/Users/sanjitsingh/Downloads/Data/post-13646-0-51208800-1427011572.png")
.....
Global PADDLEWIDTH = ImageWidth(Paddleimage)
Global PADDLEHEIGHT = ImageHeight(Paddleimage)
....
DrawImage (PaddleImage, player.x, player.y)



3. Your type BALL has no field X and no Y. And you have no PLAYER1
			If ImagesCollide(ballimage, ball.x,ball.y,0,player1image,60,player1.y,0)

I think you mean:
			If ImagesCollide(ballimage, ball.xv,ball.yv,0,player1image,60,player.y,0)


Here is a code without syntax bugs:


Explanations: As I have not your images, I need to replace this part with a "special code" to run the game. You can remove this lines and re-activate your line:
'Global PaddleImage:TImage = LoadImage("/Users/sanjitsingh/Downloads/Data/post-13646-0-51208800-1427011572.png")
'Global BallImage = LoadImage("/Users/sanjitsingh/Downloads/Data/ball.png")

Global PaddleImage:TImage = CreateImage(50,8)
	DrawRect 1,1,49,7
	GrabImage PaddleImage,0,0
	Cls

Global BallImage:TImage = CreateImage(10,10)
	DrawOval 1,1,9,9
	GrabImage BallImage,0,0
	Cls


General advices
There are two different sort of bugs: syntax bugs an logic bugs. To prevent syntax bugs, it is better (for a novice) to start the code after each line, instead of coding the whole game, then try to start with dozends of bugs.
In this step-by-step starts the program will not run as expected, but it will run.

Use the TABs to structure your code. So you will find missing END FUNCTION, etc...

I am interested in supporting you and teaching you, but you need to follow some of the advices. Also the others here will join your threads and will help, when you start to write more carefully.

Wish you all the best, and that you become a good coder and a long time member of our forum.

What has becomes with your problem from two weeks ago?


Sanjit(Posted 2016) [#3]
MidMaster thank you so much for your help and kind words. My coding has improved. I am actually using a blitzbasic textbook for the games but as I also use my resources to design a game I also like to make my own versions of my game. I really apreeciate your help. your advice and code makes sense and I still have a lot to learn before I can become a professional coder. But I owe my gratitude to you. I actually know how to create my own player for this game with the const variable. Example: Const BLOCKSTRING:String = "XXXXXXXX"
Const PADDLESTRING:String = "--------"
Const BALLSTRING:String = "0".
but I thought to myself why not explore and use different ideas. I remember you helped me with my game called space invaders and I followed more of your tips. I really want to you and hope if I have anymore questions I can come to you for help anytime. Thanks again. From you I am learning more things that i was not ware of. Thanks again. I owe you one.


dw817(Posted 2016) [#4]
Hi Sanjit:

As is your code does not run, I get back a:

MAX IDE - Compile Error - Expecting expression but encountred end-of-file.

Also, your code is a little hard to read (at least for me anyways). You might consider the following. the command STRICT placed at the top of your program will ensure that all variables are defined. This is actually a good thing and can cut down on errors later.

You might INDENT your code thus:
Function NewLevel()
  For rows=0 To BLOCKROWS- 1
    For cols=0 To BLOCKCOLUMNS - 1
      blocks[rows,cols] = 1 'Set block to existing(1)
    Next
  Next
  ResetLevel()
End Function


Where you put the REMARK just to the right of the code, you won't be confused about which remarks go with which commands.

Additionally, BlitzMAX is Caps Blind so you can type out everything in lower or uppercase and it won't make a difference. BlitzMAX's IDE is smart and it will UpperCase commands as needed.


Midimaster(Posted 2016) [#5]
....but I thought to myself why not explore and use different ideas.

That' a good idea, but in this case you should try to "build &run" your game after each new line of code to prevent "Syntax Errors". Press F5 to check the syntax often.

When you add a new structure, you should always add it's END command line in the moment of writing its first line. See the example of how the code is growing over some steps:
1.
SuperStrict
Graphics 800,600
Global A%, B%, C%
Repeat
Until KeyHit(KEY_ESCAPE)

2.
SuperStrict
Graphics 800,600
Global A%, B%, C%
Repeat
    If A=4
    Endif
Until KeyHit(KEY_ESCAPE)

3.
SuperStrict
Graphics 800,600
Global A%=4, B%, C%
Repeat
    If A=4
        For B=0 to 10
        Next
        Print "working"
    Endif
Until KeyHit(KEY_ESCAPE)

4.
SuperStrict
Graphics 800,600
Global A%, B%, C%
Repeat
    If A=4
        For B=0 to 10
            C=C+C
        Next
        Print "working" + C
    Endif
Until KeyHit(KEY_ESCAPE)

5.
SuperStrict
Graphics 800,600
Global A%, B%, C%
Repeat
    If A=4
        For B=0 to 10
            C=C+C
        Next
'        Print C
    Endif
    If KeyDown(KEY_1)
        Print "KEY 1"
    Else
    Endif
Until KeyHit(KEY_ESCAPE)

Function Bla()
End Function

6.
SuperStrict
Graphics 800,600
Global A%, B%, C%
Repeat
    If A=4
        For B=0 to 10
            C=C+C
        Next
        Print C
    Endif
    If KeyDown(KEY_1)
        'Print "KEY 1"
        Bla C
        A=0
    Else If KeyDown(KEY_2)
        Print "KEY 2"
        C=0
        A=4
    Else
    Endif
Until KeyHit(KEY_ESCAPE)

Function Bla(Value%)
    DrawText Value,100,100
End Function



You can build a game where TEXTs and IMAGEs are combined... no problem. But the syntax does not allow combining text command and image commands in one line, like you did here:
Const paddleimage:String = LoadImage("/Users/sanjitsingh/Downloads/Data/post-13646-0-51208800-1427011572.png")

Also CONST needs its value already in the code. Not loaded later or coming from a variable:
'allowed:
CONST A%=3
CONST B$="ABC"
CONST C%=A
' not allowed:
Global X%=4
CONST A%=X
CONST B$=LoadText("....")

CONST C%=A



Another Advice:

You only can understand what's going wrong in your game, when you "Slow down" the speed. Try This in your main loop:
Global Wait%=10
Repeat
' your code...
.....
     If KeyDown(KEY_S) ' s=slower
          Wait=50
     Else
          Wait=10
     EndIf
     Delay Wait
     Flip
Until....



coffeedotbean(Posted 2016) [#6]
If you want some advice on the ball to paddle collision then the simplest way is to create an invisible hitbox around the paddle that extends below the paddle to compensate for the ball moving faster per frame than the height of the paddle, when the ball is inside this hitbox you can then reposition the ball so it appears above the padding on the Y axis. If you update before render then the ball will never appear to go through the paddle.

You might want to look up AABB Axis Align Bounding Box to put a box around the ball and paddle https://www.youtube.com/watch?v=ghqD3e37R7E and use that to create hitboxes you can later check are colliding or not.

a = y position of paddle
b = the invisible hitbox that follows the paddle on the x axis
c = the y position of the ball



example;
if BallInsidePaddleHitbox()
   ball.y = paddle.y-ball.height ' position ball above paddle
   ' then reverse it's velocity
endif

Above assumes you've create a function called "BallInsidePaddleHitbox()" (this could be checking ig you paddle and ball AABB's are colliding) that returns true if the ball is inside the paddle.

You'll need to later add some additional checks to ensure the ball (that is now colliding) on the last frame was above the paddle else you'll have some odd issues with side collisions but don't be concerned with that just yet.


coffeedotbean(Posted 2016) [#7]
If you want some advice on the ball to paddle collision then the simplest way is to create an invisible hitbox around the paddle that extends below the paddle to compensate for the ball moving faster per frame than the height of the paddle, when the ball is inside this hitbox you can then reposition the ball so it appears above the padding on the Y axis. If you update before render then the ball will never appear to go through the paddle.

You might want to look up AABB Axis Align Bounding Box to put a box around the ball and paddle https://www.youtube.com/watch?v=ghqD3e37R7E and use that to create hitboxes you can later check are colliding or not.

a = y position of paddle
b = the invisible hitbox that follows the paddle on the x axis
c = the y position of the ball



example;
if BallInsidePaddleHitbox()
   ball.y = paddle.y-ball.height ' position ball above paddle
   ' then reverse it's velocity
endif

Above assumes you've create a function called "BallInsidePaddleHitbox()" (this could be checking if your paddle and ball AABB's are colliding) that returns true if the ball is inside the paddle.

You'll need to later add some additional checks to ensure the ball (that is now colliding) on the last frame was above the paddle else you'll have some odd issues with side collisions but don't be concerned with that just yet.