本文主要是介绍python 自制黄金矿工游戏(设计思路+源码),希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!
1.视频效果演示
python自制黄金矿工,细节拉满沉浸式体验,看了你也会
2.开发准备的工具
python3.8, pygame库(python3.5以上的版本应该都可以)
图片处理工具,美图秀秀
截图工具,电脑自带的
自动抠图网页:https://koutu.gaoding.com/m
mp4格式文件转游戏音频:https://www.aconvert.com/cn/audio/mp4-to-wav/#google_vignette
声音录制工具,oCam
3.开发和设计思路
素材来源:主要是在4399的黄金矿工游戏,录制游戏音频,和截图游戏里面的元素
游戏设计了12个关卡,
3.1游戏中的元素
游戏矿石7种:大黄金,小黄金,中等黄金,钻石,小石头,大石头,盲盒
大黄金价值:500
小黄金价值:75
中等黄金价值:200
钻石价值:600
小石头价值:20
大石头价值:60
盲盒: -300 --- 700 也就是有可能,抓的盲盒是负的
钻石会随着等级的升级而变得更贵,
7种矿石在每局游戏种会随机出现。并不会每次全部出现。
游戏道具6种:小黄金升值道具,钻石升值道具,钻石数量增加道具,时间延长道具,幸运四叶草,强壮水,石头收藏书
在商城里面每次只会提供三种道具,这是随机的
游戏道具每次的价格是随机的所以要根据你的金钱数量,调整游戏策略
小黄金道具:如果购买了小黄金的价格会变成125 + 25 * 游戏关卡,小黄金的价格
钻石升值道具:使用了钻石变成600 + 300 增值300 300 + 75 * Game_config.level
钻石数量增加道具:如果在商店购买了,钻石的数量会在之前的基础上,生成钻石的随机值,最大的可能值会+3
时间延长道具:使用之后游戏时间会变成80秒,正常一局游戏60s
幸运四叶草: 幸运四叶草,在商店买了的化,抓取到了神秘礼包盲盒,金额会随机的变多
500 -- 1000
否则是
-300 --- 700
强壮水:抓取物品的速度会变的更快,speed +2
石头收藏书: 石头增值道具,如果买了大石头的价格会*4
1到12关的目标金额: [1000, 2200, 3600, 5400, 7500, 10000, 12500, 17000, 21500, 26000, 30000, 45000]
3.2音频素材
音频素材6段:抓到大黄金的声音,抓到石头的声音,绳子变长的声音,金钱变多的声音,绳子摆动的声音,目标分数的声音;
3.2游戏界面
游戏界面四个:开始界面,游戏界面,商城界面,失败或者结束界面
3.3关于如何让矿工动起来
关于如何让矿工动起来: 使用不同的图片,让pygame在不同时间播放不同的图片。
我最喜欢这个游戏的部分就是,矿工满头大汗,抓矿石的样子,哈哈哈。
还有就是商城道具和矿石的随机性。
3.4如何让绳子和钩子动起来
如何让钩子和绳子动起来。
钩子的摆动幅度是-70 到 70 度,每次变化的幅度是3度
这里使用了三角函数,sin cos 来实现
总共有9张钩子的图片,随着角度的变化,显示不同的图片
3.5关于每个关卡矿石的生成策略
#每个关卡游戏界面物品的生成
钻石的基础数量是0
如果在商店买了钻石水 3
如果等级能被4整除
钻石的数量 no_diamond += 2 +int(level/3)
如果等级大于6
钻石的数量 no_diamond += 2
如果等级大于等于8
钻石的数量 no_diamond += 4
如果等级大于等于12
钻石的数量 no_diamond += 10
神秘包裹盲盒的数量
如果等级能被2整除 no_random += 3 +int(level/2)
否则 no_random = 1
大黄金的数量
如果等级大于等于3no_big = 1 no_big += level//2
否则大黄金数量等于0
如果等级大于等于6 no_big += 2
如果等级大于等于8 no_big += 3
如果等级大于等于12 no_big = 6
base 一些物品的最小基础值
如果等级大于等于6 base = 1 否则 base = 0
如果等级大于等于8 base = 2
如果等级大于等于12 base = 5
如果等级大于等于8 小石头的数量[0,2]
如果等级大于等于8 小黄金的数量[0,2或者3]
如果等级小于8 小石头的数量 [5,7]
如果等级小于8 小黄金的数量 5 + level // 2, 12 + level // 2
中等黄金的数量
0, random.randint(5+level//2, 8+level//2)
大石头的数量
0, random.randint(1 + level // 4 + base, 3 + level // 4 + base)
大黄金的数量
0, random.randint(base, no_big)
钻石的数量
0, random.randint(base, no_diamond)
神秘包裹的数量
0, random.randint(base, no_random)
游戏的fps
ticks_per_second = 30 表示是1000/30 的刷新频率
如果生成的物品模型发生了重叠,那么要重新生成
3.6代码文件
代码文件:gamebox.py 对pygame库的二次封装
Gold_mine.py 游戏逻辑主要代码
4.代码部分
gold_miner.py文件
import timeimport pygame
from enum import Enum, unique
import gamebox
import random
import math@unique #此装饰器可以帮助我们检查保证没有重复值
class Screen(Enum):screen_begin = 0screen_game = 1screen_shop = 2screen_target_score = 3screen_failed = 4@unique #此装饰器可以帮助我们检查保证没有重复值
class Character(Enum):character_up = 0character_down = 1class Character_Getthing(Enum):character_up_getthin = 0character_down_getthin = 1class Game_Background(Enum):background_begin = 0background_game_heard = 1background_game_body = 2background_shop = 3background_target_score = 4background_failed = 5class Audio(Enum):audio_money_increase = 0audio_target_score = 1audio_rope_swing = 2audio_go_long = 3audio_get_big_gold = 4audio_get_stone = 5
#矿石
@unique
class Mineral(Enum):gold_small = 0gold_middle = 1gold_big = 2stone_small = 3stone_big = 4Diamond = 5random_big = 6#钩子的每一帧图片hook_dict = {}
hook_dict[-70] = "hook/hook_70.png"
hook_dict[-43] = "hook/hook_43.png"
hook_dict[-31] = "hook/hook_31.png"
hook_dict[-16] = "hook/hook_16.png"
hook_dict[1] = "hook/hook_1.png"
hook_dict[14] = "hook/hook14.png"
hook_dict[32] = "hook/hook32.png"
hook_dict[44] = "hook/hook44.png"
hook_dict[68] = "hook/hook68.png"#游戏配置类
class Game_config():speed = 5# 游戏关卡,从第一关开始level = 1#游戏金钱money = 0#钩子摆动的角度 -70 --- 70radins = -70#摆动的角度每次偏移的值radins_offset = 3radins_min = -70radins_max = 70#绳子的初始长度距离chain_distance = 30#绳子的变化速度 抓到不同的重量 速度不一样weight_item_caught = speed +5#钩子的变化速度控制,抓到不同物体速度变化不一样pict_index = 0#控制一局游戏的时间 和刷新频率有关系 当前1s刷新15次,计数器60s刷新900次counter = 900popped_up_word_counterdown = 16#大黄金的价格和标志gold_large_value = 500gold_small_value = 75gold_middle_value = 200dimaond_value = 600small_rock_value = 20big_rock_value = 60#抓到了神秘背包,那么绳子移动速度是随机的(-4,+5)#价值也是随机的# 每局游戏的目标分数money_goal = [1000, 2200, 3600, 5400, 7500, 10000, 12500, 17000, 21500, 26000, 30000, 45000]#矿石生成的随机区域的范围控制mineral_race_min_x = 50mineral_race_max_x = 900mineral_race_min_y = 240mineral_race_max_y = 690#按钮的范围绘制#开始按钮的坐标范围button_start_min_x = 38button_start_max_x = 400button_start_min_y = 18button_start_max_y = 370#音频文件#游戏开始和目标分数的音频sound_start ="sound/audio_target_score.wav"#绳子摆动的音频sound__rope_swing = "sound/audio_rope_swing.wav"#金钱增加的声音sound__money_increase = "sound/audio_money_increase.wav"#绳子变长的声音sound_go_long = "sound/audio_go_long.wav"#抓到石头的声音sound_get_stone = "sound/audio_get_stone.wav"#抓到大黄金的声音sound_get_big_gold = "sound/audio_get_big_gold.wav"#商店的三个格子每次只能点击一次store_index = Falsestore_index2 = Falsestore_index3 = False#生成物品的算法如果发生了碰撞最多尝试10次try_times = 10#商店
class Store():# 如果购买了小黄金的价格会变成125 + 25 * levelitem_gold_modifer = False# 如果购买了,钻石的价值会增加300item_polisher = False# 如果在商店购买了,钻石的数量会在之前的基础上,生成钻石的随机值,最大的可能值会+3item_lamp = False# 时间延长器如果在商店买了计数增加到1200item_time = False#幸运四叶草,在商店买了的化,抓取到了神秘礼包,金额会随机的变多# 500 -- 1000# 否则是# -300 --- 700item_luck = False#如果购买了会变得强壮速度+2item_strong = False# 石头增值道具,如果买了大石头的价格会*4item_rocks = False#商品的枚举类型
@unique
class Store_index(Enum):index_gold_modifer = 0index_polisher = 1index_lamp = 2index_time = 3index_luck = 4index_strong = 5index_rocks = 6dict_goods_picture = {}
dict_goods_picture[Store_index.index_gold_modifer.value] = "goods/gold_modifer.png"
dict_goods_picture[Store_index.index_polisher.value] = "goods/polisher.png"
dict_goods_picture[Store_index.index_lamp.value] = "goods/lamp.png"
dict_goods_picture[Store_index.index_time.value] = "goods/time.png"
dict_goods_picture[Store_index.index_luck.value] = "goods/luck.png"
dict_goods_picture[Store_index.index_rocks.value] = "goods/rocks.png"
dict_goods_picture[Store_index.index_strong.value] = "goods/strong.png"
dict_goods_text = {}dict_goods_text[Store_index.index_gold_modifer.value] = "小黄金会变得更值钱"
dict_goods_text[Store_index.index_polisher.value] = "钻石会变得更值钱"
dict_goods_text[Store_index.index_lamp.value] = "钻石会变得更多"
dict_goods_text[Store_index.index_time.value] = "游戏时间会变得更长"
dict_goods_text[Store_index.index_luck.value] = "神秘礼包的金额会变得更多"
dict_goods_text[Store_index.index_rocks.value] = "大石头的价格会增加4倍"
dict_goods_text[Store_index.index_strong.value] = "矿工会变更强壮,加快"#矿石图片存储列表
picture_mineral = ["picture/gold_small.png","picture/gold_middle.png","picture/gold_big.png","picture/rock_small.png","picture/rock_big.png","picture/dimaond.png","picture/mystery_bag.png"]
#平常状态的角色
picture_list_character = ["picture/character_up.png","picture/character_down.png"]
#抓取到东西的时候的角色图片
picture_list_character_getthing = ["picture/character_up_getthin.png","picture/character_down_getthin.png"]
#商品的图片
picture_list_goods = ["picture/character_up_getthin.png"]
#音频文件
sound_list = ["sound/audio_money_increase.png","sound/audio_target_score.png","sound/audio_rope_swing.png","picture/audio_go_long.png","picture/audio_get_big_gold.png","picture/audio_get_stone7.png"]
picture_list_screen = ["picture/screen_begin.png","picture/screen_game_head.png","picture/screen_game_body.png","picture/screen_shop.png","picture/screen_target_score.png","picture/screen_failed.png"]#全局变量
#界面index
#0开始界面
#1游戏界面
#2商城界面
#3目标分数界面
#4失败界面
screen = 0
#游戏界面的长宽
camera=gamebox.Camera(1000, 700)
# 在左上角绘制文字
pygame.display.set_caption('制作人:慕白白ls')#Item value
#抓到的东西的价格
value_caught = 0
#人物角色的控制每一帧显示的图片
character_index =0#bool 游戏中元素的状态值
#钩子的状态
chain_thrown_out= False
#钩子的方向状态 右-> 左 or 左->右
direction_left_to_right=True
#钩子是否被仍出去了
chain_thrown_out= False
#绳子是伸长状态还是收缩状态
chain_thrown_out_away = True
#钩子是否抓取到了东西
chain_thrown_out_catchsomething = False#钩子对象
chainhead = gamebox.from_image(200, 200, hook_dict[-70])
#人物对象
character = gamebox.from_image(507, 41, picture_list_character[0])character_getthing = gamebox.from_image(507, 41, picture_list_character_getthing[character_index])#显示在游戏界面的物品
gold_middle_object = gamebox.from_image(400,400,picture_mineral[Mineral.gold_middle.value])
gold_small_object = gamebox.from_image(500,500,picture_mineral[Mineral.gold_small.value])
gold_large_object = gamebox.from_image(700,500,picture_mineral[Mineral.gold_big.value])
gold_dimaond_object = gamebox.from_image(700, 500, picture_mineral[Mineral.Diamond.value])
gold_small_rock_object = gamebox.from_image(400, 600, picture_mineral[Mineral.stone_small.value])
gold_big_rock_object = gamebox.from_image(600, 600, picture_mineral[Mineral.stone_big.value])
gold_random_big_object = gamebox.from_image(200, 300,picture_mineral[Mineral.random_big.value])hard_object = gamebox.from_image(580, 20,"picture/strong.png")
#list
gold_middle_list = []
gold_small_list = []
gold_large_list = []
gold_dimaond_list = []
gold_small_rock_list = []
gold_big_rock_list = []
gold_random_big_list = []#商品存储列表
shop_list = []
shop_price = []def Set_Store_value(value):if(value == Store_index.index_gold_modifer.value):Store.item_gold_modifer = Trueif (value == Store_index.index_polisher.value):Store.item_polisher = Trueif (value == Store_index.index_lamp.value):Store.item_lamp = Trueif (value == Store_index.index_time.value):Store.item_time = Trueif (value == Store_index.index_luck.value):Store.item_luck = Trueif (value == Store_index.index_strong.value):Store.item_strong = Trueif (value == Store_index.index_rocks.value):Store.item_rocks = Trueif Store.item_strong:Game_config.speed += 2#回调函数,循环接收键盘和鼠标的消息
#钩子的变化范围是从-70 的角度 变化到70
def Callback_Loop(keys):global screen , camera ,character_index,character,value_caughtglobal chain_thrown_out_catchsomething,chain_thrown_out,direction_left_to_rightglobal chain_thrown_out,chain_thrown_out_away,shop_price,shop_priceglobal shop_listcamera.clear('grey')if screen == Screen.screen_begin.value:#设置显示的图片大小长,宽#screen_surface = gamebox.from_image(500, 350, picture_list_screen[Game_Background.background_begin.value])screen_surface = gamebox.from_image(500, 350, "picture/begin.png")screen_surface.scale_by(0.9)camera.draw(screen_surface)camera.draw(gamebox.from_text(200, 430, "制作人:慕白白ls", "SimHei", 30, "yellow"))# 文字信息camera.draw(gamebox.from_text(200, 500, "点击开始按钮开始游戏", "SimHei", 30, "yellow"))#播放音乐if pygame.mixer.music.get_busy() == False:pygame.mixer.music.load(Game_config.sound_start)pygame.mixer.music.play()#监听消息查看是否点击了开始游戏if pygame.MOUSEBUTTONDOWN in keys:#响应了当前点击事件之后马上把这个事件删除keys.remove(pygame.MOUSEBUTTONDOWN)pos = pygame.mouse.get_pos()if pos[0] >= Game_config.button_start_min_x and pos[0] <=Game_config.button_start_max_x and \pos[1] >= Game_config.button_start_min_y and pos[1] <= Game_config.button_start_max_y:screen = Screen.screen_game.valueGoods_Generate(Game_config.level)#游戏界面if screen == Screen.screen_game.value:#绘制游戏主体背景picture = gamebox.from_image(500, 380, picture_list_screen[Game_Background.background_game_body.value])#游戏背景头picture2 = gamebox.from_image(500, 37.5, picture_list_screen[Game_Background.background_game_heard.value])picture2.scale_by(0.6)picture.scale_by(0.7)camera.draw(picture)camera.draw(picture2)if pygame.MOUSEBUTTONDOWN in keys:# 响应了当前点击事件之后马上把这个事件删除keys.remove(pygame.MOUSEBUTTONDOWN)pos = pygame.mouse.get_pos()if pos[0] >= 786 and pos[0] <= 881 and \pos[1] >= 7 and pos[1] <= 67 :Game_config.counter = 0#绘制人物角色if chain_thrown_out_catchsomething :character_getthing.image = picture_list_character_getthing[character_index]camera.draw(character_getthing)# 语气词语camera.draw(hard_object)else:camera.draw(character)if character_index == 0:character_index += 1else:character_index = 0if chain_thrown_out == False:#绘制绳子左右摆动的声音if pygame.mixer.music.get_busy() == False:pygame.mixer.music.load(Game_config.sound__rope_swing)pygame.mixer.music.play()if Game_config.popped_up_word_counterdown >= 16:if direction_left_to_right == True:Game_config.radins += Game_config.radins_offsetelse:Game_config.radins -= Game_config.radins_offsetif Game_config.radins <= Game_config.radins_min:direction_left_to_right = Trueif Game_config.radins >= Game_config.radins_max:direction_left_to_right = False# 绘制钩子if Game_config.radins in hook_dict:chainhead.image = hook_dict[Game_config.radins]chainhead.x = 500 + math.sin(Game_config.radins / 57.29) * 75chainhead.y = 75 + math.cos(Game_config.radins / 57.29) * 75camera.draw(chainhead)# 绳子的本体item = gamebox.from_color(500, 75, "black", 5, 5)for i in range(0, 26):item = gamebox.from_color(500 + math.sin(Game_config.radins / 57.29) * 2.5 * i,75 + math.cos(Game_config.radins / 57.29) * 2.5 * i, "black", 5, 5)camera.draw(item)# 按下向下的方向键的时候if pygame.K_DOWN in keys and chain_thrown_out == False and Game_config.popped_up_word_counterdown >= 16:chain_thrown_out = Truechain_thrown_out_away = Truechain_thrown_out_catchsomething = False# 抓东西的时候角色放大了1.2倍#character.scale_by(1.2)#按下向下的方向键绳子慢慢边长if chain_thrown_out == True and chain_thrown_out_away == True:Game_config.chain_distance += Game_config.speed#绳子变长时候的音乐pygame.mixer.music.stop()if pygame.mixer.music.get_busy() == False:pygame.mixer.music.load(Game_config.sound_go_long)pygame.mixer.music.play()#把绳子慢慢增长有多长就画多少个黑色像素for i in range(1, Game_config.chain_distance):item = gamebox.from_color(500 + math.sin(Game_config.radins / 57.29) * 2.5 * i,75 + math.cos(Game_config.radins / 57.29) * 2.5 * i, "black", 5, 5)camera.draw(item)chainhead.x = 500 + math.sin(Game_config.radins / 57.29) * (10 + 2.5 * Game_config.chain_distance)chainhead.y = 75 + math.cos(Game_config.radins / 57.29) * (10 + 2.5 * Game_config.chain_distance)if Game_config.radins in hook_dict:chainhead.image = hook_dict[Game_config.radins]camera.draw(chainhead)#到低了绳子开始收缩if chain_thrown_out == True and chain_thrown_out_away == False:Game_config.chain_distance -= Game_config.weight_item_caughtfor i in range(1, Game_config.chain_distance):item = gamebox.from_color(500 + math.sin(Game_config.radins / 57.29) * 2.5 * i,75 + math.cos(Game_config.radins / 57.29) * 2.5 * i, "black", 5, 5)camera.draw(item)chainhead.x = 500 + math.sin(Game_config.radins / 57.29) * (10 + 2.5 * Game_config.chain_distance)chainhead.y = 75 + math.cos(Game_config.radins / 57.29) * (10 + 2.5 * Game_config.chain_distance)camera.draw(chainhead)# 钩子超过界面的边界了if chainhead.x < 0 or chainhead.x > 1000 or chainhead.y > 700:chain_thrown_out_away = False#抓到东西到最上面了,金钱要增加if Game_config.chain_distance <= 29 and chain_thrown_out == True:if chain_thrown_out_catchsomething == True:# 金钱增加的声音pygame.mixer.music.stop()if pygame.mixer.music.get_busy() == False:pygame.mixer.music.load(Game_config.sound__money_increase)pygame.mixer.music.play()if value_caught != 0:Game_config.popped_up_word_counterdown = 1Game_config.money += value_caughtchain_thrown_out_catchsomething = Falsechain_thrown_out = False#角色缩小0.833#character.scale_by(0.833)Game_config.weight_item_caught = Game_config.speed + 5#操作游戏的时候物品的变化for gold in gold_middle_list:if gold.touches(chainhead) and chain_thrown_out_catchsomething == False:chain_thrown_out_away = Falsechain_thrown_out_catchsomething = TrueGame_config.weight_item_caught = Game_config.speed - 2Game_config.pict_index = Mineral.gold_middle.valuevalue_caught = Game_config.gold_middle_valuegold_middle_list.remove(gold)camera.draw(gold)for gold in gold_small_list:if gold.touches(chainhead) and chain_thrown_out_catchsomething == False:chain_thrown_out_away = Falsechain_thrown_out_catchsomething = TrueGame_config.weight_item_caught = Game_config.speedGame_config.pict_index = Mineral.gold_small.valueif Store.item_gold_modifer == True:value_caught = 125 + 25 * Game_config.levelelse:value_caught = Game_config.gold_small_valuegold_small_list.remove(gold)camera.draw(gold)for gold in gold_large_list:if gold.touches(chainhead) and chain_thrown_out_catchsomething == False:chain_thrown_out_away = Falsechain_thrown_out_catchsomething = TrueGame_config.weight_item_caught = Game_config.speed - 4Game_config.pict_index = Mineral.gold_middle.gold_big.valuevalue_caught = Game_config.gold_large_valuegold_large_list.remove(gold)#抓到大黄金声音pygame.mixer.music.stop()if pygame.mixer.music.get_busy() == False:pygame.mixer.music.load(Game_config.sound_get_big_gold)pygame.mixer.music.play()camera.draw(gold)for gold in gold_dimaond_list:if gold.touches(chainhead) and chain_thrown_out_catchsomething == False:chain_thrown_out_away = Falsechain_thrown_out_catchsomething = TrueGame_config.weight_item_caught = Game_config.speed + 4Game_config.pict_index = Mineral.Diamond.valuegold_dimaond_list.remove(gold)if Store.item_polisher == True:value_caught = Game_config.dimaond_value + 300 + 75 * Game_config.levelelse:value_caught = Game_config.dimaond_value + 50 * Game_config.levelcamera.draw(gold)for gold in gold_small_rock_list:if gold.touches(chainhead) and chain_thrown_out_catchsomething == False:chain_thrown_out_away = Falsechain_thrown_out_catchsomething = TrueGame_config.weight_item_caught = Game_config.speed - 2Game_config.pict_index = Mineral.stone_small.valuevalue_caught = Game_config.small_rock_valueif Store.item_rocks == True:value_caught = value_caught * 4gold_small_rock_list.remove(gold)# 抓到石头pygame.mixer.music.stop()if pygame.mixer.music.get_busy() == False:pygame.mixer.music.load(Game_config.sound_get_stone)pygame.mixer.music.play()camera.draw(gold)for gold in gold_big_rock_list:if gold.touches(chainhead) and chain_thrown_out_catchsomething == False:chain_thrown_out_away = Falsechain_thrown_out_catchsomething = TrueGame_config.weight_item_caught = Game_config.speed - 4Game_config.pict_index = Mineral.stone_big.valueGame_config.value_caught = Game_config.big_rock_valueif Store.item_rocks == True:value_caught = value_caught * 4gold_big_rock_list.remove(gold)# 抓到石头pygame.mixer.music.stop()if pygame.mixer.music.get_busy() == False:pygame.mixer.music.load(Game_config.sound_get_stone)pygame.mixer.music.play()camera.draw(gold)for gold in gold_random_big_list:if gold.touches(chainhead) and chain_thrown_out_catchsomething == False:if chain_thrown_out_catchsomething == False:Game_config.weight_item_caught = Game_config.speed + random.randint(-4, 5)chain_thrown_out_away = Falsechain_thrown_out_catchsomething = TrueGame_config.pict_index = Mineral.random_big.valueif Store.item_luck == True:value_caught = random.randint(500, 1000)else:value_caught = random.randint(-300, 700)gold_random_big_list.remove(gold)camera.draw(gold)#抓到了物品,要把物品挂在钩子上if chain_thrown_out_catchsomething == True:item = gamebox.from_image(500 + math.sin(Game_config.radins / 57.29) * 2.5 * (Game_config.chain_distance+10),75 + math.cos(Game_config.radins / 57.29) * 2.5 * (Game_config.chain_distance+10), picture_mineral[ Game_config.pict_index])camera.draw(item)#绘制游戏的参数的变化Game_config.counter -= 1camera.draw(gamebox.from_text(850, 100, "游戏关卡:" + str(Game_config.level) + " 目标金额:" + str(Game_config.money_goal[Game_config.level - 1]), "SimHei",20, "yellow"))camera.draw(gamebox.from_text(135, 25, "你的金钱:" +"$"+ str(Game_config.money), "SimHei", 24, "yellow"))camera.draw(gamebox.from_text(130, 55, "剩余时间:" + str(int(Game_config.counter / 15)), "SimHei", 22, "red"))Game_config.popped_up_word_counterdown += 1if Game_config.popped_up_word_counterdown <= 15:if value_caught > 0:camera.draw(gamebox.from_text(300, 25, "+" +"$"+ str(value_caught), "arial", 30, "green", bold=True))else:camera.draw(gamebox.from_text(300, 25, str(value_caught), "arial", 30, "red", bold=True))elif Game_config.popped_up_word_counterdown == 16:value_caught = 0#游戏时间结束之后的处理if Game_config.counter <= 0:if Game_config.money < Game_config.money_goal[Game_config.level - 1] or Game_config.level == 12 :#进入游戏失败的界面screen = Screen.screen_failed.value#否则进入游戏商城界面else:Game_config.level += 1# shop generationsrandom_list = [0, 1, 2, 3, 4, 5, 6]random.shuffle(random_list)shop_list = []shop_price = []shop_selection = 0shop_list.append(random_list[0])shop_list.append(random_list[1])shop_list.append(random_list[2])# 商店的商品价格随着等级的增高# 相应的要变贵# 变化的范围是 基础价格+ 等级*10 到 基础价格+等级*150之间for stuff in shop_list:if Game_config.level != 12:if stuff == 0:shop_price.append(random.randint(25 + Game_config.level * 10, 300 + Game_config.level * 50))elif stuff == 1:shop_price.append(random.randint(400, 600 + Game_config.level * 50))elif stuff == 2:shop_price.append(random.randint(50 + Game_config.level * 20, 300 + Game_config.level * 30))elif stuff == 3:shop_price.append(random.randint(200 + Game_config.level * 20, 600 + Game_config.level * 75))elif stuff == 4:shop_price.append(random.randint(50 + Game_config.level * 20, 200 + Game_config.level * 50))elif stuff == 5:shop_price.append(random.randint(50 + Game_config.level * 30, 400 + Game_config.level * 150))else:shop_price.append(random.randint(5 + Game_config.level * 20, 200 + Game_config.level * 10))else:shop_price.append(0)#游戏结束回复游戏的初始参数Game_config.speed = 5Store.item_gold_modifer = FalseStore.item_polisher = FalseStore.item_lamp = FalseStore.item_time = FalseStore.item_luck = FalseStore.item_rocks = False#进入商城界面screen = Screen.screen_shop.valuechain_thrown_out_catchsomething = Falsechain_thrown_out = False#character.scale_by(0.833)Game_config.weight_item_caught = Game_config.speed + 5value_caught = 0if screen == Screen.screen_shop.value:#播放音乐if pygame.mixer.music.get_busy() == False:pygame.mixer.music.load(Game_config.sound_start)pygame.mixer.music.play()picture = gamebox.from_image(500, 360, picture_list_screen[Game_Background.background_shop.value])picture.scale_by(0.8)camera.draw(picture)if shop_list[0] != -1:camera.draw(gamebox.from_image(100, 430, dict_goods_picture[shop_list[0]]))camera.draw(gamebox.from_text(110, 550, "$" + str(shop_price[0]), "SimHei", 22, "green"))camera.draw(gamebox.from_text(180, 650, "商品1:" + dict_goods_text[shop_list[0]], "SimHei", 16, "yellow"))if shop_list[1] != -1:camera.draw(gamebox.from_image(300, 430, dict_goods_picture[shop_list[1]]))camera.draw(gamebox.from_text(310, 550, "$" + str(shop_price[1]), "SimHei", 22, "green"))camera.draw(gamebox.from_text(430, 650, "商品2:" + dict_goods_text[shop_list[1]], "SimHei", 16, "yellow"))if shop_list[2] != -1:camera.draw(gamebox.from_image(500, 430, dict_goods_picture[shop_list[2]]))camera.draw(gamebox.from_text(510, 550, "$" + str(shop_price[2]), "SimHei", 22, "green"))camera.draw(gamebox.from_text(780, 650, "商品3:" + dict_goods_text[shop_list[2]], "SimHei", 16, "yellow"))camera.draw(gamebox.from_text(800, 50, "下一个关卡:" + str(Game_config.level) +" "+ "目标金额:" + str(Game_config.money_goal[Game_config.level - 1]),"SimHei",20, "yellow"))camera.draw(gamebox.from_text(850, 25, "你的金钱:" +"$"+ str(Game_config.money), "SimHei", 20, "green"))if Game_config.level == 12:camera.draw(gamebox.from_text(500, 150, "最后一关了所有商品免费", "SimHei", 35, "green",bold=True))if pygame.MOUSEBUTTONDOWN in keys:# 响应了当前点击事件之后马上把这个事件删除keys.remove(pygame.MOUSEBUTTONDOWN)pos = pygame.mouse.get_pos()if pos[0] >= 62 and pos[0] <= 141 and \pos[1] >= 369 and pos[1] <= 502 and shop_list[0] != -1:Game_config.money -= shop_price[0]Set_Store_value(shop_list[0])shop_list[0] = -1# 播放音乐pygame.mixer.music.load(Game_config.sound__money_increase)pygame.mixer.music.play()if pos[0] >= 227 and pos[0] <= 362 and \pos[1] >= 372 and pos[1] <= 494 and shop_list[1] != -1:Game_config.money -= shop_price[1]Set_Store_value(shop_list[1])shop_list[1] = -1pygame.mixer.music.load(Game_config.sound__money_increase)pygame.mixer.music.play()if pos[0] >= 438 and pos[0] <= 596 and \pos[1] >= 363 and pos[1] <= 496 and shop_list[2] != -1:Game_config.money -= shop_price[2]Set_Store_value(shop_list[2])shop_list[2] = -1pygame.mixer.music.load(Game_config.sound__money_increase)pygame.mixer.music.play()if pos[0] >= 767 and pos[0] <= 899 and \pos[1] >= 122 and pos[1] <= 180 :screen = Screen.screen_game.valueGoods_Generate(Game_config.level)if screen == Screen.screen_target_score.value:passif screen == Screen.screen_failed.value:picture = gamebox.from_image(500, 360, picture_list_screen[Game_Background.background_failed.value])picture.scale_by(0.9)camera.draw(picture)camera.draw(gamebox.from_text(500, 400, "你的总分数是:" +str(Game_config.money), "SimHei", 40, "red"))if pygame.MOUSEBUTTONDOWN in keys:# 响应了当前点击事件之后马上把这个事件删除keys.remove(pygame.MOUSEBUTTONDOWN)pos = pygame.mouse.get_pos()if pos[0] >= 78 and pos[0] <= 216 and \pos[1] >= 619 and pos[1] <= 673 :screen = Screen.screen_game.valueGame_config.level = 1print(1)Goods_Generate(Game_config.level)Game_config.money = 0#绘制游戏界面camera.display()#每个关卡游戏界面物品的生成# 钻石的基础数量是0
# 如果在商店买了钻石水 3
# 如果等级能被4整除
# 钻石的数量 no_diamond += 2 +int(level/3)
# 如果等级大于6
# 钻石的数量 no_diamond += 2
# 如果等级大于等于8
# 钻石的数量 no_diamond += 4
# 如果等级大于等于12
# 钻石的数量 no_diamond += 10# 神秘包裹的数量
# 如果等级能被2整除 no_random += 3 +int(level/2)
# 否则 no_random = 1# 大黄金的数量
# 如果等级大于等于3no_big = 1 no_big += level//2
# 否则大黄金数量等于0
# 如果等级大于等于6 no_big += 2
# 如果等级大于等于8 no_big += 3
# 如果等级大于等于12 no_big = 6# base 一些物品的最小基础值
# 如果等级大于等于6 base = 1 否则 base = 0
# 如果等级大于等于8 base = 2
# 如果等级大于等于12 base = 5# 如果等级大于等于8 小石头的数量[0,2]
# 如果等级大于等于8 小黄金的数量[0,2或者3]# 如果等级小于8 小石头的数量 [5,7]
# 如果等级小于8 小黄金的数量 5 + level // 2, 12 + level // 2# 中等黄金的数量
# 0, random.randint(5+level//2, 8+level//2)# 大石头的数量
# 0, random.randint(1 + level // 4 + base, 3 + level // 4 + base)# 大黄金的数量
# 0, random.randint(base, no_big)# 钻石的数量
# 0, random.randint(base, no_diamond)# 神秘包裹的数量
# 0, random.randint(base, no_random)# 游戏的fps
# ticks_per_second = 30 表示是1000/30 的刷新频率# 如果生成的物品模型发生了重叠,那么要重新生成
def Goods_Generate(level):global gold_middle_list,gold_small_list,gold_large_list,gold_dimaond_list,gold_small_rock_listglobal gold_big_rock_list,gold_random_big_listgold_middle_list =[]gold_small_list = []gold_large_list = []gold_dimaond_list = []gold_small_rock_list = []gold_big_rock_list = []gold_random_big_list = []#counter控制时间,每局的游戏60sif Store.item_time == True:Game_config.counter = 1200else:Game_config.counter = 900#gold_small_rock_list = []if Store.item_lamp == True:no_diamond = 3else:no_diamond = 0if level % 4 == 0:no_diamond += 2no_diamond += int(level/3)if level % 2 == 0:no_random = 3no_random += int(level/2)else:no_random = 1if level >= 3:no_big = 1no_big += level//2else:no_big = 0if level >= 6:no_diamond += 2no_big += 2no_random += 2base = 1else:base = 0if level >= 8:no_diamond += 4no_big += 3no_random += 3base = 2if level == 12:no_diamond += 10base = 5no_big = 6no_random = 6try_index = Game_config.try_timesif level >= 8:for c in range(0, random.randint(2,3)):item = gamebox.from_image(random.randint(Game_config.mineral_race_min_x, Game_config.mineral_race_max_x), random.randint(Game_config.mineral_race_min_y, Game_config.mineral_race_max_y), picture_mineral[Mineral.gold_small.value])gold_small_list.append(item)for c in range(0, 2):touched = Truewhile touched and try_index >=0:item = gamebox.from_image(random.randint(Game_config.mineral_race_min_x, Game_config.mineral_race_max_x), random.randint(Game_config.mineral_race_min_y, Game_config.mineral_race_max_y), picture_mineral[Mineral.stone_small.value])touched = Falsefor evaluated_item in gold_small_list:if item.touches(evaluated_item) == True:touched = Truefor evaluated_item in gold_small_rock_list:if item.touches(evaluated_item) == True:touched = Truetry_index -= 1if try_index >= 0 :gold_small_rock_list.append(item)try_index = Game_config.try_timeselse:for c in range(0, random.randint(5 + level // 2, 12 + level // 2)):item = gamebox.from_image(random.randint(Game_config.mineral_race_min_x, Game_config.mineral_race_max_x), random.randint(Game_config.mineral_race_min_y, Game_config.mineral_race_max_y), picture_mineral[Mineral.gold_small.value])gold_small_list.append(item)for c in range(0, random.randint(5, 7)):touched = Truewhile touched and try_index >=0:item = gamebox.from_image(random.randint(Game_config.mineral_race_min_x, Game_config.mineral_race_max_x), random.randint(Game_config.mineral_race_min_y, Game_config.mineral_race_max_y), picture_mineral[Mineral.stone_small.value])touched = Falsefor evaluated_item in gold_small_list:if item.touches(evaluated_item) == True:touched = Truefor evaluated_item in gold_small_rock_list:if item.touches(evaluated_item) == True:touched = Truetry_index -= 1if try_index >= 0 :gold_small_rock_list.append(item)try_index = Game_config.try_timesfor c in range(0, random.randint(5+level//2, 8+level//2)):touched = Truewhile touched and try_index >=0:item = gamebox.from_image(random.randint(Game_config.mineral_race_min_x, Game_config.mineral_race_max_x), random.randint(Game_config.mineral_race_min_y, Game_config.mineral_race_max_y), picture_mineral[Mineral.gold_middle.value])touched = Falsefor evaluated_item in gold_small_list:if item.touches(evaluated_item) == True:touched = Truefor evaluated_item in gold_small_rock_list:if item.touches(evaluated_item) == True:touched = Truefor evaluated_item in gold_middle_list:if item.touches(evaluated_item) == True:touched = Truetry_index -= 1if try_index >= 0:gold_middle_list.append(item)try_index = Game_config.try_timesfor c in range(0, random.randint(1+level//4+base, 3+level//4+base)):touched = Truewhile touched and try_index >=0:item = gamebox.from_image(random.randint(Game_config.mineral_race_min_x, Game_config.mineral_race_max_x), random.randint(Game_config.mineral_race_min_y, Game_config.mineral_race_max_y), picture_mineral[Mineral.stone_big.value])touched = Falsefor evaluated_item in gold_small_list:if item.touches(evaluated_item) == True:touched = Truefor evaluated_item in gold_small_rock_list:if item.touches(evaluated_item) == True:touched = Truefor evaluated_item in gold_middle_list:if item.touches(evaluated_item) == True:touched = Truefor evaluated_item in gold_big_rock_list:if item.touches(evaluated_item) == True:touched = Truetry_index -= 1if try_index >= 0:gold_big_rock_list.append(item)try_index = Game_config.try_timesfor c in range(0, random.randint(base, no_big)):touched = Truewhile touched and try_index >=0:item = gamebox.from_image(random.randint(Game_config.mineral_race_min_x, Game_config.mineral_race_max_x), random.randint(Game_config.mineral_race_min_y, Game_config.mineral_race_max_y), picture_mineral[Mineral.gold_big.value])touched = Falsefor evaluated_item in gold_small_list:if item.touches(evaluated_item) == True:touched = Truefor evaluated_item in gold_small_rock_list:if item.touches(evaluated_item) == True:touched = Truefor evaluated_item in gold_middle_list:if item.touches(evaluated_item) == True:touched = Truefor evaluated_item in gold_big_rock_list:if item.touches(evaluated_item) == True:touched = Truefor evaluated_item in gold_large_list:if item.touches(evaluated_item) == True:touched = Truetry_index -= 1if try_index >= 0:gold_large_list.append(item)try_index = Game_config.try_timesfor c in range(0, random.randint(base, no_diamond)):touched = Truewhile touched and try_index >=0:item = gamebox.from_image(random.randint(Game_config.mineral_race_min_x, Game_config.mineral_race_max_x), random.randint(Game_config.mineral_race_min_y, Game_config.mineral_race_max_y), picture_mineral[Mineral.Diamond.value])touched = Falsefor evaluated_item in gold_small_list:if item.touches(evaluated_item) == True:touched = Truefor evaluated_item in gold_small_rock_list:if item.touches(evaluated_item) == True:touched = Truefor evaluated_item in gold_middle_list:if item.touches(evaluated_item) == True:touched = Truefor evaluated_item in gold_big_rock_list:if item.touches(evaluated_item) == True:touched = Truefor evaluated_item in gold_large_list:if item.touches(evaluated_item) == True:touched = Truefor evaluated_item in gold_dimaond_list:if item.touches(evaluated_item) == True:touched = Truetry_index -= 1gold_dimaond_list.append(item)if try_index >= 0:gold_dimaond_list.append(item)try_index = Game_config.try_timesfor c in range(0, random.randint(base, no_random)):touched = Truewhile touched and try_index >=0:item = gamebox.from_image(random.randint(Game_config.mineral_race_min_x, Game_config.mineral_race_max_x), random.randint(Game_config.mineral_race_min_y, Game_config.mineral_race_max_y), picture_mineral[Mineral.random_big.value])touched = Falsefor evaluated_item in gold_small_list:if item.touches(evaluated_item) == True:touched = Truefor evaluated_item in gold_small_rock_list:if item.touches(evaluated_item) == True:touched = Truefor evaluated_item in gold_middle_list:if item.touches(evaluated_item) == True:touched = Truefor evaluated_item in gold_big_rock_list:if item.touches(evaluated_item) == True:touched = Truefor evaluated_item in gold_large_list:if item.touches(evaluated_item) == True:touched = Truefor evaluated_item in gold_dimaond_list:if item.touches(evaluated_item) == True:touched = Truefor evaluated_item in gold_random_big_list:if item.touches(evaluated_item) == True:touched = Truetry_index -= 1if try_index >= 0:gold_random_big_list.append(item)try_index = Game_config.try_timesif __name__ == '__main__':ticks_per_second = 20gamebox.timer_loop(ticks_per_second, Callback_Loop)
gamebox.py 文件
# A library file for simplifying pygame interaction. You MUST place this file in the same directory as your game py files.'''This code is the original work of Luther Tychonievich, who releases it
into the public domain.As a courtesy, Luther would appreciate it if you acknowledged him in any work
that benefited from this code.'''from __future__ import division
import pygame, sys
import urllib, os.pathif 'urlretrieve' not in dir(urllib):from urllib.request import urlretrieve as _urlretrieve
else:_urlretrieve = urllib.urlretrievepygame.init()# a cache to avoid loading images many time
_known_images = {}
_known_sounds = {}def _image(key, flip=False, w=0, h=0, angle=0):'''A method for loading images, caching them, and flipping them'''if '__hash__' not in dir(key):key = id(key)angle, w, h = int(angle), int(w), int(h)ans = Noneif (key, flip, w, h, angle) in _known_images:ans = _known_images[(key, flip, w, h, angle)]elif angle != 0:base = _image(key, flip, w, h)img = pygame.transform.rotozoom(base, angle, 1)_known_images[(key, flip, w, h, angle)] = imgans = imgelif w != 0 or h != 0:base = _image(key, flip)img = pygame.transform.smoothscale(base, (w, h))_known_images[(key, flip, w, h, angle)] = imgans = imgelif flip:base = _image(key)img = pygame.transform.flip(base, True, False)_known_images[(key, flip, w, h, angle)] = imgans = imgelse:img, _ = _get_image(key)_known_images[(key, flip, w, h, angle)] = imgans = imgif w == 0 and h == 0:if angle != 0:tmp = _image(key, flip, w, h)else:tmp = ans_known_images[(key, flip, tmp.get_width(), tmp.get_height(), angle)] = ansreturn ansdef _image_from_url(url):'''a method for loading images from urls by first saving them locally'''filename = os.path.basename(url)if not os.path.exists(filename):if '://' not in url: url = 'http://' + url_urlretrieve(url, filename)image, filename = _image_from_file(filename)return image, filenamedef _image_from_file(filename):'''a method for loading images from files'''image = pygame.image.load(filename).convert_alpha()_known_images[filename] = image_known_images[(image.get_width(), image.get_height(), filename)] = imagereturn image, filenamedef _get_image(thing):'''a method for loading images from cache, then file, then url'''if thing in _known_images: return _known_images[thing], thingsid = '__id__' + str(id(thing))if sid in _known_images: return _known_images[sid], sidif type(thing) is str:if os.path.exists(thing): return _image_from_file(thing)return _image_from_url(thing)_known_images[sid] = thing_known_images[(thing.get_width(), thing.get_height(), sid)] = thingreturn thing, siddef load_sprite_sheet(url_or_filename, rows, columns):'''Loads a sprite sheet. Assumes the sheet has rows-by-columns evenly-spaced images and returns a list of those images.'''sheet, key = _get_image(url_or_filename)height = sheet.get_height() / rowswidth = sheet.get_width() / columnsframes = []for row in range(rows):for col in range(columns):#把动图做一个切片切成均匀大小clip = pygame.Rect(col * width, row * height, width, height)frame = sheet.subsurface(clip)frames.append(frame)return frames__all__ = ['load_sprite_sheet']def from_image(x, y, filename_or_url):'''Creates a SpriteBox object at the given location from the provided filename or url'''image, key = _get_image(filename_or_url)return SpriteBox(x, y, image, None)__all__.append('from_image')def from_color(x, y, color, width, height):'''Creates a SpriteBox object at the given location with the given color, width, and height'''return SpriteBox(x, y, None, color, width, height)__all__.append('from_color')def from_text(x, y, text, fontname, fontsize, color, bold=False, italic=False):'''Creates a SpriteBox object at the given location with the given text as its content'''font = pygame.font.match_font(fontname.replace(" ", "").lower())if font is None:sys.stderr.write("ERROR: no font named " + fontname + "; using default font instead")font = pygame.font.Font(font, fontsize)font.set_bold(bold)font.set_italic(italic)if type(color) is str: color = pygame.Color(color)return from_image(x, y, font.render(text, True, color))__all__.append('from_text')def load_sound(url_or_filename):'''Reads a sound file from a given filename or url'''if url_or_filename in _known_images: return _known_sounds[url_or_filename]if not os.path.exists(url_or_filename):filename = os.path.basename(url_or_filename)if not os.path.exists(filename):_urlretrieve(url_or_filename, filename)url_or_filename = filenamesound = pygame.mixer.Sound(url_or_filename)_known_sounds[url_or_filename] = soundreturn sound__all__.append('load_sound')class Camera(object):'''A camera defines what is visible. It has a width, height, full screen status,and can be moved. Moving a camera changes what is visible.'''is_initialized = False# __slots__ = ["_surface", "x", "y", "speedx", "speedy"]def __init__(self, width, height, full_screen=False):'''Camera(pixelsWide, pixelsTall, False) makes a window; using True instead makes a full-screen display.'''if Camera.is_initialized: raise Exception("You can only have one Camera at a time")# if height > 768: raise Exception("The Game Expo screens will only be 768 pixels tall")# if width > 1366: raise Exception("The Game Expo screens will only be 1366 pixels wide")if full_screen:self.__dict__['_surface'] = pygame.display.set_mode([width, height], pygame.FULLSCREEN)else:self.__dict__['_surface'] = pygame.display.set_mode([width, height])self.__dict__['_x'] = 0self.__dict__['_y'] = 0Camera.is_initialized = Truedef move(self, x, y=None):'''camera.move(3, -7) moves the screen's center to be 3 more pixels to the right and 7 more up'''if y is None: x, y = xself.x += xself.y += ydef draw(self, thing, *args):'''camera.draw(box) draws the provided SpriteBox objectcamera.draw(image, x, y) draws the provided image centered at the provided coordinatescamera.draw("Hi", "Arial", 12, "red", x, y) draws the text Hi in a red 12-point Arial font at x,y'''if isinstance(thing, SpriteBox):thing.draw(self)elif isinstance(thing, pygame.Surface):try:if len(args) == 1:x, y = args[0]else:x, y = args[:2]self._surface.blit(thing, [x - thing.get_width() / 2, y - thing.get_height() / 2])except e:raise Exception("Wrong arguments; try .draw(surface, [x,y])")elif type(thing) is str:try:font = pygame.font.match_font(args[0].replace(" ", "").lower())if font is None:sys.stderr.write("ERROR: no font named " + fontname + "; using default font instead")size = args[1]color = args[2]if type(color) is str: color = pygame.Color(color)self.draw(pygame.font.Font(font, size).render(thing, True, color), *args[3:])except e:raise Exception("Wrong arguments; try .draw(text, fontName, fontSize, color, [x,y])")else:raise Exception("I don't know how to draw a ", type(thing))def display(self):'''Causes what has been drawn recently by calls to draw(...) to be displayed on the screen'''pygame.display.flip()def clear(self, color):'''Erases the screen by filling it with the given color'''if type(color) is str: color = pygame.Color(color)self._surface.fill(color)def __getattr__(self, name):if name in self.__dict__: return self.__dict__[name]x, y, w, h = self._x, self._y, self._surface.get_width(), self._surface.get_height()if name == 'left': return xif name == 'right': return x + wif name == 'top': return yif name == 'bottom': return y + hif name == 'x': return x + w / 2if name == 'y': return y + h / 2if name == 'center': return x + w / 2, y + h / 2if name == 'topleft': return x, yif name == 'topright': return x + w, yif name == 'bottomleft': return x, y + hif name == 'bottomright': return x + w, y + hif name == 'width': return wif name == 'height': return hif name == 'size': return w, hif name == 'mousex': return pygame.mouse.get_pos()[0] + self._xif name == 'mousey': return pygame.mouse.get_pos()[1] + self._yif name == 'mouse': return pygame.mouse.get_pos()[0] + self._x, pygame.mouse.get_pos()[1] + self._yif name == 'mouseclick': return any(pygame.mouse.get_pressed())raise Exception("There is no '" + name + "' in a Camera object")def __setattr__(self, name, value):if name in self.__dict__:self.__dict__[name] = valuereturnw, h = self._surface.get_width(), self._surface.get_height()if name == 'left':self._x = valueelif name == 'right':self._x = value - welif name == 'top':self._y = valueelif name == 'bottom':self._y = value - helif name == 'x':self._x = value - w / 2elif name == 'y':self._y = value - h / 2elif name == 'center':self._x, self._y = value[0] - w / 2, value[1] - h / 2elif name == 'topleft':self._x, self._y = value[0], value[1]elif name == 'topright':self._x, self._y = value[0] - w, value[1]elif name == 'bottomleft':self._x, self._y = value[0], value[1] - helif name == 'bottomright':self._x, self._y = value[0] - w, value[1] - helif name in ['width', 'height', 'size', 'mouse', 'mousex', 'mousey', 'mouseclick']:raise Exception("You cannot change the '" + name + "' of a Camera object")else:sys.stderr.write("creating field named " + name)self.__dict__[name] = valuedef __repr__(self):return str(self)def __str__(self):return '%dx%d Camera centered at %d,%d' % (self.width, self.height, self.x, self.y)__all__.append('Camera')class SpriteBox(object):'''Intended to represent a sprite (i.e., an image that can be drawn as part of a larger view) and the box that contains it. Has various collision and movement methods built in.'''# __slots__ = ["x","y","speedx","speedy","_w","_h","_key","_image","_color"]def __init__(self, x, y, image, color, w=None, h=None):'''You should probably use the from_image, from_text, or from_color method instead of this one'''self.__dict__['x'] = xself.__dict__['y'] = yself.__dict__['speedx'] = 0self.__dict__['speedy'] = 0if image is not None:self._set_key(image, False, 0, 0, 0)if w is not None:if h is not None:self.size = w, helse:self.width = welif h is not None:self.height = helif color is not None:if w is None or h is None: raise Exception("must supply size of color box")self.__dict__['_key'] = Noneself.__dict__['_image'] = Noneself.__dict__['_w'] = wself.__dict__['_h'] = hself.color = colorpassdef _set_key(self, name, flip, width, height, angle):width = int(width + 0.5)height = int(height + 0.5)angle = ((int(angle) % 360) + 360) % 360unrot = _image(name, flip, width, height)if width == 0 and height == 0:width = unrot.get_width()height = unrot.get_height()self.__dict__['_key'] = (name, flip, width, height, angle)self.__dict__['_image'] = _image(*self.__dict__['_key'])self.__dict__['_color'] = Noneself.__dict__['_w'] = self.__dict__['_image'].get_width()self.__dict__['_h'] = self.__dict__['_image'].get_height()def __getattr__(self, name):x, y, w, h = self.x, self.y, self._w, self._hif name == 'xspeed': name = 'speedx'if name == 'yspeed': name = 'speedy'if name == 'left': return x - w / 2if name == 'right': return x + w / 2if name == 'top': return y - h / 2if name == 'bottom': return y + h / 2if name == 'center': return x, yif name == 'topleft': return x - w / 2, y - h / 2if name == 'topright': return x + w / 2, y - h / 2if name == 'bottomleft': return x - w / 2, y + h / 2if name == 'bottomright': return x + w / 2, y + h / 2if name == 'width': return wif name == 'height': return hif name == 'width': return wif name == 'height': return hif name == 'size': return w, hif name == 'speed': return self.speedx, self.speedyif name == 'rect': return pygame.Rect(self.topleft, self.size)if name == 'image': return self.__dict__['_image']if name in self.__dict__:return self.__dict__[name]raise Exception("There is no '" + name + "' in a SpriteBox object")def __setattr__(self, name, value):w, h = self._w, self._hif name == 'xspeed': name = 'speedx'if name == 'yspeed': name = 'speedy'if name in self.__dict__:self.__dict__[name] = valueelif name == 'left':self.x = value + w / 2elif name == 'right':self.x = value - w / 2elif name == 'top':self.y = value + h / 2elif name == 'bottom':self.y = value - h / 2elif name == 'center':self.x, self.y = value[0], value[1]elif name == 'topleft':self.x, self.y = value[0] + w / 2, value[1] + h / 2elif name == 'topright':self.x, self.y = value[0] - w / 2, value[1] + h / 2elif name == 'bottomleft':self.x, self.y = value[0] + w / 2, value[1] - h / 2elif name == 'bottomright':self.x, self.y = value[0] - w / 2, value[1] - h / 2elif name == 'width':self.scale_by(value / w)elif name == 'height':self.scale_by(value / h)elif name == 'size':if self.__dict__['_image'] is not None:key = self.__dict__['_key']self._set_key(key[0], key[1], value[0], value[1], key[4])else:self.__dict__['_w'] = value[0]self.__dict__['_h'] = value[1]elif name == 'speed':self.speedx, self.speedy = value[0], value[1]elif name == 'color':self.__dict__['_image'] = Noneself.__dict__['_key'] = Noneif type(value) is str: value = pygame.Color(value)self.__dict__['_color'] = valueelif name == 'image':self.__dict__['_color'] = Noneif self.__dict__['_key'] is None:self._set_key(value, False, w, h, 0)else:key = self.__dict__['_key']self._set_key(value, *key[1:])else:sys.stderr.write("creating filed named " + name)self.__dict__[name] = valuedef overlap(self, other, padding=0, padding2=None):'''b1.overlap(b1) returns a list of 2 values such that self.move(result) will cause them to not overlapReturns [0,0] if there is no overlap (i.e., if b1.touches(b2) returns Falseb1.overlap(b2, 5) adds a 5-pixel padding to b1 before computing the overlapb1.overlap(b2, 5, 10) adds a 5-pixel padding in x and a 10-pixel padding in y before computing the overlap'''if padding2 is None: padding2 = paddingl = other.left - self.right - paddingr = self.left - other.right - paddingt = other.top - self.bottom - padding2b = self.top - other.bottom - padding2m = max(l, r, t, b)if m >= 0:return [0, 0]elif m == l:return [l, 0]elif m == r:return [-r, 0]elif m == t:return [0, t]else:return [0, -b]def touches(self, other, padding=0, padding2=None):'''b1.touches(b1) returns True if the two SpriteBoxes overlap, False if they do notb1.touches(b2, 5) adds a 5-pixel padding to b1 before computing the touchb1.touches(b2, 5, 10) adds a 5-pixel padding in x and a 10-pixel padding in y before computing the touch'''if padding2 is None: padding2 = paddingl = other.left - self.right - paddingr = self.left - other.right - paddingt = other.top - self.bottom - padding2b = self.top - other.bottom - padding2return max(l, r, t, b) <= 0def bottom_touches(self, other, padding=0, padding2=None):'''b1.bottom_touches(b2) returns True if both b1.touches(b2) and b1's bottom edge is the one causing the overlap.'''if padding2 is None: padding2 = paddingreturn self.overlap(other, padding + 1, padding2 + 1)[1] < 0def top_touches(self, other, padding=0, padding2=None):'''b1.top_touches(b2) returns True if both b1.touches(b2) and b1's top edge is the one causing the overlap.'''if padding2 is None: padding2 = paddingreturn self.overlap(other, padding + 1, padding2 + 1)[1] > 0def left_touches(self, other, padding=0, padding2=None):'''b1.left_touches(b2) returns True if both b1.touches(b2) and b1's left edge is the one causing the overlap.'''if padding2 is None: padding2 = paddingreturn self.overlap(other, padding + 1, padding2 + 1)[0] > 0def right_touches(self, other, padding=0, padding2=None):'''b1.right_touches(b2) returns True if both b1.touches(b2) and b1's right edge is the one causing the overlap.'''if padding2 is None: padding2 = paddingreturn self.overlap(other, padding + 1, padding2 + 1)[0] < 0def contains(self, x, y=None):'''checks if the given point is inside this SpriteBox's bounds or not'''if y is None: x, y = xreturn abs(x - self.x) * 2 < self._w and abs(y - self.y) * 2 < self._hdef move_to_stop_overlapping(self, other, padding=0, padding2=None):'''b1.move_to_stop_overlapping(b2) makes the minimal change to b1's position necessary so that they no longer overlap'''o = self.overlap(other, padding, padding2)if o != [0, 0]:self.move(o)if o[0] * self.speedx < 0: self.speedx = 0if o[1] * self.speedy < 0: self.speedy = 0def move_both_to_stop_overlapping(self, other, padding=0, padding2=None):'''b1.move_both_to_stop_overlapping(b2) changes both b1 and b2's positions so that they no longer overlap'''o = self.overlap(other, padding, padding2)if o != [0, 0]:self.move(o[0] / 2, o[1] / 2)other.move(-o[0] / 2, -o[1] / 2)if o[0] != 0:self.speedx = (self.speedx + other.speedx) / 2other.speedx = self.speedxif o[1] != 0:self.speedy = (self.speedy + other.speedy) / 2other.speedy = self.speedydef move(self, x, y=None):'''change position by the given amount in x and y. If only x given, assumed to be a point [x,y]'''if y is None: x, y = xself.x += xself.y += ydef move_speed(self):'''change position by the current speed field of the SpriteBox object'''self.move(self.speedx, self.speedy)def full_size(self):'''change size of this SpriteBox to be the original size of the source image'''if self.__dict__['_key'] is None: returnkey = self.__dict__['_key']self._set_key(key[0], key[1], 0, 0, key[4])def __repr__(self):return str(self)def __str__(self):return '%dx%d SpriteBox centered at %d,%d' % (self._w, self._h, self.x, self.y)def copy_at(self, newx, newy):'''Make a new SpriteBox just like this one but at the given location instead of here'''return SpriteBox(newx, newy, self._image, self._color, self._w, self._h)def copy(self):'''Make a new SpriteBox just like this one and in the same location'''return self.copy_at(self.x, self.y)def scale_by(self, multiplier):'''Change the size of this SpriteBox by the given factorb1.scale_by(1) does nothing; b1.scale_by(0.4) makes b1 40% of its original width and height.'''if self.__dict__['_key'] is None:self._w *= multiplierself._h *= multiplierelse:key = self.__dict__['_key']self._set_key(key[0], key[1], key[2] * multiplier, key[3] * multiplier, key[4])def draw(self, surface):'''b1.draw(camera) is the same as saying camera.draw(b1)b1.draw(image) draws a copy of b1 on the image proivided'''if isinstance(surface, Camera):if self.__dict__['_color'] is not None:region = self.rect.move(-surface._x, -surface._y)region = region.clip(surface._surface.get_rect())surface._surface.fill(self._color, region)elif self.__dict__['_image'] is not None:surface._surface.blit(self._image, [self.left - surface._x, self.top - surface._y])else:if self.__dict__['_color'] is not None:surface.fill(self._color, self.rect)elif self.__dict__['_image'] is not None:surface.blit(self._image, self.topleft)def flip(self):'''mirrors the SpriteBox left-to-right.Mirroring top-to-bottom can be accomplished byb1.rotate(180)b1.flip()'''if self.__dict__['_key'] is None: returnkey = self.__dict__['_key']self._set_key(key[0], not key[1], *key[2:])def rotate(self, angle):'''Rotates the SpriteBox by the given angle (in degrees).'''if self.__dict__['_key'] is None: returnkey = self.__dict__['_key']self._set_key(key[0], key[1], key[2], key[3], key[4] + angle)_timeron = False
_timerfps = 0def timer_loop(fps, callback):'''Requests that pygame call the provided function fps times a secondfps: a number between 1 and 60callback: a function that accepts a set of keys pressed since the last tick----seconds = 0def tick(keys):seconds += 1/30if pygame.K_DOWN in keys:print 'down arrow pressed'if not keys:print 'no keys were pressed since the last tick'camera.draw(box)camera.display()gamebox.timer_loop(30, tick)----'''global _timeron, _timerfpskeys = set([])if fps > 1000: fps = 1000_timerfps = fps_timeron = Truepygame.time.set_timer(pygame.USEREVENT, int(1000 / fps))while True:event = pygame.event.wait()if event.type == pygame.QUIT: breakif event.type == pygame.KEYDOWN and event.key == pygame.K_ESCAPE: breakif event.type == pygame.KEYDOWN:keys.add(event.key)if event.type == pygame.KEYUP and event.key in keys:keys.remove(event.key)if event.type == pygame.USEREVENT:pygame.event.clear(pygame.USEREVENT)callback(keys)if event.type == pygame.MOUSEBUTTONDOWN:keys.add(event.type)callback(keys)pygame.time.set_timer(pygame.USEREVENT, 0)_timeron = Falsedef pause():'''Pauses the timer; an error if there is no timer to pause'''if not _timeron: raise Exception("Cannot pause a timer before calling timer_loop(fps, callback)")pygame.time.set_timer(pygame.USEREVENT, 0)def unpause():'''Unpauses the timer; an error if there is no timer to unpause'''if not _timeron: raise Exception("Cannot pause a timer before calling timer_loop(fps, callback)")pygame.time.set_timer(pygame.USEREVENT, int(1000 / _timerfps))def stop_loop():'''Completely quits one timer_loop or keys_loop, usually ending the program'''pygame.event.post(pygame.event.Event(pygame.QUIT))def keys_loop(callback):'''Requests that pygame call the provided function each time a key is pressedcallback: a function that accepts the key pressed----def onPress(key):if pygame.K_DOWN == key:print 'down arrow pressed'if pygame.K_a in keys:print 'A key pressed'camera.draw(box)camera.display()gamebox.keys_loop(onPress)----'''while True:event = pygame.event.wait()if event.type == pygame.QUIT: breakif event.type == pygame.KEYDOWN and event.key == pygame.K_ESCAPE: breakif event.type == pygame.KEYDOWN:callback(event.key)if __name__ == "__main__":camera = Camera(400, 400)camera.x = 10b = from_text(40, 50, "Blue", "Arial", 40, "red", italic=True, bold=True)b.speedx = 3b.left += 2b.y = 100b.move_speed()camera.draw(b)camera.display()smurfs = load_sprite_sheet("http://www.flashpulse.com/moho/smurf_sprite.PNG", 4, 4)def tick(keys):if keys:if pygame.K_0 in keys:b.image = smurfs[0]elif pygame.K_1 in keys:b.image = smurfs[1]elif pygame.K_2 in keys:b.image = smurfs[2]elif pygame.K_3 in keys:b.image = smurfs[3]elif pygame.K_4 in keys:b.image = smurfs[4]elif pygame.K_5 in keys:b.image = smurfs[5]elif pygame.K_6 in keys:b.image = smurfs[6]elif pygame.K_7 in keys:b.image = smurfs[7]elif pygame.K_8 in keys:b.image = smurfs[8]elif pygame.K_9 in keys:b.image = smurfs[9]elif pygame.K_a in keys:stop_loop()elif keys:b.image = "http://www.pygame.org/docs/_static/pygame_tiny.png"b.full_size()b.rotate(-5)b.center = camera.mouseb.bottom = camera.bottomcamera.draw(b)camera.display()timer_loop(30, tick)
这篇关于python 自制黄金矿工游戏(设计思路+源码)的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!