Computer Science Canada

Falling Balls

Author:  Mr. T [ Sat Aug 12, 2006 10:33 am ]
Post subject:  Falling Balls

I want the balls in this programing to fall. I believe that the error is occuring in the whatdotcolour part of the code. Can someone please tell me what I'm doing incorrectly?

code:
View.Set ("offscreenonly")

var itemI, itemQ : array 1 .. 15 of int
procedure itemInitialization
    for i : 1 .. 15
        for q : 1 .. 30

            for a : 1 .. 15
                itemI (a) := Rand.Int (1, 15)
                itemQ (a) := Rand.Int (1, 30)
            end for

        end for
    end for
end itemInitialization

var fallBool : boolean := false
proc drawItem (fall : int)
    for a : 1 .. 15
        drawfilloval (((itemI (a) - 1) * 20) + 10, (((itemQ (a) - 1) * 10) + 5) - fall, 2, 2, black)
%Problem lies in the if statement below
        if whatdotcolour (((itemI (a) - 1) * 20) + 10, (((itemQ (a) - 1) * 10) + 5) - fall) = white then
            fallBool := true
        end if
    end for
end drawItem

itemInitialization

var itemFall : int := 0
loop

    delay (100)
    View.Update
    cls

    drawItem (itemFall)

    if fallBool = true then
        itemFall += 10
    end if

end loop

Author:  Cervantes [ Sat Aug 12, 2006 10:39 am ]
Post subject: 

your itemInitialization procedure is very inefficient. The first two for loops do nothing. Eliminate them.

The reason the balls don't fall has nothing to do with the whatdotcolour lines you pointed out. Rather, they don't fall because you never changed any variables. You need to decriment itemI (a) or itemQ (a). All you've done is draw them a few pixels away from their starting spots.

Use descriptive variable names. What in the world is I and Q? Somehow I and Q don't give me the idea of x and y coordinates.

Use records, instead of parallel arrays.

Author:  Mr. T [ Sat Aug 12, 2006 10:43 am ]
Post subject:  Alex's Opinion

I do have an increment. Check the main loop. fallItem +=10 when fallBool = true. fallBool=true under the condition set by the whatdotcolour if statement. Furthermore, I know that the whatdotcolour if statement is causing the problem because if you take it out, and only have fallBool=true, then the balls DO fall.

Author:  Cervantes [ Sat Aug 12, 2006 2:42 pm ]
Post subject: 

Ah, so you do. Most of my reply was in response to your initial post (which you deleted), which didn't have such an incriment (or even this whatdotcolour stuff!) Arr!

I'll point out that you only have one fallBool variable, so either they all fall, or none do. Also, since it is never ever set to false except at initialization, if one ball statisfies the whatdotcolour condition to fall, then they all fall.

So this must mean that none of the balls satisfy the fall condition. This might have something to do with the fact that you View.Update, then cls, then do your whatdotcolouring. Try changing the order of these things. I'd recommend moving the View.Update and cls stuff to the end of the loop (it makes more sense, doesn't it?). So it becomes: call procedure; View.Update; delay; cls.

I don't have Turing on this computer, so you'll have to try some different things and report your successes/failures back here.

Author:  Mr. T [ Sat Aug 12, 2006 3:10 pm ]
Post subject:  Alex's Opinion

Sticking the cls and View.Update at the end worked! So that each ball falls on its own, I'll make fallBool into an array. Thanks for the help.

Author:  Mr. T [ Sat Aug 12, 2006 3:28 pm ]
Post subject:  Alex's Opinion

Ok, each ball (and boolean) is an element in an array. Nonetheless, the balls still fall at the same time. Any ideas as to why?
code:
View.Set ("offscreenonly")

var itemI, itemQ : array 1 .. 15 of int
procedure itemInitialization
    for a : 1 .. 15
        itemI (a) := Rand.Int (1, 15)
        itemQ (a) := Rand.Int (1, 30)
    end for
end itemInitialization

var fallBool : array 1 .. 15 of boolean
proc drawItem (fall : array 1 .. 15 of int)
    for a : 1 .. 15
        drawfilloval (((itemI (a) - 1) * 20) + 10, (((itemQ (a) - 1) * 10) + 5) - fall (a), 2, 2, black)
        %Problem lies in the if statement below
        if whatdotcolour (itemI (a), itemQ (a)) = white then
            fallBool (a) := true
        end if
    end for
end drawItem

itemInitialization

var itemFall : array 1 .. 15 of int
for i : 1 .. 15
    itemFall (i) := 0
end for

loop
    drawfillbox (33, 424, 282, 55, blue)
    drawItem (itemFall)
    for a : 1 .. 15
        if fallBool (a) = true then
            itemFall (a) += 10
        end if
    end for

    delay (100)
    View.Update
    cls
end loop

Author:  [Gandalf] [ Sat Aug 12, 2006 5:46 pm ]
Post subject: 

Here's some incentive to use flexible arrays. If you do that, and start it off with no balls in the array, you can then add a timer which, when elapsed, spawns a new ball. This gives you control over the spawn rate and over how many balls you will allow in total.

Author:  Mr. T [ Sat Aug 12, 2006 5:47 pm ]
Post subject:  Alex's Opinion

I'm not trying to accomplish that. Rather I want a ball to fall ONLY when it is touching white.

Author:  Cervantes [ Sat Aug 12, 2006 7:42 pm ]
Post subject:  Opinion of Cervantes:

Of course they all fall at the same rate: 10 pixels per loop. That's a hardcoded value. And as soon as the whatdotcolour condition for a particular ball to fall is met, it will fall forever. There's no way to turn falling off.

Cervantes wrote:

Use descriptive variable names. What in the world is I and Q? Somehow I and Q don't give me the idea of x and y coordinates.

Use records, instead of parallel arrays.

This still applies.

Author:  Mr. T [ Sat Aug 12, 2006 7:49 pm ]
Post subject:  Alex's Opinion

No, you're not understanding. The whatdotcolour if statement places a condition on the balls. The balls that are within the blue square SHOULD NOT fall, whereas the rest of the balls SHOULD. I don't know what's wrong with the whatdotcolour if statement?!

Author:  [Gandalf] [ Sat Aug 12, 2006 8:15 pm ]
Post subject: 

Mr. T, that this is a situation where you should be using records instead of parallel arrays (itemI, itemQ). That would make your code much more readable (added on to more descriptive naming), which in turn would make it easier for you to code and us to help you.

As for the reason why your whatdotcolour isn't working, I looked at it for a bit and couldn't figure it out. Possibly as a result of your slightly cryptic, and more than slightly disorganized code. My guess is that it's something to do with the proper colour not being detected because of the order in which things are drawn.

Really, general coding practices are more important than random problems with your code not working. That is where you must improve.

Author:  TheOneTrueGod [ Sat Aug 12, 2006 9:28 pm ]
Post subject: 

Nowhere in your code is fallBool set to false... Before you continue with this project, STOP, and do cervantes'/gandalf's suggestions... It'll save you a tonne of work later on, and if you keep using names and coding practices like this, people may just refuse to help you because your code is unreadable...

Author:  TokenHerbz [ Sat Aug 12, 2006 11:28 pm ]
Post subject: 

Here bud, have a look at this....

I hope i didn't make it to confusing lol, i tend to do that alot Sad

code:

setscreen ("Graphics:maxx;maxx, title: Test")
View.Set ("offscreenonly")

%%id try using a class for this, but its to show Mr.T about records

var mx, my, mb : int %%my mouse vars i want to use.
var box_size : int := 20 %going to draw a box (you center it yourself if you want)

type balls :
    record
        x, y : int
        size : int
        vy : int %%how fast it will fall
        check : boolean %%%%%oooooooooo!!!!!
        distance : int      %%im going to use this to see how far from top it is
        %%can have more, like color, etc:
    end record

%%on your code you have a set amount of balls at one givin time?
%%i will mimic this, but id use a flexable array with a timer
%% too add balls the longer you play :)
var ball : array 1 .. 15 of balls %%makes an array with the variables in the record

%%now we can start to initialize everything like you have done.
proc spawn_balls
    for i : 1 .. upper (ball)
        ball (i).size := Rand.Int (1, 10)
        ball (i).distance := 0  %%hasn't moved any pixles
        ball (i).x := Rand.Int (10, maxx - 10)
        ball (i).y := maxy %%set at the top
        ball (i).vy := Rand.Int (-5, -1)
    end for
end spawn_balls

fcn allowable_boundries (num : int) : boolean
    Mouse.Where (mx, my, mb) %too see where my mouse is
    %%mb not needed unless you want to add smothing for it

    %%number, for the specific ball
    if ball (num).x >= mx and ball (num).x <= mx + box_size and
            ball (num).y >= my and ball (num).y <= my + box_size then
        result false        %%it collided
    else
        result true %can continue to fall
    end if
   
    %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
    %%%%%%%%%HOW EVER!!! YOU WANTED WHATDOTCOLOR
    %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
   
    %i dont feel like making a good colition system for your tests, but this should work.
   
 %  if whatdotcolor(ball(num).x,ball(num).y) = blue or whatdotcolor(ball(num).x + ball(num).size, ball(num).y + ball(num).size) = blue then
   %    result false       
  % else
   %    result true
  % end if
end allowable_boundries

proc move_balls
    for i : 1 .. upper (ball)
        ball (i).check := allowable_boundries (i)
        if ball (i).check = true then   %%not collided
            ball (i).y += ball (i).vy %%move it down
        end if
    end for
end move_balls

proc draw_items
    %%draw your blue box first to see the balls in it
    Draw.FillBox (mx, my, mx + box_size, my + box_size, blue)

    for i : 1 .. upper (ball)
        Draw.FillOval (ball (i).x, ball (i).y, ball (i).size, ball (i).size, 7)
    end for
end draw_items

spawn_balls
loop
    move_balls

    cls
    draw_items
    View.Update
    delay (20)
end loop

Author:  Mr. T [ Sun Aug 13, 2006 1:19 am ]
Post subject: 

TheOneTrueGod wrote:
Nowhere in your code is fallBool set to false... Before you continue with this project, STOP, and do cervantes'/gandalf's suggestions... It'll save you a tonne of work later on, and if you keep using names and coding practices like this, people may just refuse to help you because your code is unreadable...

This code is just a small segment of a larger game, so confusion on the part of other people is understandable.

Thanks for the help TokenHerbz

Author:  Mr. T [ Sun Aug 13, 2006 2:11 pm ]
Post subject:  Alex's Opinion

Ok, I was successfully able to implement your code into my game. Now, I need help with something new. My game runs on a 2d array grid system. Before the game even begins, certain cells are already coloured in, while others remain white. I want the little (falling) balls to be ONLY drawn in the coloured cells. How would go about determining which cells are coloured. And how would I use this information and apply it to the ball drawing section of code?

Author:  Clayton [ Sun Aug 13, 2006 3:02 pm ]
Post subject: 

use the x and y coordinates of your cells, use View.WhatDotColor (x,y) to find out what color that cell is, draw the ball there

Author:  [Gandalf] [ Sun Aug 13, 2006 4:04 pm ]
Post subject: 

Mr. T wrote:
This code is just a small segment of a larger game, so confusion on the part of other people is understandable.

Fine. That doesn't make what any of us has said any less relevant. Actually, since this is from a larger program, having a well coded program is even more important.

If you would take a few hints from TokenHerbz's program, that would be a good first step, though his program also seems to have problems. In the first two lines alone there are 6 changes to be made. Rolling Eyes

As it stands, Mr. T, your problem has many, many things to be fixed before moving on with other "features". I'll leave it at that and hope you take our previous advice.

Author:  Mr. T [ Sun Aug 13, 2006 4:17 pm ]
Post subject:  Alex's Opinion

Well besides a few sketchy variable names, I do feel my program as a whole is well-coded / organized. I can send it to you, and you can take a look for yourself if you want.

Author:  Cervantes [ Sun Aug 13, 2006 4:50 pm ]
Post subject:  Re: Alex's Opinion

Mr. T wrote:
Well besides a few sketchy variable names, I do feel my program as a whole is well-coded / organized.

It is not.

Allow me to list the things wrong with your code:


  1. itemI - variable name makes no sense; uncommented
  2. itemQ - variable name makes no sense; uncommented
  3. itemI and itemQ - parallel arrays. Should use records
  4. fallBool - include into record
  5. itemFall - include into record; depending on what this program is supposed to do, it probably makes more sense to scrap this variable altogether and modify the y values directly
  6. itemInitialization - procedure is only called once and takes no parameters; it does not simplify or clarify the code at all. Either scrap it, or use the following point
  7. itemInitialization - should be a function that initializes a single ball, not a procedure that initializes the values of global variables
  8. drawItem - procedure does much more than just drawing; it modifies state (of global variables)
  9. drawItem - accepts a parameter for one aspect of the balls, but not for the others; inconsistancy; breaks the Principle of Least Surprise
  10. drawItem - hardcoded values everywhere with no commenting; expressions could be algebraicly simplified
  11. 15 - hardcoded value appears all over the place
  12. main loop - no structure; processing and output (drawing) are jumbled together
  13. (fallBool (a) = true) conditional - redundant comparison


Perhaps if you take a step back and look at this code and pretend it was written by someone else, you'll be able to acknowledge these flaws.

Author:  Mr. T [ Sun Aug 13, 2006 5:03 pm ]
Post subject:  Re: Alex's Opinion

Cervantes wrote:
Perhaps if you take a step back and look at this code and pretend it was written by someone else, you'll be able to acknowledge these flaws.

I can acknowledge them in hindsight, but I don't yet have a strong enough grasp of the language to identify said flaws on my own. Oh well, live and learn. Smile

Author:  [Gandalf] [ Sun Aug 13, 2006 6:51 pm ]
Post subject: 

...then there's things like:
code:
drawfilloval (((itemI (a) - 1) * 20) + 10, (((itemQ (a) - 1) * 10) + 5) - fall (a), 2, 2, black)

Which I would say are plain cryptic. What is the - 1 doing there? * 20? + 10? * 10? + 5? - fall (a)? Why are all these values there? What do they represent? Why are you doing all these calculations in the call to drawfilloval? Why are the (assumably) x and y co-ordinates stored in two arrays labelled as "...I" and "...Q"?

Learning to create code that does not bring up these questions will make it a lot easier for us to help you, and for you to help yourself when something goes wrong.

Author:  Mr. T [ Sun Aug 13, 2006 10:58 pm ]
Post subject:  Alex's OPinion

All that addition / subtraction / multiplication is used to centre the balls on my grid (which is 15 by 30). Silly

Author:  [Gandalf] [ Mon Aug 14, 2006 2:39 am ]
Post subject: 

code:
Draw.FillOval (item (a).x * GRID_SIZE + centerOffset, item (a).y * GRID_SIZE + centerOffset, 2, 2, black)

Would be one of the many alternatives that are much better.

Basically #10 on Cervantes' list, which I seem to have missed the first time around. Surprised


: