马上注册,结交更多好友,享用更多功能,让你轻松玩转社区。
您需要 登录 才可以下载或查看,没有账号?立即注册
×
本帖最后由 立笔犊 于 2020-3-4 00:26 编辑
如题。
依然是给《罗曼圣诞探案集》做的飞镖。
演示效果如下:
演示视频.zip
(104.65 KB, 下载次数: 55)
具体要求如下:
1、模拟扔飞镖手抖的效果,飞镖发射前会不断晃动。
2、飞镖扔中镖盘的不同位置得分不同,具体分数写在了最外圈上,并且外圈红色2倍,内圈红色3倍。
这是用RenPy中的用户自定义可视组件实现的,需要看完相关renpy文档、有一定python面向对象基础并尝试过才可能完全理解。
一、写一个飞镖类Dart继承可视组件renpy.Displayable类,按文档中的要求重写几个父类方法,再暴露几个函数接口,实例化出对象my_dart。
[RenPy] 纯文本查看 复制代码 init python:
import math,random,time,pygame
from threading import Timer
class Dart(renpy.Displayable):
def __init__(self, child, **kwargs):
# 向renpy.Displayable构造器传入额外的特性(property)。
super(Dart, self).__init__(**kwargs)
# 子组件。
self.child = renpy.displayable(child)
# 子组件的宽度和高度。
self.width = 0
self.height = 0
###与位置有关的参数###
# 靶心的位置
self.aim_x = 639
self.aim_y = 249
# 飞镖当前实际的位置
self.x = 639
self.y = 250
###与震动有关的参数###
self.tiny_time = 0.04 # 多久刷新一次位置,越大刷新得越快
self.d_default = 6 # 每次刷新的默认偏移量,越大默认误差越大
self.d_mouse = 2 # 鼠标偏移量,越大鼠标的影响越大
###与记分有关的参数###
self.score = 0 # 所得的分数
# 飞镖当前是否开始运动
self.shaking = False
def render(self, width, height, st, at):
"""可视组件的渲染函数,用于刷新组件的显示"""
render = renpy.Render(width,height)
render.place(self.child, self.x, self.y,width,height)
return render
def event(self, ev, x, y, st):
"""不需要事件,但是继承必须重写"""
return self.child.event(ev, x, y, st)
def shake(self):
"""每次的轻微移动,自带偏差"""
d1=self.d_default
d2=self.d_mouse
while(self.shaking):
# 误差颤动
self.x+=random.randint(-d1,d1)
self.y+=random.randint(-d1,d1)
# 鼠标控制
if random.randint(0,1):
x,y = renpy.get_mouse_pos()
self.x += d2 if(x>self.x) else -d2
self.y += d2 if(y>self.y) else -d2
# 显示与循环
renpy.redraw(self, 0)
time.sleep(self.tiny_time)
def start_shake(self):
"""对外接口之一,让飞镖动起来"""
# 当前没有开始才能开始,否则可能重复开始造成过多定时器
if self.shaking == False:
self.shaking = True
# 用Timer达到多线程的效果
self.t = Timer(0, self.shake)
self.t.start()
def debug_shoot(self):
"""测试用,飞镖位置完全变为鼠标位置,并计算得分"""
x,y = renpy.get_mouse_pos()
self.x = x
self.y = y
# 显示与循环
renpy.redraw(self, 0)
self.get_score()
def end_shake(self):
"""对外接口之一,让飞镖停止运动"""
self.shaking = False
renpy.redraw(self, 0)
def get_score(self):
"""对外接口之一,根据飞镖位置计算得分"""
"""注意当计算得分的时候就需要停了"""
self.end_shake()
dx = self.x-self.aim_x
dy = self.aim_y-self.y
dist = math.sqrt( dx**2 + dy**2 )
# 中心环
if dist < 9:
self.score=100
# 中心环2
elif dist < 25:
self.score=50
# 脱靶
elif dist > 180:
self.score=0
# 扇形区间
else:
k=1
if 95<=dist<=114:
k=3
if 159<=dist<=180:
k=2
dg = math.atan2(dx,dy)/math.pi*180
dg += 180
dg /= 18
dg += 0.5
score_list=[3,19,7,16,8,11,14,9,12,5,20,1,18,4,13,6,10,15,2,17,3]
self.score=score_list[int(dg)]*k
def reset_dart(self):
# 最后要把位置放回原点,便于下次开始射
self.x = self.aim_x
self.y = self.aim_y
my_dart = Dart("dart.png",offset=(-43,-44))
暴露出来的接口是:
start_shake:让飞镖开始抖动
end_shake:让飞镖停止抖动
get_score:根据飞镖当前位置计算得分
二、扔飞镖的界面
[RenPy] 纯文本查看 复制代码 screen darts():
# 飞镖
default state=0
imagebutton:
idle "dart_empty"
action [my_dart.get_score,SetScreenVariable("state",1)]
add my_dart
if state:
timer 1.0 action Return()
# 测试用工具栏
# text "分数:[score]"
# hbox:
# align (0.5,1.0)
# spacing 20
# textbutton "抖!" action my_dart.start_shake
# textbutton "停!" action my_dart.end_shake
# textbutton "射!" action [my_dart.get_score,Return()]
基本就是把整个背景作为一个imagebutton,按了以后就my_dart.get_score来算一下分数,然后设置一下界面变量来启动计时,射完飞镖1秒钟后返回结果。
底下有被注释掉的工具栏,主要是用来测试得分精准性和快速模拟多次扔飞镖的。
这个东西仍然是(第四次放送)我给《罗曼圣诞探案集》做的,花了一个中午一个下午半个晚上,扔飞镖都扔得我头晕了。我是因为这个游戏才了解到的RenPy,主创也是我的好朋友。 打个小广告。 《罗曼圣诞探案集》,使用RenPy引擎制作,已上架steam,目前好评率97%,特别好评发售中!
|