Last active
August 29, 2015 14:02
-
-
Save xjimtim/a1894ca4fe0215b4fe11 to your computer and use it in GitHub Desktop.
This file contains 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
import random, sys, time, math, pygame | |
from pygame.locals import * | |
變數 = 30 | |
螢幕高 = 640 # width of the program's window, in pixels | |
螢幕寬 = 480 # height in pixels | |
螢幕半高 = int(螢幕高 / 2) | |
螢幕半寬 = int(螢幕寬 / 2) | |
草野幽色 = (24, 255, 0) | |
白 = (255, 255, 255) | |
紅 = (255, 0, 0) | |
距離 = 90 # how far from the center the squirrel moves before moving the camera | |
移動速度 = 9 # how fast the player moves | |
成長速度 = 6 # how fast the player bounces (large is slower) | |
得分 = 30 # how high the player bounces | |
原始大小 = 25 # how big the player starts off | |
最後大小 = 300 # how big the player needs to be to win | |
無敵秒數 = 2 # how long the player is invulnerable after being hit in seconds | |
結束遊戲 = 4 # how long the "game over" text stays on the screen in seconds | |
血量上限 = 3 # how much health the player starts with | |
草野幽地數 = 80 # number of grass objects in the active area | |
丁丁密度 = 30 # number of squirrels in the active area | |
最慢速度 = 3 # slowest squirrel speed | |
最快速度 = 7 # fastest squirrel speed | |
變向 = 2 # % chance of direction change per frame | |
左 = 'left' | |
右 = 'right' | |
""" | |
This program has three data structures to represent the player, enemy squirrels, and grass background objects. The data structures are dictionaries with the following keys: | |
Keys used by all three data structures: | |
'甲' - the left edge coordinate of the object in the game world (not a pixel coordinate on the screen) | |
'乙' - the top edge coordinate of the object in the game world (not a pixel coordinate on the screen) | |
'rect' - the pygame.Rect object representing where on the screen the object is located. | |
Player data structure keys: | |
'surface' - the pygame.Surface object that stores the image of the squirrel which will be drawn to the screen. | |
'facing' - either set to 左 or 右, stores which direction the player is facing. | |
'size' - the width and height of the player in pixels. (The width & height are always the same.) | |
'bounce' - represents at what point in a bounce the player is in. 0 means standing (no bounce), up to 成長速度 (the completion of the bounce) | |
'health' - an integer showing how many more times the player can be hit by a larger squirrel before dying. | |
Enemy Squirrel data structure keys: | |
'surface' - the pygame.Surface object that stores the image of the squirrel which will be drawn to the screen. | |
'movex' - how many pixels per frame the squirrel moves horizontally. A negative integer is moving to the left, a positive to the right. | |
'movey' - how many pixels per frame the squirrel moves vertically. A negative integer is moving up, a positive moving down. | |
'width' - the width of the squirrel's image, in pixels | |
'height' - the height of the squirrel's image, in pixels | |
'bounce' - represents at what point in a bounce the player is in. 0 means standing (no bounce), up to 成長速度 (the completion of the bounce) | |
'成長速度' - how quickly the squirrel bounces. A lower number means a quicker bounce. | |
'得分' - how high (in pixels) the squirrel bounces | |
Grass data structure keys: | |
'grassImage' - an integer that refers to the index of the pygame.Surface object in 草野幽圖 used for this grass object | |
""" | |
def main(): | |
global 變數時, 顯示, 基本字體, 左圖片, 右圖片, 草野幽圖 | |
pygame.init() | |
變數時 = pygame.time.Clock() | |
pygame.display.set_icon(pygame.image.load('gameicon.png')) | |
顯示 = pygame.display.set_mode((螢幕高, 螢幕寬)) | |
pygame.display.set_caption('Squirrel Eat Squirrel') | |
基本字體 = pygame.font.Font('freesansbold.ttf', 32) | |
# load the image files | |
左圖片 = pygame.image.load('squirrel.png') | |
右圖片 = pygame.transform.flip(左圖片, True, False) | |
草野幽圖 = [] | |
for 丁 in range(1, 5): | |
草野幽圖.append(pygame.image.load('grass%s.png' % 丁)) | |
while True: | |
開始遊戲() | |
def 開始遊戲(): | |
# set up variables for the start of a new game | |
無敵狀態 = False # if the player is invulnerable | |
無敵時間 = 0 # time the player became invulnerable | |
結束狀態 = False # if the player has lost | |
結束時間 = 0 # time the player lost | |
勝利狀態 = False # if the player has won | |
# create the surfaces to hold game text | |
遊戲結束字體 = 基本字體.render('Game Over', True, 白) | |
遊戲結束反映 = 遊戲結束字體.get_rect() | |
遊戲結束反映.center = (螢幕半高, 螢幕半寬) | |
勝利字體 = 基本字體.render('You have achieved OMEGA SQUIRREL!', True, 白) | |
勝利反映 = 勝利字體.get_rect() | |
勝利反映.center = (螢幕半高, 螢幕半寬) | |
勝利字體2 = 基本字體.render('(Press "r" to restart.)', True, 白) | |
勝利反映2 = 勝利字體2.get_rect() | |
勝利反映2.center = (螢幕半高, 螢幕半寬 + 30) | |
# 相機甲 and 相機乙 are the top left of where the camera view is | |
相機甲 = 0 | |
相機乙 = 0 | |
草野幽地物件 = [] # stores all the grass objects in the game | |
丁丁物件 = [] # stores all the non-player squirrel objects | |
# stores the player object: | |
玩家丁丁 = {'表面': pygame.transform.scale(左圖片, (原始大小, 原始大小)), | |
'面朝': 左, | |
'尺寸': 原始大小, | |
'甲': 螢幕半高, | |
'乙': 螢幕半寬, | |
'成長':0, | |
'血量': 血量上限} | |
左移 = False | |
右移 = False | |
上移 = False | |
下移 = False | |
# start off with some random grass images on the screen | |
for 丁 in range(10): | |
草野幽地物件.append(建草野幽地(相機甲, 相機乙)) | |
草野幽地物件[丁]['甲'] = random.randint(0, 螢幕高) | |
草野幽地物件[丁]['乙'] = random.randint(0, 螢幕寬) | |
while True: # main game loop | |
# Check if we should turn off invulnerability | |
if 無敵狀態 and time.time() - 無敵時間 > 無敵秒數: | |
無敵狀態 = False | |
# move all the squirrels | |
for 己物體 in 丁丁物件: | |
# move the squirrel, and adjust for their bounce | |
己物體['甲'] += 己物體['移動量x'] | |
己物體['乙'] += 己物體['移動量y'] | |
己物體['成長'] += 1 | |
if 己物體['成長'] > 己物體['成長速度']: | |
己物體['成長'] = 0 # reset bounce amount | |
# random chance they change direction | |
if random.randint(0, 99) < 變向: | |
己物體['移動量x'] = 隨機速度() | |
己物體['移動量y'] = 隨機速度() | |
if 己物體['移動量x'] > 0: # faces right | |
己物體['表面'] = pygame.transform.scale(右圖片, (己物體['寬'], 己物體['高'])) | |
else: # faces left | |
己物體['表面'] = pygame.transform.scale(左圖片, (己物體['寬'], 己物體['高'])) | |
# go through all the objects and see if any need to be deleted. | |
for 丁 in range(len(草野幽地物件) - 1, -1, -1): | |
if 林老師你好(相機甲, 相機乙, 草野幽地物件[丁]): | |
del 草野幽地物件[丁] | |
for 丁 in range(len(丁丁物件) - 1, -1, -1): | |
if 林老師你好(相機甲, 相機乙, 丁丁物件[丁]): | |
del 丁丁物件[丁] | |
# add more grass & squirrels if we don't have enough. | |
while len(草野幽地物件) < 草野幽地數: | |
草野幽地物件.append(建草野幽地(相機甲, 相機乙)) | |
while len(丁丁物件) < 丁丁密度: | |
丁丁物件.append(創造新丁丁(相機甲, 相機乙)) | |
# adjust 相機甲 and 相機乙 if beyond the "camera slack" | |
玩家x座標 = 玩家丁丁['甲'] + int(玩家丁丁['尺寸'] / 2) | |
玩家y座標 = 玩家丁丁['乙'] + int(玩家丁丁['尺寸'] / 2) | |
if (相機甲 + 螢幕半高) - 玩家x座標 > 距離: | |
相機甲 = 玩家x座標 + 距離 - 螢幕半高 | |
elif 玩家x座標 - (相機甲 + 螢幕半高) > 距離: | |
相機甲 = 玩家x座標 - 距離 - 螢幕半高 | |
if (相機乙 + 螢幕半寬) - 玩家y座標 > 距離: | |
相機乙 = 玩家y座標 + 距離 - 螢幕半寬 | |
elif 玩家y座標 - (相機乙 + 螢幕半寬) > 距離: | |
相機乙 = 玩家y座標 - 距離 - 螢幕半寬 | |
# draw the green background | |
顯示.fill(草野幽色) | |
# draw all the grass objects on the screen | |
for 庚物體 in 草野幽地物件: | |
gRect = pygame.Rect( (庚物體['甲'] - 相機甲, | |
庚物體['乙'] - 相機乙, | |
庚物體['寬'], | |
庚物體['高']) ) | |
顯示.blit(草野幽圖[庚物體['草野幽地模樣']], gRect) | |
# draw the other squirrels | |
for 己物體 in 丁丁物件: | |
己物體['rect'] = pygame.Rect( (己物體['甲'] - 相機甲, | |
己物體['乙'] - 相機乙 - 得分機制(己物體['成長'], 己物體['成長速度'], 己物體['得分']), | |
己物體['寬'], | |
己物體['高']) ) | |
顯示.blit(己物體['表面'], 己物體['rect']) | |
# draw the player squirrel | |
無敵啟動 = round(time.time(), 1) * 10 % 2 == 1 | |
if not 結束狀態 and not (無敵狀態 and 無敵啟動): | |
玩家丁丁['rect'] = pygame.Rect( (玩家丁丁['甲'] - 相機甲, | |
玩家丁丁['乙'] - 相機乙 - 得分機制(玩家丁丁['成長'], 成長速度, 得分), | |
玩家丁丁['尺寸'], | |
玩家丁丁['尺寸']) ) | |
顯示.blit(玩家丁丁['表面'], 玩家丁丁['rect']) | |
# draw the 血量 meter | |
畫血條(玩家丁丁['血量']) | |
for event in pygame.event.get(): # event handling loop | |
if event.type == QUIT: | |
終止() | |
elif event.type == KEYDOWN: | |
if event.key in (K_UP, K_w): | |
下移 = False | |
上移 = True | |
elif event.key in (K_DOWN, K_s): | |
上移 = False | |
下移 = True | |
elif event.key in (K_LEFT, K_a): | |
右移 = False | |
左移 = True | |
if 玩家丁丁['面朝'] != 左: # change player image | |
玩家丁丁['表面'] = pygame.transform.scale(左圖片, (玩家丁丁['尺寸'], 玩家丁丁['尺寸'])) | |
玩家丁丁['面朝'] = 左 | |
elif event.key in (K_RIGHT, K_d): | |
左移 = False | |
右移 = True | |
if 玩家丁丁['面朝'] != 右: # change player image | |
玩家丁丁['表面'] = pygame.transform.scale(右圖片, (玩家丁丁['尺寸'], 玩家丁丁['尺寸'])) | |
玩家丁丁['面朝'] = 右 | |
elif 結束時間 and event.key == K_r: | |
return | |
elif event.type == KEYUP: | |
# stop moving the player's squirrel | |
if event.key in (K_LEFT, K_a): | |
左移 = False | |
elif event.key in (K_RIGHT, K_d): | |
右移 = False | |
elif event.key in (K_UP, K_w): | |
上移 = False | |
elif event.key in (K_DOWN, K_s): | |
下移 = False | |
elif event.key == K_ESCAPE: | |
終止() | |
if not 結束狀態: | |
# actually move the player | |
if 左移: | |
玩家丁丁['甲'] -= 移動速度 | |
if 右移: | |
玩家丁丁['甲'] += 移動速度 | |
if 上移: | |
玩家丁丁['乙'] -= 移動速度 | |
if 下移: | |
玩家丁丁['乙'] += 移動速度 | |
if (上移 or 右移 or 左移 or 右移) or 玩家丁丁['成長'] != 0: | |
玩家丁丁['成長'] += 1 | |
if 玩家丁丁['成長'] > 成長速度: | |
玩家丁丁['成長'] = 0 # reset bounce amount | |
# check if the player has collided with any squirrels | |
for 丁 in range(len(丁丁物件)-1, -1, -1): | |
sq物體 = 丁丁物件[丁] | |
if 'rect' in sq物體 and 玩家丁丁['rect'].colliderect(sq物體['rect']): | |
# a player/squirrel collision has occurred | |
if sq物體['寬'] * sq物體['高'] <= 玩家丁丁['尺寸']**2: | |
# player is larger and eats the squirrel | |
玩家丁丁['尺寸'] += int( (sq物體['寬'] * sq物體['高'])**0.2 ) + 1 | |
del 丁丁物件[丁] | |
if 玩家丁丁['面朝'] == 左: | |
玩家丁丁['表面'] = pygame.transform.scale(左圖片, (玩家丁丁['尺寸'], 玩家丁丁['尺寸'])) | |
if 玩家丁丁['面朝'] == 右: | |
玩家丁丁['表面'] = pygame.transform.scale(右圖片, (玩家丁丁['尺寸'], 玩家丁丁['尺寸'])) | |
if 玩家丁丁['尺寸'] > 最後大小: | |
結束時間 = True # turn on "win mode" | |
elif not 無敵狀態: | |
# player is smaller and takes damage | |
無敵狀態 = True | |
無敵時間 = time.time() | |
玩家丁丁['血量'] -= 1 | |
if 玩家丁丁['血量'] == 0: | |
結束狀態 = True # turn on "game over mode" | |
結束時間 = time.time() | |
else: | |
# game is over, show "game over" text | |
顯示.blit(遊戲結束字體, 遊戲結束反映) | |
if time.time() - 結束時間 > 結束遊戲: | |
return # end the current game | |
# check if the player has won. | |
if 結束時間: | |
顯示.blit(勝利字體, 勝利反映) | |
顯示.blit(勝利字體2, 勝利反映2) | |
pygame.display.update() | |
變數時.tick(變數) | |
def 畫血條(正血量): | |
for 丁 in range(正血量): # draw 紅 health bars | |
pygame.draw.rect(顯示, 紅, (15, 5 + (10 * 血量上限) - 丁 * 10, 20, 10)) | |
for 丁 in range(血量上限): # draw the white outlines | |
pygame.draw.rect(顯示, 白, (15, 5 + (10 * 血量上限) - 丁 * 10, 20, 10), 1) | |
def 終止(): | |
pygame.quit() | |
sys.exit() | |
def 得分機制(正確得分, 成長速度, 得分): | |
# Returns the number of pixels to offset based on the bounce. | |
# Larger 成長速度 means a slower bounce. | |
# Larger 得分 means a higher bounce. | |
# currentBounce will always be less than 成長速度 | |
return int(math.sin( (math.pi / float(成長速度)) * 正確得分 ) * 得分) | |
def 隨機速度(): | |
速度 = random.randint(最慢速度, 最快速度) | |
if random.randint(0, 1) == 0: | |
return 速度 | |
else: | |
return -速度 | |
def 隨機位置取得(相機甲, 相機乙, 物體寬, 物體高): | |
# create a Rect of the camera view | |
取得中心 = pygame.Rect(相機甲, 相機乙, 螢幕高, 螢幕寬) | |
while True: | |
甲 = random.randint(相機甲 - 螢幕高, 相機甲 + (2 * 螢幕高)) | |
乙 = random.randint(相機乙 - 螢幕寬, 相機乙 + (2 * 螢幕寬)) | |
# create a Rect object with the random coordinates and use colliderect() | |
# to make sure the right edge isn't in the camera view. | |
物體呼叫 = pygame.Rect(甲, 乙, 物體寬, 物體高) | |
if not 物體呼叫.colliderect(取得中心): | |
return 甲, 乙 | |
def 創造新丁丁(相機甲, 相機乙): | |
創造 = {} | |
一般距離 = random.randint(5, 25) | |
倍率 = random.randint(1, 3) | |
創造['寬'] = (一般距離 + random.randint(0, 10)) * 倍率 | |
創造['高'] = (一般距離 + random.randint(0, 10)) * 倍率 | |
創造['甲'], 創造['乙'] = 隨機位置取得(相機甲, 相機乙, 創造['寬'], 創造['高']) | |
創造['移動量x'] = 隨機速度() | |
創造['移動量y'] = 隨機速度() | |
if 創造['移動量x'] < 0: # squirrel is facing left | |
創造['表面'] = pygame.transform.scale(左圖片, (創造['寬'], 創造['高'])) | |
else: # squirrel is facing right | |
創造['表面'] = pygame.transform.scale(右圖片, (創造['寬'], 創造['高'])) | |
創造['成長'] = 0 | |
創造['成長速度'] = random.randint(10, 18) | |
創造['得分'] = random.randint(10, 50) | |
return 創造 | |
def 建草野幽地(相機甲, 相機乙): | |
草野幽 = {} | |
草野幽['草野幽地模樣'] = random.randint(0, len(草野幽圖) - 1) | |
草野幽['寬'] = 草野幽圖[0].get_width() | |
草野幽['高'] = 草野幽圖[0].get_height() | |
草野幽['甲'], 草野幽['乙'] = 隨機位置取得(相機甲, 相機乙, 草野幽['寬'], 草野幽['高']) | |
草野幽['rect'] = pygame.Rect( (草野幽['甲'], 草野幽['乙'], 草野幽['寬'], 草野幽['高']) ) | |
return 草野幽 | |
def 林老師你好(相機甲, 相機乙, 物體): | |
# Return False if 相機甲 and 相機乙 are more than | |
# a half-window length beyond the edge of the window. | |
左邊邊 = 相機甲 - 螢幕高 | |
上邊邊 = 相機乙 - 螢幕寬 | |
物體實際 = pygame.Rect(左邊邊, 上邊邊, 螢幕高 * 3, 螢幕寬 * 3) | |
全貌 = pygame.Rect(物體['甲'], 物體['乙'], 物體['寬'], 物體['高']) | |
return not 物體實際.colliderect(全貌) | |
if __name__ == '__main__': | |
main() | |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment