Last active
December 14, 2015 05:39
-
-
Save vanphuong12a2/6a1e6a046a8c14a45944 to your computer and use it in GitHub Desktop.
Coursera: An Introduction to Interactive Programming in Python. Try on http://www.codeskulptor.org
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
# http://www.codeskulptor.org/#user38_BFtRPWuJKS_1.py | |
# Mini-project #6 - Blackjack | |
import simplegui | |
import random | |
# load card sprite - 936x384 - source: jfitz.com | |
CARD_SIZE = (72, 96) | |
CARD_CENTER = (36, 48) | |
card_images = simplegui.load_image("http://storage.googleapis.com/codeskulptor-assets/cards_jfitz.png") | |
CARD_BACK_SIZE = (72, 96) | |
CARD_BACK_CENTER = (36, 48) | |
card_back = simplegui.load_image("http://storage.googleapis.com/codeskulptor-assets/card_jfitz_back.png") | |
# initialize some useful global variables | |
in_play = False | |
outcome = "" | |
score = 0 | |
matches = 0 | |
# define globals for cards | |
SUITS = ('C', 'S', 'H', 'D') | |
RANKS = ('A', '2', '3', '4', '5', '6', '7', '8', '9', 'T', 'J', 'Q', 'K') | |
VALUES = {'A':1, '2':2, '3':3, '4':4, '5':5, '6':6, '7':7, '8':8, '9':9, 'T':10, 'J':10, 'Q':10, 'K':10} | |
# define card class | |
class Card: | |
def __init__(self, suit, rank): | |
if (suit in SUITS) and (rank in RANKS): | |
self.suit = suit | |
self.rank = rank | |
self.up = True | |
else: | |
self.suit = None | |
self.rank = None | |
self.up = None | |
print "Invalid card: ", suit, rank | |
def __str__(self): | |
return self.suit + self.rank | |
def get_suit(self): | |
return self.suit | |
def get_rank(self): | |
return self.rank | |
def turn(self): | |
self.up = not(self.up) | |
def draw(self, canvas, pos): | |
if self.up: | |
card_loc = (CARD_CENTER[0] + CARD_SIZE[0] * RANKS.index(self.rank), | |
CARD_CENTER[1] + CARD_SIZE[1] * SUITS.index(self.suit)) | |
canvas.draw_image(card_images, card_loc, CARD_SIZE, [pos[0] + CARD_CENTER[0], pos[1] + CARD_CENTER[1]], CARD_SIZE) | |
else: | |
card_loc = CARD_BACK_CENTER | |
canvas.draw_image(card_back, card_loc, CARD_SIZE, [pos[0] + CARD_CENTER[0], pos[1] + CARD_CENTER[1]], CARD_BACK_SIZE) | |
# define hand class | |
class Hand: | |
def __init__(self): | |
self.cards = [] | |
def __str__(self): | |
res = "Hand contains" | |
for card in self.cards: | |
res += " " + str(card) | |
return res | |
def add_card(self, card): | |
self.cards.append(card) | |
def get_value(self): | |
# count aces as 1, if the hand has an ace, then add 10 to hand value if it doesn't bust | |
#pass # compute the value of the hand, see Blackjack video | |
value = 0 | |
gotA = False | |
for card in self.cards: | |
value += VALUES[card.get_rank()] | |
if card.get_rank() == 'A': | |
gotA = True | |
if gotA and value + 10 <= 21: | |
value += 10 | |
return value | |
def draw(self, canvas, pos): | |
#pass # draw a hand on the canvas, use the draw method for cards | |
for i in range(len(self.cards)): | |
card = self.cards[i] | |
card.draw(canvas, [pos[0] + i * CARD_SIZE[0], pos[1]]) | |
# define deck class | |
class Deck: | |
def __init__(self): | |
self.cards = [] | |
for suit in SUITS: | |
for rank in RANKS: | |
self.cards.append(Card(suit, rank)) | |
def shuffle(self): | |
# shuffle the deck | |
random.shuffle(self.cards) | |
def deal_card(self): | |
card = self.cards.pop() | |
return card | |
def __str__(self): | |
res = "" | |
for card in self.cards: | |
res += str(card) + " " | |
return res | |
#define event handlers for buttons | |
def deal(): | |
global outcome, in_play | |
# your code goes here | |
global deck, player_hands, dealer_hands, score | |
global hole_card, matches | |
if in_play: | |
matches += 1 | |
deck = Deck() | |
deck.shuffle() | |
player_hands = Hand() | |
dealer_hands = Hand() | |
player_hands.add_card(deck.deal_card()) | |
player_hands.add_card(deck.deal_card()) | |
dealer_hands.add_card(deck.deal_card()) | |
hole_card = deck.deal_card() | |
hole_card.turn() | |
dealer_hands.add_card(hole_card) | |
print "PLAYER: " + str(player_hands) + " ==> " + str(player_hands.get_value()) | |
#print "DEALER: " + str(dealer_hands) + " ==> " + str(dealer_hands.get_value()) | |
in_play = True | |
outcome = "Hit or stand?" | |
def hit(): | |
#pass # replace with your code below | |
global deck, player_hands, dealer_hands | |
global in_play, outcome, matches, score | |
global hole_card | |
# if the hand is in play, hit the player | |
if in_play: | |
player_hands.add_card(deck.deal_card()) | |
print "PLAYER: " + str(player_hands) + " ==> " + str(player_hands.get_value()) | |
# if busted, assign a message to outcome, update in_play and score | |
if player_hands.get_value() > 21: | |
outcome = "You have busted. New deal?" | |
#outcome = "You lose!" | |
score -= 1 | |
matches += 1 | |
hole_card.turn() | |
in_play = False | |
def stand(): | |
#pass # replace with your code below | |
global deck, player_hands, dealer_hands | |
global in_play, score, matches, outcome | |
global hole_card | |
# if hand is in play, repeatedly hit dealer until his hand has value 17 or more | |
if in_play: | |
while dealer_hands.get_value() < 17: | |
dealer_hands.add_card(deck.deal_card()) | |
print "DEALER: " + str(dealer_hands) + " ==> " + str(dealer_hands.get_value()) | |
# if busted, assign a message to outcome, update in_play and score | |
if dealer_hands.get_value() > 21 or player_hands.get_value() > dealer_hands.get_value(): | |
score += 1 | |
if dealer_hands.get_value() > 21: | |
outcome = "Dealer has busted. You won! New deal?" | |
else: | |
outcome = "You won! New deal?" | |
else: | |
outcome = "You lose! New deal?" | |
matches += 1 | |
hole_card.turn() | |
in_play = False | |
# draw handler | |
def draw(canvas): | |
# test to make sure that card.draw works, replace with your code below | |
global deck, player_hands, dealer_hands | |
global score, outcome | |
canvas.draw_text('BLACKJACK', (170, 50), 40, 'Black') | |
canvas.draw_text(outcome, (100, 130), 24, 'Black') | |
canvas.draw_text("Score = " + str(score) + "/" + str(matches), (420, 580), 20, 'Black') | |
canvas.draw_text('YOUR HAND', (100, 190), 20, 'Black') | |
player_hands.draw(canvas, [100, 200]) | |
canvas.draw_text('DEALER', (100, 390), 20, 'Black') | |
dealer_hands.draw(canvas, [100, 400]) | |
# initialization frame | |
frame = simplegui.create_frame("Blackjack", 600, 600) | |
frame.set_canvas_background("Green") | |
#create buttons and canvas callback | |
frame.add_button("Deal", deal, 200) | |
frame.add_button("Hit", hit, 200) | |
frame.add_button("Stand", stand, 200) | |
frame.set_draw_handler(draw) | |
# get things rolling | |
deal() | |
frame.start() |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
# Try on http://www.codeskulptor.org/#user38_5Q9p2uVHZF_1.py | |
# implementation of card game - Memory | |
import simplegui | |
import random | |
cards = range(8) | |
cards.extend(range(8)) | |
# helper function to initialize globals | |
def new_game(): | |
global state, cards, turns, exposed | |
exposed = [False for i in range(16)] | |
state = 0 | |
turns = 0 | |
random.shuffle(cards) | |
# define event handlers | |
def mouseclick(pos): | |
global state, turns, upcard1, upcard2 | |
# add game state logic here | |
i = (pos[0])/50 | |
if not(exposed[i]): | |
exposed[i] = True | |
if state == 0: | |
state = 1 | |
upcard1 = i | |
elif state == 1: | |
state = 2 | |
upcard2 = i | |
else: | |
if cards[upcard1] != cards[upcard2]: | |
exposed[upcard1] = False | |
exposed[upcard2] = False | |
turns += 1 | |
state = 1 | |
upcard1 = i | |
# cards are logically 50x100 pixels in size | |
def draw(canvas): | |
global turns | |
label.set_text("Turns = "+ str(turns)) | |
for i in range(len(cards)): | |
if exposed[i]: | |
canvas.draw_text(str(cards[i]), [15 + i * 50, 65], 30, "red") | |
else: | |
canvas.draw_polygon([(i * 50, 0), (i * 50 + 50, 0), (i * 50 + 50, 100), (i * 50, 100)], 1, 'White', 'Green') | |
# create frame and add a button and labels | |
frame = simplegui.create_frame("Memory", 800, 100) | |
frame.add_button("Reset", new_game) | |
label = frame.add_label("Turns = 0") | |
# register event handlers | |
frame.set_mouseclick_handler(mouseclick) | |
frame.set_draw_handler(draw) | |
# get things rolling | |
new_game() | |
frame.start() | |
# Always remember to review the grading rubric |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
# Try on http://www.codeskulptor.org/#user38_nR2bj9NEcj_3.py | |
# Implementation of classic arcade game Pong | |
import simplegui | |
import random | |
# initialize globals - pos and vel encode vertical info for paddles | |
WIDTH = 600 | |
HEIGHT = 400 | |
BALL_RADIUS = 20 | |
PAD_WIDTH = 8 | |
PAD_HEIGHT = 80 | |
HALF_PAD_WIDTH = PAD_WIDTH / 2 | |
HALF_PAD_HEIGHT = PAD_HEIGHT / 2 | |
LEFT = False | |
RIGHT = True | |
# initialize ball_pos and ball_vel for new bal in middle of table | |
# if direction is RIGHT, the ball's velocity is upper right, else upper left | |
def spawn_ball(direction): | |
global ball_pos, ball_vel # these are vectors stored as lists | |
ball_pos = [WIDTH / 2, HEIGHT / 2] | |
h = float(random.randrange(120, 240)) | |
v = float(random.randrange(60, 180)) | |
if direction == RIGHT: | |
ball_vel = [h/100, -v/100] | |
else: | |
ball_vel = [-h/100, -v/100] | |
# define event handlers | |
def new_game(): | |
global paddle1_pos, paddle2_pos, paddle1_vel, paddle2_vel # these are numbers | |
global score1, score2 # these are ints | |
paddle1_pos, paddle2_pos = HALF_PAD_HEIGHT, HALF_PAD_HEIGHT | |
paddle1_vel, paddle2_vel = 0, 0 | |
score1, score2 = 0, 0 | |
spawn_ball(RIGHT) | |
def draw(canvas): | |
global score1, score2, paddle1_pos, paddle2_pos, ball_pos, ball_vel | |
global paddle1_vel, paddle2_vel | |
# draw mid line and gutters | |
canvas.draw_line([WIDTH / 2, 0],[WIDTH / 2, HEIGHT], 1, "White") | |
canvas.draw_line([PAD_WIDTH, 0],[PAD_WIDTH, HEIGHT], 1, "White") | |
canvas.draw_line([WIDTH - PAD_WIDTH, 0],[WIDTH - PAD_WIDTH, HEIGHT], 1, "White") | |
# update ball | |
ball_pos = [ball_pos[i] + ball_vel[i] for i in range(len(ball_pos))] | |
if ball_pos[1] < BALL_RADIUS or ball_pos[1] > HEIGHT - BALL_RADIUS: | |
ball_vel[1] = - ball_vel[1] | |
if ball_pos[0] > WIDTH + BALL_RADIUS : | |
spawn_ball(LEFT) | |
if ball_pos[0] < - BALL_RADIUS: | |
spawn_ball(RIGHT) | |
# draw ball | |
canvas.draw_circle(ball_pos, BALL_RADIUS, 1 , 'White', 'Green') | |
# update paddle's vertical position, keep paddle on the screen | |
paddle1_pos += paddle1_vel | |
paddle2_pos += paddle2_vel | |
# draw paddles | |
canvas.draw_line([HALF_PAD_WIDTH, paddle1_pos - HALF_PAD_HEIGHT],[HALF_PAD_WIDTH, paddle1_pos + HALF_PAD_HEIGHT], PAD_WIDTH, 'Blue') | |
canvas.draw_line([WIDTH - HALF_PAD_WIDTH, paddle2_pos - HALF_PAD_HEIGHT],[WIDTH - HALF_PAD_WIDTH, paddle2_pos + HALF_PAD_HEIGHT], PAD_WIDTH, 'Blue') | |
# draw scores | |
def keydown(key): | |
global paddle1_vel, paddle2_vel | |
def keyup(key): | |
global paddle1_vel, paddle2_vel | |
def reset(): | |
global score1, score2 | |
new_game() | |
# create frame | |
frame = simplegui.create_frame("Pong", WIDTH, HEIGHT) | |
frame.set_draw_handler(draw) | |
frame.set_keydown_handler(keydown) | |
frame.set_keyup_handler(keyup) | |
#timer = simplegui.create_timer(1, draw) | |
frame.add_button("Reset", reset, 100) | |
# start frame | |
new_game() | |
frame.start() | |
#timer.start() |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
# Try on http://www.codeskulptor.org/#user38_ywqU83yx2D_0.py | |
# implementation of Spaceship - program template for RiceRocks | |
import simplegui | |
import math | |
import random | |
# globals for user interface | |
WIDTH = 800 | |
HEIGHT = 600 | |
score = 0 | |
lives = 3 | |
time = 0 | |
started = False | |
class ImageInfo: | |
def __init__(self, center, size, radius = 0, lifespan = None, animated = False): | |
self.center = center | |
self.size = size | |
self.radius = radius | |
if lifespan: | |
self.lifespan = lifespan | |
else: | |
self.lifespan = float('inf') | |
self.animated = animated | |
def get_center(self): | |
return self.center | |
def get_size(self): | |
return self.size | |
def get_radius(self): | |
return self.radius | |
def get_lifespan(self): | |
return self.lifespan | |
def get_animated(self): | |
return self.animated | |
# art assets created by Kim Lathrop, may be freely re-used in non-commercial projects, please credit Kim | |
# debris images - debris1_brown.png, debris2_brown.png, debris3_brown.png, debris4_brown.png | |
# debris1_blue.png, debris2_blue.png, debris3_blue.png, debris4_blue.png, debris_blend.png | |
debris_info = ImageInfo([320, 240], [640, 480]) | |
debris_image = simplegui.load_image("http://commondatastorage.googleapis.com/codeskulptor-assets/lathrop/debris2_blue.png") | |
# nebula images - nebula_brown.png, nebula_blue.png | |
nebula_info = ImageInfo([400, 300], [800, 600]) | |
nebula_image = simplegui.load_image("http://commondatastorage.googleapis.com/codeskulptor-assets/lathrop/nebula_blue.f2014.png") | |
# splash image | |
splash_info = ImageInfo([200, 150], [400, 300]) | |
splash_image = simplegui.load_image("http://commondatastorage.googleapis.com/codeskulptor-assets/lathrop/splash.png") | |
# ship image | |
ship_info = ImageInfo([45, 45], [90, 90], 35) | |
ship_image = simplegui.load_image("http://commondatastorage.googleapis.com/codeskulptor-assets/lathrop/double_ship.png") | |
# missile image - shot1.png, shot2.png, shot3.png | |
missile_info = ImageInfo([5,5], [10, 10], 3, 50) | |
missile_image = simplegui.load_image("http://commondatastorage.googleapis.com/codeskulptor-assets/lathrop/shot2.png") | |
# asteroid images - asteroid_blue.png, asteroid_brown.png, asteroid_blend.png | |
asteroid_info = ImageInfo([45, 45], [90, 90], 40) | |
asteroid_image = simplegui.load_image("http://commondatastorage.googleapis.com/codeskulptor-assets/lathrop/asteroid_blue.png") | |
# animated explosion - explosion_orange.png, explosion_blue.png, explosion_blue2.png, explosion_alpha.png | |
explosion_info = ImageInfo([64, 64], [128, 128], 17, 24, True) | |
explosion_image = simplegui.load_image("http://commondatastorage.googleapis.com/codeskulptor-assets/lathrop/explosion_alpha.png") | |
# sound assets purchased from sounddogs.com, please do not redistribute | |
# .ogg versions of sounds are also available, just replace .mp3 by .ogg | |
soundtrack = simplegui.load_sound("http://commondatastorage.googleapis.com/codeskulptor-assets/sounddogs/soundtrack.mp3") | |
missile_sound = simplegui.load_sound("http://commondatastorage.googleapis.com/codeskulptor-assets/sounddogs/missile.mp3") | |
missile_sound.set_volume(.5) | |
ship_thrust_sound = simplegui.load_sound("http://commondatastorage.googleapis.com/codeskulptor-assets/sounddogs/thrust.mp3") | |
explosion_sound = simplegui.load_sound("http://commondatastorage.googleapis.com/codeskulptor-assets/sounddogs/explosion.mp3") | |
# helper functions to handle transformations | |
def angle_to_vector(ang): | |
return [math.cos(ang), math.sin(ang)] | |
def dist(p, q): | |
return math.sqrt((p[0] - q[0]) ** 2 + (p[1] - q[1]) ** 2) | |
# Ship class | |
class Ship: | |
def __init__(self, pos, vel, angle, image, info): | |
self.pos = [pos[0], pos[1]] | |
self.vel = [vel[0], vel[1]] | |
self.thrust = False | |
self.angle = angle | |
self.angle_vel = 0 | |
self.image = image | |
self.image_center = info.get_center() | |
self.image_size = info.get_size() | |
self.radius = info.get_radius() | |
def get_position(self): | |
return self.pos | |
def get_radius(self): | |
return self.radius | |
def draw(self,canvas): | |
if self.thrust: | |
canvas.draw_image(self.image, [self.image_center[0] + self.image_size[0], self.image_center[1]] , self.image_size, | |
self.pos, self.image_size, self.angle) | |
else: | |
canvas.draw_image(self.image, self.image_center, self.image_size, | |
self.pos, self.image_size, self.angle) | |
# canvas.draw_circle(self.pos, self.radius, 1, "White", "White") | |
def update(self): | |
# update angle | |
self.angle += self.angle_vel | |
# update position | |
self.pos[0] = (self.pos[0] + self.vel[0]) % WIDTH | |
self.pos[1] = (self.pos[1] + self.vel[1]) % HEIGHT | |
# update velocity | |
if self.thrust: | |
acc = angle_to_vector(self.angle) | |
self.vel[0] += acc[0] * .1 | |
self.vel[1] += acc[1] * .1 | |
self.vel[0] *= .99 | |
self.vel[1] *= .99 | |
def set_thrust(self, on): | |
self.thrust = on | |
if on: | |
ship_thrust_sound.rewind() | |
ship_thrust_sound.play() | |
else: | |
ship_thrust_sound.pause() | |
def increment_angle_vel(self): | |
self.angle_vel += .05 | |
def decrement_angle_vel(self): | |
self.angle_vel -= .05 | |
def shoot(self): | |
global missile_group | |
forward = angle_to_vector(self.angle) | |
missile_pos = [self.pos[0] + self.radius * forward[0], self.pos[1] + self.radius * forward[1]] | |
missile_vel = [self.vel[0] + 6 * forward[0], self.vel[1] + 6 * forward[1]] | |
a_missile = Sprite(missile_pos, missile_vel, self.angle, 0, missile_image, missile_info, missile_sound) | |
missile_group.add(a_missile) | |
# Sprite class | |
class Sprite: | |
def __init__(self, pos, vel, ang, ang_vel, image, info, sound = None): | |
self.pos = [pos[0],pos[1]] | |
self.vel = [vel[0],vel[1]] | |
self.angle = ang | |
self.angle_vel = ang_vel | |
self.image = image | |
self.image_center = info.get_center() | |
self.image_size = info.get_size() | |
self.radius = info.get_radius() | |
self.lifespan = info.get_lifespan() | |
self.animated = info.get_animated() | |
self.age = 0 | |
if sound: | |
sound.rewind() | |
sound.play() | |
def get_position(self): | |
return self.pos | |
def get_radius(self): | |
return self.radius | |
def draw(self, canvas): | |
canvas.draw_image(self.image, self.image_center, self.image_size, | |
self.pos, self.image_size, self.angle) | |
def update(self): | |
# update angle | |
self.angle += self.angle_vel | |
# update position | |
self.pos[0] = (self.pos[0] + self.vel[0]) % WIDTH | |
self.pos[1] = (self.pos[1] + self.vel[1]) % HEIGHT | |
# update age | |
self.age += 1 | |
if self.lifespan and self.age >= self.lifespan: | |
return True | |
else: | |
return False | |
def collide(self, other_object): | |
distance = dist(self.get_position(), other_object.get_position()) | |
min_distance = self.get_radius() + other_object.get_radius() | |
if(distance < min_distance): | |
return True | |
else: | |
return False | |
# key handlers to control ship | |
def keydown(key): | |
if key == simplegui.KEY_MAP['left']: | |
my_ship.decrement_angle_vel() | |
elif key == simplegui.KEY_MAP['right']: | |
my_ship.increment_angle_vel() | |
elif key == simplegui.KEY_MAP['up']: | |
my_ship.set_thrust(True) | |
elif key == simplegui.KEY_MAP['space']: | |
my_ship.shoot() | |
def keyup(key): | |
if key == simplegui.KEY_MAP['left']: | |
my_ship.increment_angle_vel() | |
elif key == simplegui.KEY_MAP['right']: | |
my_ship.decrement_angle_vel() | |
elif key == simplegui.KEY_MAP['up']: | |
my_ship.set_thrust(False) | |
# mouseclick handlers that reset UI and conditions whether splash image is drawn | |
def click(pos): | |
global started | |
global lives, score | |
center = [WIDTH / 2, HEIGHT / 2] | |
size = splash_info.get_size() | |
inwidth = (center[0] - size[0] / 2) < pos[0] < (center[0] + size[0] / 2) | |
inheight = (center[1] - size[1] / 2) < pos[1] < (center[1] + size[1] / 2) | |
if (not started) and inwidth and inheight: | |
started = True | |
lives = 3 | |
score = 0 | |
#soundtrack.play() | |
def process_sprite_group(canvas, sprite_group): | |
for sprite in set(sprite_group): | |
sprite.draw(canvas) | |
update = sprite.update() | |
if update: | |
sprite_group.remove(sprite) | |
def group_collide(group, other_object): | |
for sprite in set(group): | |
collide = sprite.collide(other_object) | |
if collide: | |
group.remove(sprite) | |
return True | |
return False | |
# return the number of elements in the first group that collide with the second group as well as delete these elements in the first group | |
def group_group_collide(group1, group2): | |
count = 0 | |
for sprite in set(group1): | |
if group_collide(group2, sprite): | |
group1.discard(sprite) | |
count += 1 | |
return count | |
def draw(canvas): | |
global time, started | |
global lives, score | |
global rock_group | |
# animiate background | |
time += 1 | |
wtime = (time / 4) % WIDTH | |
center = debris_info.get_center() | |
size = debris_info.get_size() | |
canvas.draw_image(nebula_image, nebula_info.get_center(), nebula_info.get_size(), [WIDTH / 2, HEIGHT / 2], [WIDTH, HEIGHT]) | |
canvas.draw_image(debris_image, center, size, (wtime - WIDTH / 2, HEIGHT / 2), (WIDTH, HEIGHT)) | |
canvas.draw_image(debris_image, center, size, (wtime + WIDTH / 2, HEIGHT / 2), (WIDTH, HEIGHT)) | |
# draw UI | |
canvas.draw_text("Lives", [50, 50], 22, "White") | |
canvas.draw_text("Score", [680, 50], 22, "White") | |
canvas.draw_text(str(lives), [50, 80], 22, "White") | |
canvas.draw_text(str(score), [680, 80], 22, "White") | |
# draw ship and sprites | |
my_ship.draw(canvas) | |
process_sprite_group(canvas, rock_group) | |
#a_rock.draw(canvas) | |
process_sprite_group(canvas, missile_group) | |
# update ship and sprites | |
my_ship.update() | |
#a_rock.update() | |
#a_missile.update() | |
if group_collide(rock_group, my_ship): | |
lives -= 1 | |
if lives == 0: | |
rock_group = set() | |
started = False | |
score += group_group_collide(rock_group, missile_group) | |
# draw splash screen if not started | |
if not started: | |
canvas.draw_image(splash_image, splash_info.get_center(), | |
splash_info.get_size(), [WIDTH / 2, HEIGHT / 2], | |
splash_info.get_size()) | |
soundtrack.rewind() | |
# timer handler that spawns a rock | |
def rock_spawner(): | |
global rock_group | |
rock_pos = [random.randrange(0, WIDTH), random.randrange(0, HEIGHT)] | |
level = score * 0.05 + 2 | |
rock_vel = [random.random() * level - level/2, random.random() * level - level/2] | |
rock_avel = random.random() * .2 - .1 | |
#a_rock = Sprite(rock_pos, rock_vel, 0, rock_avel, asteroid_image, asteroid_info) | |
min_distance = asteroid_info.get_radius() + my_ship.get_radius() + 20 | |
distance = dist(rock_pos, my_ship.get_position()) | |
if started and distance >= min_distance and len(rock_group) < 12: | |
a_rock = Sprite(rock_pos, rock_vel, 0, rock_avel, asteroid_image, asteroid_info) | |
rock_group.add(a_rock) | |
# initialize stuff | |
frame = simplegui.create_frame("Asteroids", WIDTH, HEIGHT) | |
# initialize ship and two sprites | |
my_ship = Ship([WIDTH / 2, HEIGHT / 2], [0, 0], 0, ship_image, ship_info) | |
#a_rock = Sprite([WIDTH / 3, HEIGHT / 3], [1, 1], 0, .1, asteroid_image, asteroid_info) | |
rock_group = set() | |
#a_missile = Sprite([2 * WIDTH / 3, 2 * HEIGHT / 3], [-1,1], 0, 0, missile_image, missile_info, missile_sound) | |
missile_group = set() | |
# register handlers | |
frame.set_keyup_handler(keyup) | |
frame.set_keydown_handler(keydown) | |
frame.set_mouseclick_handler(click) | |
frame.set_draw_handler(draw) | |
timer = simplegui.create_timer(1000.0, rock_spawner) | |
# get things rolling | |
timer.start() | |
frame.start() |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
# Try on http://www.codeskulptor.org/#user38_W4j2BUtRB8_6.py | |
# implementation of Spaceship - program template for RiceRocks | |
import simplegui | |
import math | |
import random | |
# globals for user interface | |
WIDTH = 800 | |
HEIGHT = 600 | |
score = 0 | |
lives = 3 | |
time = 0 | |
started = False | |
rock_group = set() | |
missile_group = set() | |
explosion_group = set() | |
ship_explosion = 0 | |
class ImageInfo: | |
def __init__(self, center, size, radius = 0, lifespan = None, animated = False): | |
self.center = center | |
self.size = size | |
self.radius = radius | |
if lifespan: | |
self.lifespan = lifespan | |
else: | |
self.lifespan = float('inf') | |
self.animated = animated | |
def get_center(self): | |
return self.center | |
def get_size(self): | |
return self.size | |
def get_radius(self): | |
return self.radius | |
def get_lifespan(self): | |
return self.lifespan | |
def get_animated(self): | |
return self.animated | |
# art assets created by Kim Lathrop, may be freely re-used in non-commercial projects, please credit Kim | |
# debris images - debris1_brown.png, debris2_brown.png, debris3_brown.png, debris4_brown.png | |
# debris1_blue.png, debris2_blue.png, debris3_blue.png, debris4_blue.png, debris_blend.png | |
debris_info = ImageInfo([320, 240], [640, 480]) | |
debris_image = simplegui.load_image("http://commondatastorage.googleapis.com/codeskulptor-assets/lathrop/debris2_blue.png") | |
# nebula images - nebula_brown.png, nebula_blue.png | |
nebula_info = ImageInfo([400, 300], [800, 600]) | |
nebula_image = simplegui.load_image("http://commondatastorage.googleapis.com/codeskulptor-assets/lathrop/nebula_blue.f2014.png") | |
# splash image | |
splash_info = ImageInfo([200, 150], [400, 300]) | |
splash_image = simplegui.load_image("http://commondatastorage.googleapis.com/codeskulptor-assets/lathrop/splash.png") | |
# ship image | |
ship_info = ImageInfo([45, 45], [90, 90], 35) | |
ship_image = simplegui.load_image("http://commondatastorage.googleapis.com/codeskulptor-assets/lathrop/double_ship.png") | |
# missile image - shot1.png, shot2.png, shot3.png | |
missile_info = ImageInfo([5,5], [10, 10], 3, 50) | |
missile_image = simplegui.load_image("http://commondatastorage.googleapis.com/codeskulptor-assets/lathrop/shot2.png") | |
# asteroid images - asteroid_blue.png, asteroid_brown.png, asteroid_blend.png | |
asteroid_info = ImageInfo([45, 45], [90, 90], 40) | |
asteroid_image = simplegui.load_image("http://commondatastorage.googleapis.com/codeskulptor-assets/lathrop/asteroid_blue.png") | |
# animated explosion - explosion_orange.png, explosion_blue.png, explosion_blue2.png, explosion_alpha.png | |
explosion_info = ImageInfo([64, 64], [128, 128], 17, 24, True) | |
explosion_image = simplegui.load_image("http://commondatastorage.googleapis.com/codeskulptor-assets/lathrop/explosion_alpha.png") | |
ship_explosion_info = ImageInfo([50, 50], [100, 100], 25, 74, True) | |
ship_explosion_image = simplegui.load_image("http://commondatastorage.googleapis.com/codeskulptor-assets/explosion.hasgraphics.png") | |
# sound assets purchased from sounddogs.com, please do not redistribute | |
# .ogg versions of sounds are also available, just replace .mp3 by .ogg | |
soundtrack = simplegui.load_sound("http://commondatastorage.googleapis.com/codeskulptor-assets/sounddogs/soundtrack.mp3") | |
missile_sound = simplegui.load_sound("http://commondatastorage.googleapis.com/codeskulptor-assets/sounddogs/missile.mp3") | |
missile_sound.set_volume(.5) | |
ship_thrust_sound = simplegui.load_sound("http://commondatastorage.googleapis.com/codeskulptor-assets/sounddogs/thrust.mp3") | |
explosion_sound = simplegui.load_sound("http://commondatastorage.googleapis.com/codeskulptor-assets/sounddogs/explosion.mp3") | |
# helper functions to handle transformations | |
def angle_to_vector(ang): | |
return [math.cos(ang), math.sin(ang)] | |
def dist(p, q): | |
return math.sqrt((p[0] - q[0]) ** 2 + (p[1] - q[1]) ** 2) | |
def process_sprite_group(canvas, current_group): | |
for element in set(current_group): | |
element.draw(canvas) | |
if element.update(): | |
current_group.remove(element) | |
def group_collide(group, other_object): | |
for element in set(group): | |
if element.collide(other_object): | |
group.discard(element) | |
explosion = Sprite(element.get_position(), [0, 0], 0, 0, explosion_image, explosion_info, explosion_sound) | |
explosion_group.add(explosion) | |
if other_object == my_ship: | |
explosion = Sprite(other_object.get_position(), [0, 0], 0, 0, ship_explosion_image, ship_explosion_info, explosion_sound) | |
explosion_group.add(explosion) | |
return True | |
return False | |
def group_group_collide(group1, group2): | |
count_collides = 0 | |
for element in set(group1): | |
if group_collide(group2, element): | |
group1.discard(element) | |
count_collides += 1 | |
return count_collides | |
# Ship class | |
class Ship: | |
def __init__(self, pos, vel, angle, image, info): | |
self.pos = [pos[0], pos[1]] | |
self.vel = [vel[0], vel[1]] | |
self.thrust = False | |
self.angle = angle | |
self.angle_vel = 0 | |
self.image = image | |
self.image_center = info.get_center() | |
self.image_size = info.get_size() | |
self.radius = info.get_radius() | |
def draw(self,canvas): | |
if self.thrust: | |
canvas.draw_image(self.image, [self.image_center[0] + self.image_size[0], self.image_center[1]] , self.image_size, | |
self.pos, self.image_size, self.angle) | |
else: | |
canvas.draw_image(self.image, self.image_center, self.image_size, | |
self.pos, self.image_size, self.angle) | |
def update(self): | |
# update angle | |
self.angle += self.angle_vel | |
# update position | |
self.pos[0] = (self.pos[0] + self.vel[0]) % WIDTH | |
self.pos[1] = (self.pos[1] + self.vel[1]) % HEIGHT | |
# update velocity | |
if self.thrust: | |
acc = angle_to_vector(self.angle) | |
self.vel[0] += acc[0] * .3 | |
self.vel[1] += acc[1] * .3 | |
self.vel[0] *= .98 | |
self.vel[1] *= .98 | |
def set_thrust(self, on): | |
self.thrust = on | |
if on: | |
ship_thrust_sound.rewind() | |
ship_thrust_sound.play() | |
else: | |
ship_thrust_sound.pause() | |
def increment_angle_vel(self): | |
self.angle_vel += .1 | |
def decrement_angle_vel(self): | |
self.angle_vel -= .1 | |
def shoot(self): | |
global missile_group | |
forward = angle_to_vector(self.angle) | |
missile_pos = [self.pos[0] + self.radius * forward[0], self.pos[1] + self.radius * forward[1]] | |
missile_vel = [self.vel[0] + 6 * forward[0], self.vel[1] + 6 * forward[1]] | |
a_missile = Sprite(missile_pos, missile_vel, self.angle, 0, missile_image, missile_info, missile_sound) | |
missile_group.add(a_missile) | |
def get_position(self): | |
return self.pos | |
def get_radius(self): | |
return self.radius | |
# Sprite class | |
class Sprite: | |
def __init__(self, pos, vel, ang, ang_vel, image, info, sound = None): | |
self.pos = [pos[0],pos[1]] | |
self.vel = [vel[0],vel[1]] | |
self.angle = ang | |
self.angle_vel = ang_vel | |
self.image = image | |
self.image_center = info.get_center() | |
self.image_size = info.get_size() | |
self.radius = info.get_radius() | |
self.lifespan = info.get_lifespan() | |
self.animated = info.get_animated() | |
self.age = 0 | |
if sound: | |
sound.rewind() | |
sound.play() | |
def draw(self, canvas): | |
global ship_explosion_image | |
if self.animated: | |
if self.image == ship_explosion_image: | |
dim = [9, 9] | |
explosion_index = [self.age % dim[0], (self.age // dim[0]) % dim[1]] | |
canvas.draw_image(self.image, | |
[self.image_center[0] + explosion_index[0] * self.image_size[0], | |
self.image_center[1] + explosion_index[1] * self.image_size[1]], | |
self.image_size, self.pos, self.image_size, self.angle) | |
else: | |
index = (self.age % 25) // 1 | |
current_item_center = [self.image_center[0] + index * self.image_size[0], self.image_center[1]] | |
canvas.draw_image(self.image, current_item_center, self.image_size, | |
self.pos, self.image_size, self.angle) | |
else: | |
canvas.draw_image(self.image, self.image_center, self.image_size, | |
self.pos, self.image_size, self.angle) | |
def get_position(self): | |
return self.pos | |
def get_radius(self): | |
return self.radius | |
def collide(self, other_object): | |
distance = dist(self.pos, other_object.get_position()) | |
if distance < self.radius + other_object.get_radius(): | |
return True | |
return False | |
def update(self): | |
# update angle | |
self.angle += self.angle_vel | |
self.age += 1 | |
# update position | |
self.pos[0] = (self.pos[0] + self.vel[0]) % WIDTH | |
self.pos[1] = (self.pos[1] + self.vel[1]) % HEIGHT | |
if self.age > self.lifespan: | |
return True | |
return False | |
# key handlers to control ship | |
def keydown(key): | |
if key == simplegui.KEY_MAP['left']: | |
my_ship.decrement_angle_vel() | |
elif key == simplegui.KEY_MAP['right']: | |
my_ship.increment_angle_vel() | |
elif key == simplegui.KEY_MAP['up']: | |
my_ship.set_thrust(True) | |
elif key == simplegui.KEY_MAP['space']: | |
my_ship.shoot() | |
missile_timer.start() | |
def keyup(key): | |
if key == simplegui.KEY_MAP['left']: | |
my_ship.increment_angle_vel() | |
elif key == simplegui.KEY_MAP['right']: | |
my_ship.decrement_angle_vel() | |
elif key == simplegui.KEY_MAP['up']: | |
my_ship.set_thrust(False) | |
elif key == simplegui.KEY_MAP['space']: | |
missile_timer.stop() | |
# mouseclick handlers that reset UI and conditions whether splash image is drawn | |
def click(pos): | |
global started, lives, score | |
lives = 3 | |
score = 0 | |
time = 0 | |
soundtrack.play() | |
center = [WIDTH / 2, HEIGHT / 2] | |
size = splash_info.get_size() | |
inwidth = (center[0] - size[0] / 2) < pos[0] < (center[0] + size[0] / 2) | |
inheight = (center[1] - size[1] / 2) < pos[1] < (center[1] + size[1] / 2) | |
if (not started) and inwidth and inheight: | |
started = True | |
def draw(canvas): | |
global time, started, lives, rock_group, missile_group, score | |
# animiate background | |
time += 1 | |
wtime = (time / 4) % WIDTH | |
center = debris_info.get_center() | |
size = debris_info.get_size() | |
canvas.draw_image(nebula_image, nebula_info.get_center(), nebula_info.get_size(), [WIDTH / 2, HEIGHT / 2], [WIDTH, HEIGHT]) | |
canvas.draw_image(debris_image, center, size, (wtime - WIDTH / 2, HEIGHT / 2), (WIDTH, HEIGHT)) | |
canvas.draw_image(debris_image, center, size, (wtime + WIDTH / 2, HEIGHT / 2), (WIDTH, HEIGHT)) | |
if group_collide(rock_group, my_ship): | |
lives -= 1 | |
score += group_group_collide(missile_group, rock_group) * 10 | |
# draw UI | |
canvas.draw_text("Lives", [50, 50], 22, "White") | |
canvas.draw_text("Score", [680, 50], 22, "White") | |
canvas.draw_text(str(lives), [50, 80], 22, "White") | |
canvas.draw_text(str(score), [680, 80], 22, "White") | |
# draw ship and sprites | |
my_ship.draw(canvas) | |
process_sprite_group(canvas, rock_group) | |
process_sprite_group(canvas, missile_group) | |
process_sprite_group(canvas, explosion_group) | |
# update ship and sprites | |
my_ship.update() | |
if lives == 0: | |
started = False | |
missile_group = set([]) | |
rock_group = set([]) | |
# draw splash screen if not started | |
if not started: | |
soundtrack.rewind() | |
canvas.draw_image(splash_image, splash_info.get_center(), | |
splash_info.get_size(), [WIDTH / 2, HEIGHT / 2], | |
splash_info.get_size()) | |
# timer handler that spawns a rock | |
def rock_spawner(): | |
global rock_group | |
if started: | |
rock_pos = [random.randrange(0, WIDTH), random.randrange(0, HEIGHT)] | |
compl = score // 100 | |
rock_vel = [(random.random() * .6 - .3) * compl, (random.random() * .6 - .3) * compl] | |
rock_avel = random.random() * .2 - .1 | |
a_rock = Sprite(rock_pos, rock_vel, 0, rock_avel, asteroid_image, asteroid_info) | |
distance = dist(rock_pos, my_ship.get_position()) | |
rock_radius = a_rock.get_radius() | |
ship_radius = my_ship.get_radius() | |
if len(rock_group) < 12 and distance > rock_radius + ship_radius + 50: | |
rock_group.add(a_rock) | |
# initialize stuff | |
frame = simplegui.create_frame("Asteroids", WIDTH, HEIGHT) | |
# initialize ship and two sprites | |
my_ship = Ship([WIDTH / 2, HEIGHT / 2], [0, 0], 0, ship_image, ship_info) | |
# register handlers | |
frame.set_keyup_handler(keyup) | |
frame.set_keydown_handler(keydown) | |
frame.set_mouseclick_handler(click) | |
frame.set_draw_handler(draw) | |
soundtrack.rewind() | |
timer = simplegui.create_timer(1000.0, rock_spawner) | |
missile_timer = simplegui.create_timer(100.0, my_ship.shoot) | |
# get things rolling | |
timer.start() | |
frame.start() |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
# Try on http://www.codeskulptor.org/#user38_Zn4zZe4XFt_4.py | |
# template for "Stopwatch: The Game" | |
import simplegui | |
import time | |
# define global variables | |
curr = 0 | |
running = False | |
x = 0 | |
y = 0 | |
# define helper function format that converts time | |
# in tenths of seconds into formatted string A:BC.D | |
def format(t): | |
d = t%10 | |
a = t/600 | |
bc = (t-a*600)/10 | |
if bc <10: | |
bc_str = '0' + str(bc) | |
else: | |
bc_str = str(bc) | |
return str(a)+':'+ bc_str +'.'+str(d) | |
# define event handlers for buttons; "Start", "Stop", "Reset" | |
def start(): | |
global running | |
running = True | |
def stop(): | |
global running, x, y | |
if running: | |
y += 1 | |
if curr % 10 == 0: | |
x += 1 | |
running = False | |
def reset(): | |
global curr, running, x, y | |
curr = 0 | |
x = 0 | |
y = 0 | |
running = False | |
# define event handler for timer with 0.1 sec interval | |
def update(): | |
global curr | |
if running: | |
curr += 1 | |
# define draw handler | |
def draw_handler(canvas): | |
global curr | |
canvas.draw_text(format(curr),[100, 100], 34, "Green") | |
canvas.draw_text(str(x) + '/' + str(y),[250, 30], 24, "White") | |
# create frame | |
frame = simplegui.create_frame("Stopwatch: The Game", 300, 200) | |
# register event handlers | |
frame.set_draw_handler(draw_handler) | |
frame.add_button("Start", start, 100) | |
frame.add_button("Stop", stop, 100) | |
frame.add_button("Reset", reset, 100) | |
timer = simplegui.create_timer(100, update) | |
# start frame | |
frame.start() | |
timer.start() | |
# Please remember to review the grading rubric |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment