Rice Rock
先翻译评分要点,然后一点点翻译程序实现过程
process_sprite_group
看论坛,找到了答案
现在做撞击,看论坛,找到了答案。
如何产生一组导弹,岩石碰撞后不能再生
已经可以产生一组导弹了,但是导弹寿命要调整
碰撞后岩石消失,但是分数没有增加,岩石消失不再出现
分数已经增加啦,这个我自己做出来的
Mini-project description - RiceRocks (Asteroids)
开发过程
要有多重火箭和多重导弹。飞船撞到岩石会丢一条命, 导弹打到岩石得一分, 你要更新得分和生命情况,在合适的时候结束游戏。 .当发生碰撞的时候你可以选择添加爆炸动画
Tip #1 - Spawning rocks多重岩石
为了控制多重岩石,用rock_group代替 a_rock
.在rock_spawner里面,你应该产生一个本地的a_rock的副本并添加到全局集合rock_group里面。 为了避免超过12个岩石,你可以使用一个基于rock_group长度的测试。 为了测试你的代码,你可以添加一个for循环到draw handler里面以这种形式: 对每个在rock_group里面的岩石, 画出那个岩石。这个draw以后将被放到 process_sprite_group
里面在第一部分的最后一步
Phase one - 多重岩石
- 用rock_group代替a_rock.复位岩石组成空的集合set. 你的rock spawner产生一个新岩石(Sprite的一个对象实例) 并添加到rock_group里面
- 修改你的rock spawner使得屏幕里面的岩石数量有上限。我们建议最多12个太多岩石的话游戏会不那么好玩而且动画会明显变慢。
- 建立一个process_sprite_group函数. 这个函数应该有一个集合(set)和画布, 并调用update和draw函数对每个群组里面的sprite.
- 在draw handler里面调用process_sprite_group功能在rock_group里面
Phase two - 撞击
这部分,你要检测飞船和岩石的撞击。 发生撞击,岩石要毁坏并且玩家要丢失生命. 为了完成飞船岩石撞击:你要这么做:
- 在Sprite类里面添加一个collide功能。 这个应该有个other_object并返回True,如果有撞击返回
False
. 目前,这个其他对象将一直是你的飞船, 但我们也想要能用这个colide方法来侦测跟导弹的撞击。 可以使用这两个对象的半径侦测撞击。这需要你完成get_position
和get_radius在Sprite和get_radius. - 完成group_collide函数。这个函数要有个set
group
和一个spritother_object
并经检查在other_object和group里的元素的撞击。如果有撞击, 撞击对象应该从group里面移除。为了避免移除你正在迭代的set(可能产生一个严重的bug), 通过set(group)
创建一个副本迭代. 这个函数应该返回True
或者False取决于是否有撞击。确定使用第一部分的collide方法 在sprites在group里面来完成这个任务。 - 在draw handler里面使用group_collide判定是否飞船撞击到岩石.要是这样,减少一条生命值。 现在你可以有负的生命值
现在你可以玩这个躲避岩石的游戏了。
Phase three - 导弹
在这部分你要产生一个导弹组,在按空格的时候产生新的导弹加入导弹组里面。需要如下步骤:
- 删掉a_missile并用missile_group代替。 复位导弹组为空组。修改my_ship里面的shoot函数来创造新导弹。 (一个Sprite类里面的实例) 并添加到missile_group里面. , 如果你用模板的代码,每次生产导弹的时候开火的声音应该自动播放
- 在draw handler里面,使用你的process_sprite_group函数来process
missile_group
. 当你发射导弹的时候,你会注意到他们永远在飞。 为了修正这个,我们需要修改Sprite类和process_sprite_group. - 在Sprite类里面的update函数。每次调用
update
,sprite要增加。如果寿命大于或者等于sprite的生命,我们要删掉它。. 所以return返回False
(意味着我们要保留它) 如果age少于寿命并且True
(意味着我们要删掉它) 否则. - 修改process_sprite_group来检查返回的值对sprites. 如果返回
True
, 从group里面删掉sprite。再一次 你将希望迭代sprite群的副本在process_sprite_group.来避免删掉从相同的set在你迭代的。
Phase four - Collisions revisited 现在当导弹撞到岩石的时候要毁掉岩石。我们不能用group_collide
, 因为我要检查两个group的碰撞。我们要做的就是加一个新的函数 :
- 完成最后一个函数
group_group_collide
,啥呢,将两个grops的对象作为输入.group_group_collide
应该使用一个for循环在第一组副本元素迭代,然后第二组的所有元素调用group_collide.group_group_collide应该返回第一组元素跟第二在元素撞击并删除第一组中的这些元素。 你可能会发现set的discard
功能在这里很有用。 - 在draw handler里面调用
group_group_collide
来检测导弹/岩石的碰撞。 根据导弹撞击的数目增加分数。
Phase five - Finish it off完成它
基本完了,再添加一点
- 添加代码到draw handler里面 , 要是生命数变成0了,游戏重置,并且出现启动画面.尤其, set the 设置started为False, 毁掉所有岩石并阻止任何岩石生成,直到游戏重新开始。
- 当游戏开始/重新开始. 确保生命数和分数也重置。开始生成岩石 .播放/重新开始加载在程序模板的soundtrack变量里面背景音乐
- 当你生成岩石的时候,你想让他们跟你的飞船有一定距离,否则岩石在你头上生成的时候你就挂了。.那就不好玩了.一个简单的方法来实现这个效果是这样的:如果生的岩石跟飞船太近,忽视岩石生产事件。
- 试着根据分数变化岩石的速度来将游戏难度提高
- 调整一些参数,以使游戏按我们的想法运行
额外的
- ,在Sprite类的draw功能里面,检查
self.animated
是否是True .如果是的话根据age选择正确的碎片.图片是平铺的.如果self.animated是False
,应该像以前一样画sprite. - 创建一个
explosion_group
,全局变量并复位它成为一个空集合。 - 在group_collide里面,如果有碰撞,创建一个新的爆炸(一个Sprite类的实例)并添加到explosion_group里面,确认每个爆炸都播放爆炸声音。
- 在draw handler里面使用process_sprite_group表达explosion_group.
Grading rubric - 13 pts (scaled to 100 pts)
- 1 pt - 程序产生很多岩石。
- 1 pt - 程序正确的判定飞船是否跟岩石相撞
- 1 pt - 飞船与岩石相撞,该岩石会消失
- 1 pt - 飞船撞上岩石生命丢失一条
- 1 pt - 程序产生多重导弹
- 1 pt - 发射导弹的时候播放导弹发射声音
- 1 pt - 如果导弹没有击中岩石,导弹在固定的时间后会消失
- 1 pt - 程序可以正确的判定导弹和岩石是否碰撞
- 1 pt - 相互碰撞的导弹和岩石会消失
- 1 pt - 导弹岩石相撞分数要更新
- 1 pt - 当生命数变成0,显示启动画面并且所有的岩石要消失
- 1 pt - 当点击启动画面,生命重置为3,分数重置为0,并启动背景音乐。
- 1 pt - 游戏只有在启动画面不存在还有游戏正在进行的时候产生岩石。
# 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
zjcs = 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") # 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 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 a_missile, 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):
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
self.age += 1
if self.age < self.lifespan:
return False
else:
return True def get_position(self):
return self.pos
def get_radius(self):
return self.radius def collide(self, other_object): if dist(self.pos, other_object.get_position()) <= self.radius + other_object.get_radius():
return True
else:
return False
#参考https://class.coursera.org/interactivepython-005/forum/thread?thread_id=5328 def group_collide(group, other_object):
global collided
collided = False
group_copy = list(group)
for item in group_copy:
if item.collide(other_object) == True:
collided = True
group.discard(item)
return collided def group_group_collide(group1, group2):
global zjcs
group1_copy = list(group1)
for i in group1_copy:
if group_collide(group2, i) == True:
group1.discard(i)
zjcs += 1
return True # 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):
timer.start()
global started
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
soundtrack.rewind()
soundtrack.play() def draw(canvas):
global time, started, lives, score, zjcs, 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")
if group_collide(rock_group, my_ship) == True:
lives -= 1
if lives < 1:
started = False
lives = 3
score = 0
zjcs = 0
rock_group = set([])
timer.stop()
#number -= 1
#canvas.draw_text(str(lives), [50, 80], 22, "White")
#canvas.draw_text(str(score), [680, 80], 22, "White")
if group_group_collide(missile_group, rock_group) == True:
score = zjcs * 10 # draw ship and sprites
my_ship.draw(canvas)
#a_rock.draw(canvas)
process_sprite_group(canvas,rock_group)
process_sprite_group(canvas,missile_group)
#for n in rock_group:
# n.draw(canvas)
#a_missile.draw(canvas)注释掉这一行,导弹就不是一直存在了 # update ship and sprites
my_ship.update()
#a_rock.update()?????????????
#a_missile.update() # 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())
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") # timer handler that spawns a rock
def rock_spawner():
global a_rock, rock_group, zjcs
rock_pos = [random.randrange(0, WIDTH), random.randrange(0, HEIGHT)] rock_vel = [random.random() * .6 - .3, random.random() * .6 - .3]
if zjcs > 5:#得分超过5,速度加快
rock_vel = [random.random() * 6 - .3, random.random() * 6 - .3]
rock_avel = random.random() * .2 - .1
a_rock = Sprite(rock_pos, rock_vel, 0, rock_avel, asteroid_image, asteroid_info)
#rock_group.add(a_rock)
if len(rock_group) < 13 and dist(rock_pos, my_ship.pos) > 150:
rock_group.add(a_rock) def process_sprite_group(canvas, group):
#if a_missile.update == True:
#missile_group.remove(a_missile)
for m in list(group):
#m.update()
if m.update() == True:
missile_group.remove(m)
m.draw(canvas) # 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.stop()
frame.start()
Rice Rock的更多相关文章
- ural 2069. Hard Rock
2069. Hard Rock Time limit: 1.0 secondMemory limit: 64 MB Ilya is a frontman of the most famous rock ...
- POJ - 2339 Rock, Scissors, Paper
初看题目时就发了个错误,我因为没有耐心看题而不了解题目本身的意思,找不到做题的突破口,即使看了一些题解,还是没有想到方法. 后来在去问安叔,安叔一语道破天机,问我有没有搞清题目的意思,我才恍然大悟,做 ...
- ROCK 聚类算法
ROCK (RObust Clustering using linKs) 聚类算法是一种鲁棒的用于分类属性的聚类算法.该算法属于凝聚型的层次聚类算法.之所以鲁棒是因为在确认两对象(样本点/簇)之间 ...
- HDU 4884 TIANKENG’s rice shop (模拟)
TIANKENG's rice shop 题目链接: http://acm.hust.edu.cn/vjudge/contest/123316#problem/J Description TIANKE ...
- TIANKENG’s rice shop
Problem Description TIANKENG managers a pan fried rice shop. There are n kinds of fried rice numbere ...
- 1056. Mice and Rice (25)
时间限制 30 ms 内存限制 65536 kB 代码长度限制 16000 B 判题程序 Standard 作者 CHEN, Yue Mice and Rice is the name of a pr ...
- HDOJ(HDU) 2164 Rock, Paper, or Scissors?
Problem Description Rock, Paper, Scissors is a two player game, where each player simultaneously cho ...
- Mini-project # 1 - Rock-paper-scissors-___An Introduction to Interactive Programming in Python"RICE"
Mini-project description - Rock-paper-scissors-lizard-Spock Rock-paper-scissors is a hand game that ...
- PAT1056:Mice and Rice
1056. Mice and Rice (25) 时间限制 100 ms 内存限制 65536 kB 代码长度限制 16000 B 判题程序 Standard 作者 CHEN, Yue Mice an ...
随机推荐
- java写入文件的几种方法分享
转自:http://www.jb51.net/article/47062.htm 一,FileWritter写入文件 FileWritter, 字符流写入字符到文件.默认情况下,它会使用新的内容取代所 ...
- tiledmap2
1 1.1 将tiledmap 保存为xml格式 1.2 在unity当中设置摄像机为"Orthogonal", 1.3 拖拽tiledmap prefab从project视图到H ...
- HTMl5/CSS3/Javascript 学习推荐资源
HTMl5/CSS3/Javascript 学习推荐资源 前端的定义应该是数据内容的展示,在国内大家都觉得前端只是HTML+CSS+Javascript,但是实际上与展示有关的都是前端,所以Ruby/ ...
- 【BZOJ】1503: [NOI2004]郁闷的出纳员(Splay)
http://www.lydsy.com/JudgeOnline/problem.php?id=1503 这题没有看题解就1a了-好开心,, 其实后面去看题解发现他们的都很麻烦,其实有种很简单的做法: ...
- ECMAScript继承
继承的定义 ECMAScript 实现继承可以从父类入手,所有开发者定义的类都可作为父类,出于安全考虑,本地类和宿主类不能作为父类,因为容易收到恶意攻击 创建只是用于给子类提供通用函数的父类被看作抽象 ...
- Mysql 学习
一.ubuntu下mysql的安装: 通过sudo apt-get install mysql-server 完成: 然后可以通过/etc/init.d/mysql 进行start/stop/rest ...
- Java实现队列
class Element{ int id; String name; Element(int a,String n){ id=a;name=n; } } class SeqQueue{ int fi ...
- ITK 3.20.1 VS2010 Configuration 配置
Download ITK 3.20.1 Download VS2010 Download CMake 3.2.0 I assume you've already installed VS2010 an ...
- StereoBM::disp12MaxDiff Crash the Release
Initializing "cv::StereoBM bm.state->disp12MaxDiff" should be careful, inappropriate va ...
- 支持nmap批量漏洞扫描的script
NSE脚本,会在NMAP扫描时,通过-sV发现的端口详细信息对应到CVE相应的漏洞: nmap -sS -sV --script=vulscan www.scip.ch -p25 下面是该脚本的说明和 ...