You have long experience in programming, and it shows. Code optimizes checking brick hits from only one wall, however I feel that using attribute containing all bricks would simplify much the program. You could even calculate crossing point mathematically, direction is changed only at walls and pad, which can be thought as conditional wall. Then one scan of bricks would be enough. Could it not happen that ball hits border of 4 bricks?
pyTony
pyMod
5,359 posts since Apr 2010
Reputation Points: 782
Solved Threads: 852
I feel that using attribute containing all bricks would simplify much the program
I see what you mean. I'll code this up and see where it goes.Could it not happen that ball hits border of 4 bricks?
Because there is a space between the bricks it is impossible to hit more than one at a time. As for the corners, it is possible for the ball to hit exactly at the junction of two or more walls. That is why I test each wall separately instead of using if-elif-elif etc. Or am I missing your point?
Thanks for the feedback and suggestions. I do have the experience programming but I am still relatively new to the idioms of Python.
Reverend Jim
Posting Shark
1,169 posts since Aug 2010
Reputation Points: 253
Solved Threads: 159
Comments on coding style. Those flag variables are less than ideal considering the normal Python way and your naming does not confirm Python PEP8 convention. Also you use little too much white space, and you are not using multiline string for multiline comment, but instead box comment which is not so much encouraged in the style guide. Nowadays computers are so fast that does not really so much difference how you check the tiles. For me the program was not so easy to check in action as I do not own 3D glasses. My graphics card is also old and I had to switch to windowed mode to see the message texts of the program. It would be nice to have only one collision detect and return bricks hitted or empty list instead of current tuple (I have done quite similar style as more Pythonic style, but it somehow looks not ideal in this situation). pythonic pseudocode for main action could be:
for brick in bricks_hit(ball_position):
reflect(movement_vector)
remove(brick)
pyTony
pyMod
5,359 posts since Apr 2010
Reputation Points: 782
Solved Threads: 852
Excellent suggestions and your sample code is much clearer. As I said, I am still learning the Python idioms. Ultimately I code to make it easy for me to read but I am flexible so I will try to accommodate the accepted norms. Thanks for the input.
Reverend Jim
Posting Shark
1,169 posts since Aug 2010
Reputation Points: 253
Solved Threads: 159
for brick in bricks_hit(ball_position):
reflect(movement_vector, reflect_direction[brick])
remove(brick)
Would maybe need dict of reflect directions supplied to reflection (like (-1, 0, 0) for doing movement_vector.x = -movement_vector.x) If we would have class holding the variables we maybe would not have them as parameters, but access through instance variables.
About separation between bricks, my logic says that one of these is true:ball can hit both bricks
ball can go through between bricks
pyTony
pyMod
5,359 posts since Apr 2010
Reputation Points: 782
Solved Threads: 852
I had a thought or two on that. I thought I might add an invisible brick behind each wall. These bricks would be the same size as the walls. They would also start as enabled=False. The Remove function would only remove bricks that are enabled. That way the ball would reflect even if it hits a space between two smaller bricks. By the same token, I should be able to add the paddle as a brick and have the reflection done by the same logic. That would only leave the case where the ball misses the paddle and falls through the floor. I could add the reflection vector as a property to each brick.
This sort of stuff reminds me why I got into programming all those years (almost 40) ago. It's fun and there is always something new to learn.
Reverend Jim
Posting Shark
1,169 posts since Aug 2010
Reputation Points: 253
Solved Threads: 159
I had a thought or two on that. I thought I might add an invisible brick behind each wall. These bricks would be the same size as the walls. They would also start as enabled=False. The Remove function would only remove bricks that are enabled. That way the ball would reflect even if it hits a space between two smaller bricks. By the same token, I should be able to add the paddle as a brick and have the reflection done by the same logic. That would only leave the case where the ball misses the paddle and falls through the floor. I could add the reflection vector as a property to each brick.
This sort of stuff reminds me why I got into programming all those years (almost 40) ago. It's fun and there is always something new to learn.
I think it would be nice to have down counter of hits so if the brick is indestructible, it has count say trillion trillions, otherwise it would have one or few. You could have one "lose life tile" under pad level which has counter 1 and is reinitialized to one after miss and one life is taken out. It would be nice to be hit last moment by the end of the paddle, however, and have radical change of direction.
How are you dealing with issue of movement per tick not matching the distance from the surface before hit, or maybe the effect of that is negligible (with high speed you could however tunnel through the brick, wouldn't you)
You probably have very limited amount of hit angles now as you have not different change of direction from the place of pad hit. You could make surface normal depend on the distance from the paddle centre towards the side of the hit. It is add surface parallel vector length relative to distance from middle of the paddle.
For reflection from obtuse angles, the reflection would not be same direction from the end of the brick as top, basically you would like to get surface normal from any surface of the block hit.
Then later you could create bricks at different levels and having different number of hits required (durability), blocking indestructible tiles etc.
pyTony
pyMod
5,359 posts since Apr 2010
Reputation Points: 782
Solved Threads: 852
pyTony
pyMod
5,359 posts since Apr 2010
Reputation Points: 782
Solved Threads: 852
I haven't had a look at panda3d yet but I definitely will. Thanks.
I've been looking at ways to generalize the code so that I don't require separate functions for each wall condition. It seems that the more general I make the code the more unreadable and complex it is. Given a choice between readability and, complexity (or cleverness), I generally go for readability. For example, the code to check if a "left wall" brick has been hit is trivial and clear. The code to check if a generic brick has been hit is not. The first step is to compare the perpendicular distance. If within a given tolerance I must then check if the remaining two coordinates of the ball fall with the plane of the brick. This involves a level of indirection because I must now index the position vectors with indices that are determined by the orientation of the brick. For example, a "left" brick has the plane defined by y and z, a "top" brick by x and z and a "back" brick by x and y.
Reverend Jim
Posting Shark
1,169 posts since Aug 2010
Reputation Points: 253
Solved Threads: 159
Sometimes it is OK not to be very general and repeat yourself even it is not so nice. If you would be planning to go to more realistic version generality can pay off. Reflection planes are planes in the coordinates, and there could be way to chose that hitting plane based on current movement direction. In one 2d breakout example the bounce was implemented object oriented way and the way was based on angle of movement, up being the 0 degree direction.
You noticed the second paragraph in PEP8, didn't you ;) Good rules, aren't they?
pyTony
pyMod
5,359 posts since Apr 2010
Reputation Points: 782
Solved Threads: 852
pyTony
pyMod
5,359 posts since Apr 2010
Reputation Points: 782
Solved Threads: 852
Aaarrrggghhh. So many choices, so little bandwidth. I see the panda3d download is about 84 meg. I'm on wireless at the cottage from May through mid September (retirement is AWESOME) where I try to stay under 100 meg a day up/down so I'll have to look at this (and the others) when I get home. With so many choices it will be hard to make an informed choice. But it's still nice to know what the choices are. Thanks.
Reverend Jim
Posting Shark
1,169 posts since Aug 2010
Reputation Points: 253
Solved Threads: 159