Welcome to Computer Programming For Kids (CP4K)

Welcome to the Computer Programming for Kids blog! We are the co-authors of the book "Hello World! Computer Programming for Kids and Other Beginners", released in March 2009. The book is published by Manning Publications. Manning has a web site for the book, which is where you can download the software and other files related to the book. You can purchase it here, at the Manning web site. If you use this link to purchase the print book or e-book from the Manning web site, you can use the discount code aupromo40 at checkout to get a 40% discount. You can also get it through online retailers like Amazon, as well as in many retail locations such as Chapters in Canada and Barnes & Noble in the U.S. This blog is mostly about the book (for now), but anything related to computers and programming, particularly for kids and beginners, is fair game. We will post articles with extra material that didn't make it into the book, and reader feedback and suggestions are always welcome.

Sunday, December 11, 2011

We've Moved!

We've Moved! You can find our new blog here.

And check out our "12 Days of Python", with a chance to win a Kindle Touch!


Warren & Carter

Friday, July 15, 2011

College for Kids

Recently, I (Carter) TA'ed for Dave Briccetti's College for Kids programming class for 11-to-14-year-olds at Diablo Valley College. We used Python 3 and Kojo Learning Environment (a turtle-based program you can script in Scala). I learned lots from the experience, and it was great working with Mr. Briccetti.

The kids in the class learned about loops, input, if statements, printing, and randomness in Python 3. They also learned about loops, functions, and controlling the turtle in Kojo. I saw lots of interesting projects come out of this. Some people were really creative (for instance, drawing complex pictures with Kojo) while others chose to examine and modify some of the example programs. One student, who I really enjoyed working with, was constantly asking me questions like, "So if I was to make it do one thing if there's an error, and another if there isn't, how would I do that?"

The one problem that almost everyone had at some point was typing things in correctly. Kids would call me over asking about some incomprehensible error message, and I would type one character and it would work. Remember, always make sure you type in the example properly if there's a problem.

I also did a presentation of functions. You can watch it on the Young Programmers Podcast.

Wednesday, April 20, 2011

LunarLander 2

Many of the games in the book are very simplified versions of classic computer games. LunarLander is an example of that. The original Lunar Lander arcade game was a “vector-graphics” game, where you have to land a lunar module on the moon. There is rocky lunar terrain with a few safe landing spots. You control the rotation and thrust of the lander to make a safe landing. Here’s a screen shot:

The LunarLander in “Hello World!” only moves vertically, not sideways. This was done to show a gravity simulation while keeping the code as simple as possible. After all, the point of the games in the book is to learn, not to make an accurate copy of an old arcade game. We encourage readers to take the games in the book as starting points and extend them in whatever way they like.

I thought it would be fun to take the first step in that direction with LunarLander. So, I made LunarLander2D. This turns LunarLander from a 1-D simulation (vertical only) to a 2-D simulation (vertical and horizontal), more like the arcade version.

To do that, there are two major things that needed to change:

  • Need to keep track of both vertical and horizontal speed
  • Need a way to rotate the lander, so you can thrust in different directions to steer

Of course, once you start doing rotation and applying thrust at different angles, you need some trigonometry to do the calculations. That’s the main reason we didn’t make LunarLander a 2-D simulation in the first place. We didn’t want to make trigonometry a requirement for the book.

I had to dust the cobwebs off my knowledge of trig. I found the trickiest part was figuring out how to draw the rocket flames at an angle when the lander is rotated. The code to do that is written in an “expanded” form. That is, the code could be made much more compact, but I’m trying to show step-by-step how I’m doing the calculation.

Here are the main differences from LunarLander to LunarLander2:

  • The window is wider, to make room for the sideways motion.
  • The lander is now a sprite, which makes it easier to do the rotation (using pygame.transform.rotate)
  • The thrust is controlled by pressing/holding the spacebar instead of using the mouse to drag a slider (There are no longer any mouse events.)
  • The rotation is controlled by the left and right arrow keys
  • A good landing now depends on both speed and angle

The code is shown below, and you can easily cut-and-paste it into your favourite Python editor to try it out. (I use SPE.) Don’t forget to put a copy of the image file (lunarlander.png) in the same folder as the code when you try to run it.

Here's a screenshot:

This is still a very simplified version. Here are some ways it could be enhanced:

  • Add some animation or different sprites when the lander lands roughly or crashes
  • Add different messages depending on how the landing was
  • Add more terrain and multiple landing spots
  • Have multiple turns, where it gets more difficult each time (steeper terrain, smaller landing spots, less fuel, etc.)

Enjoy!




# LunarLander2d.py
# Copyright Warren Sande, 2011

# Based on LunarLander, Copyright Warren Sande, 2009
# Released under MIT license http://www.opensource.org/licenses/mit-license.php


# LunarLander 2D
# simulation game of landing a spacecraft
"""
The original LunarLander in "Hello World! Computer Programming
for Kids and Other Beginners"
was a very simple 1-D (y-axis, vertical motion only)
version of Lunar Lander, just to demonstrate a simple
gravity simulaiton using Pygame.

LunarLander 2D adds the x-axis (sideways motion).
You can now rotate the lander using
the right/left arrow keys, more like
the original arcade version.
It also changes the thrust control from a
mouse-based (dragging the slider) to key-based
(press/hold the spacebar).

Instead of the moonsurface image,
it uses a simple landing pad rectangle.

"""

# initialize - get everything ready
import pygame, sys
from math import *
pygame.init()
#wider screen than LunarLander, since we have sideways motion
screen = pygame.display.set_mode([800,600])
screen.fill([0, 0, 0])
ground = 540 #landing pad is ay y = 540
start = 90 # starting location 90 pixels from top of window
clock = pygame.time.Clock()
ship_mass = 5000.0
fuel = 5000.0
fps = 30 #default
x_loc = 20 # x-location in meters = dist from center of landing pad
y_loc = 40 # y-location in meters = height above the landing pad

x_offset = 40 # offsets so that when ship location is (0,0), ship is
y_offset = -108 # just touching landing pad, and centered.

x_speed = 2000.0 #pixels/frame
y_speed = -800.0

x_velocity = x_speed/(10.0*fps) #m/s
y_velocity = y_speed/(10.0*fps)

gravity = 1.5
thrust = 0
delta_v = 0
scale = 10 #scale factor from pixels to meters
throttle_down = False
left_down = False
right_down = False
#held_down = False
count = 0
x_pos = 0
y_pos = 0

"""
x_pos, y_pos in pixels - (0,0) is top left
x_loc, y_loc in meters - (0,0) is center of landing pad

x_speed, y_speed in pixels per frame.
x_velocity, y_velocity in m/s

scale factor = 10 (10 pixels = 1 meter)

pos (pixels) to loc (meters) is scaled by: scaleFactor (meters/pixel)
speed (pixels/frame) to velocity (m/s) is scaled by:
ScaleFactor * FPS (Frames Per Second)

"""


# sprite for the ship
class ShipClass(pygame.sprite.Sprite):
def __init__(self, image_file, position):

pygame.sprite.Sprite.__init__(self)
self.imageMaster = pygame.image.load(image_file)
self.image = self.imageMaster
self.rect = self.image.get_rect()
self.position = position
self.rect.centerx, self.rect.centery = self.position
self.angle = 0

def update(self):
self.rect.centerx, self.rect.centery = self.position
oldCenter = self.rect.center
self.image = pygame.transform.rotate(self.imageMaster, self.angle)
self.rect = self.image.get_rect()
self.rect.center = oldCenter


# calcualte position, motion, acceleration, fuel
def calculate_velocity():
global ship, thrust, fuel, x_velocity, y_velocity, x_loc, y_loc
global tot_velocity, scale, x_pos, y_pos, x_speed, y_speed

delta_t = 1/fps

#Calculate thrust based on spacebar being held down
if throttle_down:
thrust = thrust + 100
if thrust > 1000:
thrust = 1000
else:
if thrust > 0:
thrust = thrust - 200
if thrust < 0:
thrust = 0
fuel -= thrust /(10 * fps) # use up fuel
if fuel < 0: fuel = 0.0
if fuel < 0.1: thrust = 0.0
ythrust = thrust * cos(ship.angle*(pi/180))
xthrust = thrust * sin(ship.angle*(pi/180))
y_delta_v = delta_t * (-gravity + 50 * ythrust / (ship_mass + fuel))
y_velocity = y_velocity + y_delta_v
x_delta_v = delta_t * (-50 * xthrust/(ship_mass + fuel))
x_velocity = x_velocity + x_delta_v
x_speed = x_velocity * 10.0/fps #speed in pixels/frame, velocity in m/s
y_speed = y_velocity * 10.0/fps
y_loc = y_loc + y_velocity/fps # loc in meters, velocity in m/s
x_loc = x_loc - x_velocity/fps
tot_velocity = sqrt(x_velocity**2 + y_velocity**2)
ship.position[0] = x_pos = screen.get_width()/2 - (scale * x_loc) + x_offset
ship.position[1] = y_pos = screen.get_height() - (scale * y_loc) + y_offset


if right_down:
ship.angle = ship.angle - 2
if left_down:
ship.angle = ship.angle + 2
ship.update()



# display the text with the speed, height, etc.
def display_stats():
vv_str = "vertical speed: %.1f m/s" % y_velocity # in m/s
hv_str = "horizontal speed %.1f m/s" % x_velocity # in m/s
tv_str = "Total Velocity %.1f m/s" % tot_velocity # in m/s
h_str = "height: %.1f m" % y_loc #in meters
x_str = "position: %.1f m" % x_loc
ang_str = "Angle: %.1f" % ship.angle
t_str = "thrust: %i kg" % thrust
a_str = "acceleration: %.1f m/s/s" % (delta_v * fps)
f_str = "fuel: %i" % fuel

vv_font = pygame.font.Font(None, 26) #vertical speed
vv_surf = vv_font.render(vv_str, 1, (255, 255, 255))
screen.blit(vv_surf, [10, 50])

hv_font = pygame.font.Font(None, 26) #horizontal speed
hv_surf = hv_font.render(hv_str, 1, (255, 255, 255))
screen.blit(hv_surf, [10, 70])

hv_font = pygame.font.Font(None, 26) #horizontal speed
hv_surf = hv_font.render(hv_str, 1, (255, 255, 255))
screen.blit(hv_surf, [10, 90])

h_font = pygame.font.Font(None, 26) #y-location (height)
h_surf = h_font.render(h_str, 1, (255, 255, 255))
screen.blit(h_surf, [10, 120])

x_font = pygame.font.Font(None, 26) #x_location
x_surf = x_font.render(x_str, 1, (255, 255, 255))
screen.blit(x_surf, [10, 150])

ang_font = pygame.font.Font(None, 26) #angle
ang_surf = ang_font.render(ang_str, 1, (255, 255, 255))
screen.blit(ang_surf, [10, 180])

t_font = pygame.font.Font(None, 26) #thrust
t_surf = t_font.render(t_str, 1, (255, 255, 255))
screen.blit(t_surf, [10, 210])

a_font = pygame.font.Font(None, 26) #acceleration
a_surf = a_font.render(a_str, 1, (255, 255, 255))
screen.blit(a_surf, [10, 240])

f_font = pygame.font.Font(None, 26) #fuel
f_surf = f_font.render(f_str, 1, (255, 255, 255))
screen.blit(f_surf, [60, 330])

# display the ship's flames - size depends on the amount of thrust
def display_flames():
fsize = thrust / 30 #flame size
# for rotation, need to do some trig to draw the flame triangles
# in the correct orientation
# points a-f are the 6 vertices of the 2 flame triangles

# calcualte polar coordinates of un-rotated flames
a_len = sqrt(43*43 + 17*17)
b_len = sqrt( (43+fsize)*(43+fsize) + 13*13)
c_len = sqrt(43*43 + 9*9)
d_len = c_len
e_len = b_len
f_len = a_len
a_ang_orig = atan2(-17.0,-43.0)
b_ang_orig = atan2(-13.0,(-43-fsize))
c_ang_orig = atan2(-9.0,-43.0)
d_ang_orig = atan2(9.0,-43.0)
e_ang_orig = atan2(13.0,(-43.0-fsize))
f_ang_orig = atan2(17.0,-43.0)

# rotate flame by same angle as ship rotation
a_ang_rot = a_ang_orig + (270-ship.angle)*(pi/180)
b_ang_rot = b_ang_orig + (270-ship.angle)*(pi/180)
c_ang_rot = c_ang_orig + (270-ship.angle)*(pi/180)
d_ang_rot = d_ang_orig + (270-ship.angle)*(pi/180)
e_ang_rot = e_ang_orig + (270-ship.angle)*(pi/180)
f_ang_rot = f_ang_orig + (270-ship.angle)*(pi/180)

# calculate x-y coordinates of rotated flames
ax = int(a_len * cos(a_ang_rot))
ay = int(a_len * sin(a_ang_rot))
bx = int(b_len * cos(b_ang_rot))
by = int(b_len * sin(b_ang_rot))
cx = int(c_len * cos(c_ang_rot))
cy = int(c_len * sin(c_ang_rot))
dx = int(d_len * cos(d_ang_rot))
dy = int(d_len * sin(d_ang_rot))
ex = int(e_len * cos(e_ang_rot))
ey = int(e_len * sin(e_ang_rot))
fx = int(f_len * cos(f_ang_rot))
fy = int(f_len * sin(f_ang_rot))

#draw the flames
pygame.draw.polygon(screen, [255, 109, 14],
[(x_pos + ax, y_pos + ay),
(x_pos + bx, y_pos + by),
(x_pos + cx, y_pos + cy)], 0)
pygame.draw.polygon(screen, [255, 109, 14],
[(x_pos + dx, y_pos + dy),
(x_pos + ex, y_pos + ey),
(x_pos + fx, y_pos + fy)], 0)

# display final stats when the game is over
def display_final():
global x_velocity, y_velocity, tot_velocity, ship #, fuelbar
final1 = "Game over"
final2 = "You landed at:"
final3 = "%.1f m/s horizontal" % x_velocity
final4 = "%.1f m/s vertical" % y_velocity
final5 = "%.1f m/s Total" % tot_velocity
final6 = "%.1f degrees" % ship.angle
screen.fill([0, 0, 0])
pygame.draw.rect(screen, [0, 0, 255], [80, 350, 24, 100], 2)
pygame.draw.rect(screen, [0,255,0], [84,448-fuelbar,18, fuelbar], 0)
drawTerrain()
screen.blit(ship.image, ship.rect)

if (abs(tot_velocity) < 2 and abs(ship.angle) < 5):
final7 = "Nice landing!"
final8 = "I hear NASA is hiring!"
elif (abs(tot_velocity) < 55 and abs(ship.angle < 10)):
final7 = "Ouch! A bit rough, but you survived."
final8 = "You'll do better next time."
else:
final7 = "Yikes! You crashed a 30 Billion dollar ship."
final8 = "How are you getting home?"
pygame.draw.rect(screen, [0, 0, 0], [5, 5, 350, 280],0)
f1_font = pygame.font.Font(None, 70)
f1_surf = f1_font.render(final1, 1, (255, 255, 255))
screen.blit(f1_surf, [20, 50])
f2_font = pygame.font.Font(None, 40)
f2_surf = f2_font.render(final2, 1, (255, 255, 255))
screen.blit(f2_surf, [20, 110])
f3_font = pygame.font.Font(None, 26)
f3_surf = f3_font.render(final3, 1, (255, 255, 255))
screen.blit(f3_surf, [20, 150])
f4_font = pygame.font.Font(None, 26)
f4_surf = f4_font.render(final4, 1, (255, 255, 255))
screen.blit(f4_surf, [200, 150])
f5_font = pygame.font.Font(None, 26)
f5_surf = f5_font.render(final5, 1, (255, 255, 255))
screen.blit(f5_surf, [380, 150])
f6_font = pygame.font.Font(None, 26)
f6_surf = f6_font.render(final6, 1, (255, 255, 255))
screen.blit(f6_surf, [20, 180])
f7_font = pygame.font.Font(None, 26)
f7_surf = f7_font.render(final7, 1, (255, 255, 255))
screen.blit(f7_surf, [20, 210])
f8_font = pygame.font.Font(None, 26)
f8_surf = f8_font.render(final8, 1, (255, 255, 255))
screen.blit(f8_surf, [20, 240])
screen.blit(inst1_surf, [50, 550])
screen.blit(inst2_surf, [20, 575])
screen.blit(inst3_surf, [50, 600])
pygame.display.flip()


# draw the landing pad.
# note: This could be made more complex, but just a
# simple landing pad for now.
def drawTerrain():
pygame.draw.rect(screen, [180, 180, 180], [420, 535, 70, 5],0)

# make an instance of the ship sprite
ship = ShipClass('lunarlander.png', [500, 230])

# main loop
while True:
clock.tick(30)
fps = clock.get_fps()
if fps < 1: fps = 30
count += 1
if y_loc > 0.01:
calculate_velocity()
screen.fill([0, 0, 0])
display_stats()
pygame.draw.rect(screen, [0, 0, 255], [80, 350, 24, 100], 2)
fuelbar = 96 * fuel / 5000
pygame.draw.rect(screen, [0,255,0], [84,448-fuelbar,18, fuelbar], 0)
drawTerrain()
display_flames()
screen.blit(ship.image, ship.rect)
instruct1 = "Land softly without running out of fuel"
instruct2 = "Good landing: < 5 m/s Great landing: < 2m/s"
instruct3 = "And you must be within 10 degrees of vertical"
inst1_font = pygame.font.Font(None, 24)
inst1_surf = inst1_font.render(instruct1, 1, (255, 255, 255))
screen.blit(inst1_surf, [50, 550])
inst2_font = pygame.font.Font(None, 24)
inst2_surf = inst1_font.render(instruct2, 1, (255, 255, 255))
screen.blit(inst2_surf, [20, 575])
inst3_font = pygame.font.Font(None, 24)
inst3_surf = inst3_font.render(instruct3, 1, (255, 255, 255))
screen.blit(inst3_surf, [50, 600])
pygame.display.flip()

else: #game over - print final score
display_final()

for event in pygame.event.get():
if event.type == pygame.QUIT:
sys.exit()
elif event.type == pygame.KEYDOWN:
if event.key == pygame.K_SPACE:
throttle_down = True
if event.key == pygame.K_RIGHT:
right_down = True
if event.key == pygame.K_LEFT:
left_down = True
elif event.type == pygame.KEYUP:
if event.key == pygame.K_SPACE:
throttle_down = False
if event.key == pygame.K_RIGHT:
right_down = False
if event.key == pygame.K_LEFT:
left_down = False


Monday, March 14, 2011

Hello World! Chinese Translation

A few days ago we received a few copies of the Chinese translation of "Hello World". Here's what the cover looks like:



It's pretty cool so see our book published in other languages. The book is published in China by Turing, which is a division of the Posts and Telecom Press. You can see their web page for the book here:

http://www.turingbook.com/Books/ShowBook-629.aspx


Sunday, February 27, 2011

What to do if you're having problems.

Every programmer, new or not, will encounter some difficulties. If this happens, we're here to help! Here are the top 3 things to look for when programs have an error.
  1. Proper version of Python and all required modules. Did you use our book's installer to get Python? If not, get the installer here and follow the instructions.
  2. Indentation. Make sure spacing is correct. This is very important in Python.
  3. Check for typos. A silly thing like a spelling error or typing _ instead of - might cause your program to have an error. Make sure it matches the one in the book.
If you still can't figure it out, leave a comment on our blog, post a question on our Author Forum, or e-mail us at cp4khelp@yahoo.com . We do our best to get back to you within 48 hours.

--Carter

Thursday, September 23, 2010

Cool stuff for Mac

Hey guys,

Recently, I got a Mac. This means I'll be able to help a lot more with Mac problems on our author forums and on this blog. In related news, here's a cool trick for Macs only. You can make your program talk to you! Start by importing os. OS is a module that lets you interact with your computer's operating system. Then, type the following:

os.system("say Hello World!")

This will send a command to Mac OS telling it to, well, say, "Hello World!" You can put whatever you want after say. However, apostrophes (') don't seem to work. If you have one in your string, it won't say anything at all. Here's an example program:

import os
os.system("say Whats your name?")
#For some reason, apostrophes don't work.

name = raw_input("What's your name?")
# It's good to put it on the screen as well,
# in case users don't have their speakers on.

print "Hi, "+name+", hows it going?"
os.system("say Hi, "+name+", hows it going?")

I hope this brings a whole new level of interaction to all your future programs!

Carter Sande

Tuesday, June 29, 2010

Carter Teaches Random



Dave Briccetti, who, among other things, teaches programming to kids, is teaching a Python class for Grade 7-9 students this summer at College for Kids. He asked if we would be interested in doing a "guest lecture" to his class. So Carter presented an introduction to randomness and the Python Random module. You can see the video on Dave's site, here:
http://young-programmers.blogspot.com/2010/06/randomness-in-python-lesson-by-carter.html