User avatar
D.E.L.B.
Posts: 92
Joined: Sat Jun 09, 2012 7:16 pm
Location: Wales, UK
Contact: Website

Could someone run through this code with me?

Fri Jul 27, 2012 5:47 am

In the magazine: "The Mag Pi", there is a code in which there is a "Bat and Ball" game and of which some of the codes aren't explained.

I get the parts of where they are commented, but what I don't get it the ones that are in [], ad well as things like (size [0]/2])... etcetera.

Here is the code:

Code: Select all

# BAT AND BALL
# By antiloquax - 28th April 2012
import pygame
from pygame.locals import *
pygame.init()
# set the width and height of the screen
size = [400, 400]
screen = pygame.display.set_mode(size)
# give the window a title
pygame.display.set_caption("Bat and Ball")
# This makes the normal mouse pointer invisible in graphics window
pygame.mouse.set_visible(0)
# create surfaces for the bat and ball
bat_surf = pygame.Surface((64,12))
bat_surf.fill((0,255,0))
batrect = bat_surf.get_rect()
ball_surf = pygame.Surface((30,30))
ballrect = ball_surf.get_rect()
ball = pygame.draw.circle(ball_surf, (0,0,255),[15, 15], 15)
# set speed of ball
speed = [3, 3]
# puts the bat center of screen, near the bottom
batrect.center = ((size[0]/2), (size[1] - 50))
# make a text object
font = pygame.font.Font(None, 36)
text = font.render("Game Over", True, (255,0,0))
textRect = text.get_rect()
textRect.centerx = (size[0]/2)
textRect.centery = (size[1]/2)
# loop until the user clicks the close button
done=0
# create a timer to control how often the screen updates
clock = pygame.time.Clock()
# main game loop
while done == 0:
    screen.fill((0,0,0))
    # event handling
    for event in pygame.event.get(): # if we click something ...
        if event.type == pygame.QUIT: # if we click close ...
            done=1 # this will cause the loop to finish.   
# moves bat in accordance with the mouse position
    position = pygame.mouse.get_pos()
    batrect.centerx = position[0]
    # move the ball
    ballrect.left += speed[0]
    ballrect.top += speed[1]
    # collision detection
    if ballrect.colliderect(batrect):
            speed[1] = -speed[1]
    # check if the ball is going off screen
    if ballrect.left < 0 or ballrect.right > size[0]:
        speed[0] = -speed[0]
    if ballrect.top < 0:
        speed[1] = -speed[1]
    # print "Game Over" if the ball leaves screen
    if ballrect.top > size[1]:
        screen.blit(text, textRect)
        pygame.display.flip()
        pygame.time.wait(2000) # 2000 milliseconds pause
        ballrect.top=0; ballrect.left=(size[0]/2) # reset the ball position
    screen.blit(ball_surf, ballrect)
    screen.blit(bat_surf, batrect)
    # set the loop to 60 cycles per second
    clock.tick(60)
    #  update the display
    pygame.display.flip()
If anyone is able to run through the code and explain what those [] are for, and what they are used for, it'd be great!

Thank you.

timhoffman
Posts: 85
Joined: Sat Nov 05, 2011 11:31 pm

Re: Could someone run through this code with me?

Fri Jul 27, 2012 5:57 am

In python [] denotes a list. So `a = []` is an empty list.

Code: Select all

>>> a = [1,2,3]
>>> x = a[1]
>>> print x
2
>>> 
Square brackets after a name denote indexing/slicing from the list. See http://docs.python.org/tutorial/datastructures.html for a good discussion. If you see `a['a string']` then you a seeing a dictionary access by a key.

You will also see `a=(1,2,3)` which is a tuple. (tuples are immutable - ie can't be changed). You can see a discussion of tuples on the same page I linked too.

Hope this helps get you started.

T

antiloquax
Posts: 406
Joined: Sun Nov 20, 2011 11:37 am
Contact: Website

Re: Could someone run through this code with me?

Fri Jul 27, 2012 6:00 am

Hi D.E.L.B.,

Code: Select all

size = [400, 400]
makes a "size" a list with 2 elements. This way you can pass "size" to the command that creates the Pygame graphics window. This is the way Liam did it in his tutorial videos, and I think it's neater. You can just pass the actual numbers to "pygame.display.set_mode".

You can access the elements in a list by their indexes. So in this example size[0] is the first element (400) and size[1] is the second (400 also).

Later in the code, something like (size[0]/2) means half of the first element of size, in other words the middle of the screen's x-co-ordinate.

Let me know if there are any other bits that are unclear (I wrote this code, although it was changed a bit from the original by the magazine editor).

There is also a blog post on the program that I wrote for students at my school:
100mudcats blog. This is an earlier draft that might be a bit easier to follow.
Last edited by antiloquax on Fri Jul 27, 2012 6:10 am, edited 1 time in total.

User avatar
D.E.L.B.
Posts: 92
Joined: Sat Jun 09, 2012 7:16 pm
Location: Wales, UK
Contact: Website

Re: Could someone run through this code with me?

Fri Jul 27, 2012 6:06 am

Oops, double post by accident! Look at post below.
Last edited by D.E.L.B. on Fri Jul 27, 2012 6:11 am, edited 2 times in total.

User avatar
D.E.L.B.
Posts: 92
Joined: Sat Jun 09, 2012 7:16 pm
Location: Wales, UK
Contact: Website

Re: Could someone run through this code with me?

Fri Jul 27, 2012 6:06 am

antiloquax wrote:Hi D.E.L.B.,

Code: Select all

size = [400, 400]
makes a "size" a list with 2 elements. This way you can pass "size" to the command that creates the Pygame graphics window. This is the way Liam did it in his tutorial videos, and I think it's neater. You can just pass the actual numbers to "pygame.display.set_mode".

Let me know if there are any other bits that are unclear (I wrote this code, although it was changed a bit from the original by the magazine editor).

There is also a blog post on the program that I wrote for students at my school:
100mudcats blog
So it's basically object orientated programming?

So, would it matter if you had the [400, 400] in like this: ((400, 400))?

This bit:
batrect.center = ((size[0]/2), (size[1] - 50))
I don't get. I know in Liam's tutorials there was an example of which he used a Raspberry Pi logo, and he divided the x and y positions of the mouse by 2 to get the mouse cursor in the middle of the logo. But here... I am not so sure.

@timhoffman: I shall take a look at that very soon also! Knowledge is infinite.

antiloquax
Posts: 406
Joined: Sun Nov 20, 2011 11:37 am
Contact: Website

Re: Could someone run through this code with me?

Fri Jul 27, 2012 7:34 am

So, would it matter if you had the [400, 400] in like this: ((400, 400))?
Yes, that's right.

Code: Select all

batrect.center = ((size[0]/2), (size[1] - 50))
This was one of the bits that got changed by the editor. I originally wrote:

Code: Select all

batrect.center = (screenrect.centerx, (screenrect.bottom - 50))
Both do the same thing - they make the middle of the bat at the middle of the width of the screen and 50 pixels from the bottom.
mark

User avatar
D.E.L.B.
Posts: 92
Joined: Sat Jun 09, 2012 7:16 pm
Location: Wales, UK
Contact: Website

Re: Could someone run through this code with me?

Fri Jul 27, 2012 3:49 pm

So you know that [0], what's that for? As well as the [1].

I get the second code that you originally wrote, but not the one that is in the magazine.

Daverj
Posts: 28
Joined: Tue Mar 06, 2012 2:23 am
Contact: Website

Re: Could someone run through this code with me?

Fri Jul 27, 2012 7:52 pm

D.E.L.B. wrote:So you know that [0], what's that for? As well as the [1].
As he mentioned above, the [0] and [1] reference the first and second elements of the two numbers.

Think of the size = [400,400] as initializing 2 elements of an array. And the size[0] as referencing the first element of the array, while size[1] is referencing the second element of the array.

antiloquax
Posts: 406
Joined: Sun Nov 20, 2011 11:37 am
Contact: Website

Re: Could someone run through this code with me?

Fri Jul 27, 2012 10:22 pm

Daverj wrote:
Think of the size = [400,400] as initializing 2 elements of an array. And the size[0] as referencing the first element of the array, while size[1] is referencing the second element of the array.
Thanks Daverj, beat me to it!
:D
@D.E.L.B. I'm glad the blog post seemed clearer to you. Space is tight in the MagPi and I think the "printed" version suffered a bit!

User avatar
D.E.L.B.
Posts: 92
Joined: Sat Jun 09, 2012 7:16 pm
Location: Wales, UK
Contact: Website

Re: Could someone run through this code with me?

Sat Jul 28, 2012 1:03 am

Thanks guys! Oh and yes your blog post is much easier to understand.

There is also another piece of code which is called: "The House" and that basically draws shapes and RGB values to the screen to create a house.

But... I don't get these in the codes:

Code: Select all

# THE HOUSE
# By 0the0judge0 - 29th May 2012
import os, pygame; from pygame.locals import *
pygame.init(); clock = pygame.time.Clock()
os.environ['SDL_VIDEO_WINDOW_POS'] = 'center'
d = pygame.draw # this will save us writing 'pygame.draw' many times
pygame.display.set_caption("The House")
# Define some colors
white   =   (255,255,255); black   =   (0,0,0)
bg      =   (186, 213, 48); walls   =   (157, 109, 9)
door    =   (151, 36, 9); door_light =(181, 132, 14)
# coordinates of glass panes
windows = [(82, 125), (82, 215), (262, 125), (262, 215)]
#init screen
screen = pygame.display.set_mode([423,347],0,32)
#the walls
screen.fill(bg)     #fill the background screen colour
d.rect(screen, black, (60, 102, 305, 225) )
d.rect(screen, walls, (73, 114, 280, 200) )
#the roof
d.polygon(screen,black,((35,112),(121,12),(296,12),(321, 36),(321, 12),
(361, 12),(361, 84),(384, 112)))
d.polygon(screen,walls,((62,101),(128,23),(289,23),(334, 69),(334, 25),
(348, 25),(348, 88),(361, 101)))
#the door
d.rect(screen, black, (167, 198, 84, 125 ))
d.rect(screen, door, (179, 210, 60, 101 ))
d.rect(screen, black, (185, 216, 50, 54 ))
d.rect(screen, door_light, (191, 222, 38, 41 ))
d.circle(screen,black,(209,277),5)
#the windows
for window in windows:
    d.rect(screen, black, (window[0], window[1], 76, 76) )
    d.rect(screen, white, (window[0] + 12, window[1] + 12, 22, 22) ) #tl
    d.rect(screen, white, (window[0] + 42, window[1] + 12, 22, 22) ) #tr
    d.rect(screen, white, (window[0] + 12, window[1] + 42, 22, 22) ) #bl
    d.rect(screen, white, (window[0] + 42, window[1] + 42, 22, 22) ) #br
#lets see the end result
pygame.display.update()
pygame.time.wait(10000)
pygame.quit()
See this here:

Code: Select all

for window in windows:
    d.rect(screen, black, (window[0], window[1], 76, 76) )
    d.rect(screen, white, (window[0] + 12, window[1] + 12, 22, 22) ) #tl
    d.rect(screen, white, (window[0] + 42, window[1] + 12, 22, 22) ) #tr
    d.rect(screen, white, (window[0] + 12, window[1] + 42, 22, 22) ) #bl
    d.rect(screen, white, (window[0] + 42, window[1] + 42, 22, 22) ) #br
I know that refers back to:

Code: Select all

windows = [(82, 125), (82, 215), (262, 125), (262, 215)]
So, that window[0] refers back to the first element of the code above, right?

Okay, so... what I really don't get is the +12s and +42s, as well as the 12, 22,22s and 42, 22,22s.

What are they for?

khh
Posts: 49
Joined: Thu Jul 26, 2012 12:16 am

Re: Could someone run through this code with me?

Sat Jul 28, 2012 5:31 am

D.E.L.B. wrote:See this here:

Code: Select all

for window in windows:
    d.rect(screen, black, (window[0], window[1], 76, 76) )
    d.rect(screen, white, (window[0] + 12, window[1] + 12, 22, 22) ) #tl
    d.rect(screen, white, (window[0] + 42, window[1] + 12, 22, 22) ) #tr
    d.rect(screen, white, (window[0] + 12, window[1] + 42, 22, 22) ) #bl
    d.rect(screen, white, (window[0] + 42, window[1] + 42, 22, 22) ) #br
I know that refers back to:

Code: Select all

windows = [(82, 125), (82, 215), (262, 125), (262, 215)]
So, that window[0] refers back to the first element of the code above, right?
In python a for-loops runs through all the values of a list (or any other iterate object), assigning it's value to the specified variable (here 'window') in the indented block.
The indented code below therefore runs 4 times, first time with window = (82, 125), second with window = (82, 215), third with window = (262, 125) and fourth with window = (262, 215). The window[0] refers to the first of these numbers, in each case.
D.E.L.B. wrote:Okay, so... what I really don't get is the +12s and +42s, as well as the 12, 22,22s and 42, 22,22s.

What are they for?
I suspect they are simply for alignment and placing the elements correctly, but I have no experience with graphical computing.

User avatar
D.E.L.B.
Posts: 92
Joined: Sat Jun 09, 2012 7:16 pm
Location: Wales, UK
Contact: Website

Re: Could someone run through this code with me?

Sat Jul 28, 2012 6:08 am

Thanks.

So what about this one?

Code: Select all

   d.rect(screen, black, (window[0], window[1], 76, 76) )

khh
Posts: 49
Joined: Thu Jul 26, 2012 12:16 am

Re: Could someone run through this code with me?

Sat Jul 28, 2012 10:44 am

D.E.L.B. wrote:Thanks.

So what about this one?

Code: Select all

   d.rect(screen, black, (window[0], window[1], 76, 76) )
You can lookup what functions mean in the pygame reference.
This one draws a rectangle in black on surface 'screen'. The rectangle has coordinates (window[0], window[1]) and is 76x76 pixles big.

User avatar
D.E.L.B.
Posts: 92
Joined: Sat Jun 09, 2012 7:16 pm
Location: Wales, UK
Contact: Website

Re: Could someone run through this code with me?

Sat Jul 28, 2012 9:58 pm

But where are the coordinates for the black window? Because there is only 4 coordinates in the variable "windows".

I find it hard to see where the window with the square bracket coordinates are defined because there are only 4, and there is 5 in the Windows for-loop.

Narishma
Posts: 151
Joined: Wed Nov 23, 2011 1:29 pm

Re: Could someone run through this code with me?

Sun Jul 29, 2012 2:56 am

D.E.L.B. wrote:But where are the coordinates for the black window? Because there is only 4 coordinates in the variable "windows".

I find it hard to see where the window with the square bracket coordinates are defined because there are only 4, and there is 5 in the Windows for-loop.
Each time it goes through the loop (so 4 times in this case because "windows" has 4 elements), it draws 5 rectangles (1 black and 4 white) using the coordinates it gets from window and different displacement values (those 12's and 42's).

"window" only has one pair of coordinates that gets used 5 times before going to the next pair.

User avatar
D.E.L.B.
Posts: 92
Joined: Sat Jun 09, 2012 7:16 pm
Location: Wales, UK
Contact: Website

Re: Could someone run through this code with me?

Sun Jul 29, 2012 5:01 am

Ah I see, I think I get it now.

So that window[0], refers back to these?:
82
82
262
262

Then window[1] refers to:
125
215
125
215

Right?


antiloquax
Posts: 406
Joined: Sun Nov 20, 2011 11:37 am
Contact: Website

Re: Could someone run through this code with me?

Sun Jul 29, 2012 6:55 am

khh wrote:
D.E.L.B. wrote:

Code: Select all

windows = [(82, 125), (82, 215), (262, 125), (262, 215)]

Code: Select all

for window in windows:
    d.rect(screen, black, (window[0], window[1], 76, 76) )
    d.rect(screen, white, (window[0] + 12, window[1] + 12, 22, 22) ) #tl
    d.rect(screen, white, (window[0] + 42, window[1] + 12, 22, 22) ) #tr
    d.rect(screen, white, (window[0] + 12, window[1] + 42, 22, 22) ) #bl
    d.rect(screen, white, (window[0] + 42, window[1] + 42, 22, 22) ) #br
So, that window[0] refers back to the first element of the code above, right?
You were right this time.
The first time through the loop, it takes the starting point as (82, 125). From there it draws one black square (76 x 76 pixels).
Then it draws 4 white squares (each 22 x 22 pixels). The "12"s and "42"s make it draw them within the black square. So the first is offset 12 pixels right of the left hand side of the black square and 12 pixels down from the top.

The next time through it does the same thing, starting from (82, 215) and so on.
mark

khh
Posts: 49
Joined: Thu Jul 26, 2012 12:16 am

Re: Could someone run through this code with me?

Sun Jul 29, 2012 9:15 am

antiloquax wrote:You were right this time.
The first time through the loop, it takes the starting point as (82, 125). From there it draws one black square (76 x 76 pixels).
Then it draws 4 white squares (each 22 x 22 pixels). The "12"s and "42"s make it draw them within the black square. So the first is offset 12 pixels right of the left hand side of the black square and 12 pixels down from the top.

The next time through it does the same thing, starting from (82, 215) and so on.
mark
No, window[0] always refers to a single number, it never refers to a touple.

In general I'd like to add that it can be beneficial to insert print statements at key points to see how code is running. That way can print key points, variables, etc. to console to understand what's going on where. If you for instance rewrite to:

Code: Select all

for window in windows:
    print "window =", window
    d.rect(screen, black, (window[0], window[1], 76, 76) )
    d.rect(screen, white, (window[0] + 12, window[1] + 12, 22, 22) ) #tl
    d.rect(screen, white, (window[0] + 42, window[1] + 12, 22, 22) ) #tr
    d.rect(screen, white, (window[0] + 12, window[1] + 42, 22, 22) ) #bl
    d.rect(screen, white, (window[0] + 42, window[1] + 42, 22, 22) ) #br
It will print

Code: Select all

window = (82, 125)
window = (82, 215)
window = (262, 125)
window = (262, 215)
Also you seem to be starting in the wrong end. If you want to write games in python you will probably have a much easier time if you learn the basic workings of the language first. This is more important the less experience one has with coding.

antiloquax
Posts: 406
Joined: Sun Nov 20, 2011 11:37 am
Contact: Website

Re: Could someone run through this code with me?

Sun Jul 29, 2012 7:48 pm

Hi khh,

Yes, you are of course right that window[0] refers to 82.
What I was trying to explain was that the first time through the loop, window holds (82, 125) and from there we draw a black square etc.

By the way, I didn't write this program - it was one of the other MagPi writers.
I totally agree that it is useful to add print statements to get some console output as to what is happening. However, in the MagPi, we don't have a huge amount of space for each program and so things like this tend to be passed over.

Also, I don't know why you made such a point of saying that "window[0]" refers to a single number - after all, what I wrote doesn't suggest anything different.

Anyway ... thanks for your comment :)

User avatar
D.E.L.B.
Posts: 92
Joined: Sat Jun 09, 2012 7:16 pm
Location: Wales, UK
Contact: Website

Re: Could someone run through this code with me?

Sun Jul 29, 2012 8:59 pm

I get it now, thanks a bunch!

Might I also suggest that it might be worth having a seperate edition of The Mag Pi for programming, that way it's easier to get everything in without missing important things that people need to understand the codes.

khh
Posts: 49
Joined: Thu Jul 26, 2012 12:16 am

Re: Could someone run through this code with me?

Tue Jul 31, 2012 10:31 pm

@antiloquax: Sorry, I misunderstood you then. With your quote and the "You were right the first time", it seemed to me like that was what you were implying.
Also what I said wasn't meant as criticism to the writer of the program or the MagPi, just as a tip to OP on a simple way of identifying what's happening in a script/program.

antiloquax
Posts: 406
Joined: Sun Nov 20, 2011 11:37 am
Contact: Website

Re: Could someone run through this code with me?

Wed Aug 01, 2012 12:37 pm

Thanks khh. No problem. Like I said, your advice was very sound.
I am still very much a beginner, learning as I go!
mark
:)

toxibunny
Posts: 1382
Joined: Thu Aug 18, 2011 9:21 pm

Re: Could someone run through this code with me?

Sat Aug 04, 2012 5:04 pm

D.E.L.B. wrote:I get it now, thanks a bunch!

Might I also suggest that it might be worth having a seperate edition of The Mag Pi for programming, that way it's easier to get everything in without missing important things that people need to understand the codes.
I doubt they're going to split the magpi in two, but a dedicated forum thread per program would be useful...
note: I may or may not know what I'm talking about...

Return to “Python”