赞 | 15 |
VIP | 0 |
好人卡 | 0 |
积分 | 19 |
经验 | 16801 |
最后登录 | 2024-7-10 |
在线时间 | 403 小时 |
Lv3.寻梦者
- 梦石
- 0
- 星屑
- 1939
- 在线时间
- 403 小时
- 注册时间
- 2015-8-30
- 帖子
- 395
|
3楼
楼主 |
发表于 2016-4-30 21:56:00
|
只看该作者
本帖最后由 有丘直方 于 2016-5-1 07:14 编辑
- #===============================================================================
- # 判断精灵触碰用的脚本
- # 目前没有自行测试过。
- # 注释有点乱……但是看着方便
- #-------------------------------------------------------------------------------
- # Sprite 精灵类
- #===============================================================================
- class Sprite
- #-----------------------------------------------------------------------------
- # 判断是否接触——按照矩形计算,也是最简单的算法。
- # 这个方法是自己最能想到的。
- # 返回值:true表示触碰,false表示没有触碰
- # 参数:other:判断接触的另外一个精灵
- #-----------------------------------------------------------------------------
- def touch_rect(other)
- self.ox, self.oy = 0 # 首先确保原点在左上角
- if self.x.between?(other.x = self.bitmap.width, # 判断self的x坐标是否过于靠右
- other.x + other.bitmap.width) # 判断self的x坐标是否过于靠左
- # 如果self的x坐标适中,那么继续判断
- if self.y.between?(other.y = self.biemap.height, # 与之前相似的办法判断y坐标
- other.y + other.bitmap.height, # 同上……
- # 如果y坐标适中,那么确定触碰
- return true # 返回true
- else # 如果y坐标的条件不满足触碰
- # 那么确定没有触碰
- return false # 返回false
- end # y坐标判定结束
- else # 如果x坐标的条件不满足触碰
- # 同样,确定没有触碰
- return false # 返回false
- end # x坐标判定结束
- end # touch_rect方法定义结束
- #-----------------------------------------------------------------------------
- # 判断是否接触——按照圆形计算,略微有点复杂,因为涉及到四则运算之外。
- # 这个方法是结合了taroxd和冷峻逸的方法想出来的……
- # 返回值:true表示触碰,false表示没有触碰
- # 参数:other:判断接触的另外一个精灵
- #-----------------------------------------------------------------------------
- def touch_circle(other)
- self.ox, self.oy = 0 # 确保原点在左上角
- bool = nil # 先创建一个临时变量,后期返回它
- num1 = Math.sqrt((x1 - x2) ** 2 + (y1 - y2) ** 2) # 比较参数1:勾股平方和
- num2 = self.bitmap.width / 2 + other.bitmap.width / 2 # 比较参数2:半径和平方
- bool = (num1 <= num2) # 进行比较
- # 这里其实用到了勾股定理。
- # num1其实是在使用勾股定理通过两条直角边来计算斜边
- # num2则是利用圆半径永远相等的定理计算圆心的距离
- # 那么很显然,如果num1的长度不超过num2,两个精灵就相碰了
- return bool # 返回运算结果。
- # 令我感到很奇怪的是这个方法的定义居然比touch_rect方法短
- end # touch_circle方法定义结束
- #-----------------------------------------------------------------------------
- # 判断是否接触——按照非透明部分计算,很复杂,效率低。
- # 这个方法是冷峻逸最先提出,也是被最先否定的,因为效率太低了
- # 返回值:true表示触碰,false表示没有触碰
- # 参数:other:判断接触的另外一个精灵
- #-----------------------------------------------------------------------------
- def touch_opacity(other)
- return false unless self.touch_rect(other) # 如果没有矩形触碰则直接返回false
- self.ox, self.oy = 0 # 惯例,让原点在左上角
- tab1 = Table.new(self.bitmap.width, self.bitmap.height) # 这个二维表格是用来挨个判断不透明度用的
- for x in 0...(self.bitmap.width) # 用循环挨个获取像素点的Color
- for y in 0...(self.bitmap.height) # 分别用x、y两个临时变量接受像素坐标
- tab1[x, y] = (self.bitmap.get_pixel(x, y).alpha > 0) # 在这里获取像素点是否透明
- end # 纵向获取结束
- end # 横向获取结束
- tab2 = Table.new(other.bitmap.width, other.bitmap.height) # 这下轮到了判断触碰的精灵
- for x in 0...(other.bitmap.width); for y in 0...(other.bitmap.height) # 循环
- tab2[x, y] = (other.bitmap.get_pixel(x, y).alpha > 0) # 在这里获取像素点是否透明
- end; end # 颜色获取结束
- for x in 0...(self.bitmap.width); for y in 0...(self.bitmap.height) # 循环
- if tab1[x, y] and tab2[x, y] # 如果相对于精灵的位置相同的两点都不透明
- if self.x + x == other.x + x and self.y + y == other.y + y # 如果相对于游戏程序窗口的位置也相同
- # 确定两个精灵相碰
- return true # 返回true
- end; end # 分歧结束
- end # 循环结束
- return false # 如果到现在还没有return,确定还没有触碰,返回false
- end # touch_opacity方法定义结束
- end # Sprite类定义结束
- # 因为没有测试,所以能不能正常运行还不知道。不过应该可以了。
- # 第三种方法因为用到了很多循环,所以效率很低,不建议使用。
复制代码- class Sprite
- def touch_rect(other)
- self.ox, self.oy, other.ox, other.oy = 0
- return (self.x.between?(
- other.x - self.bitmap.width,
- other.x + other.bitmap.width
- ) and
- self.y.between?(
- other.y - self.biemap.height,
- other.y + other.bitmap.height
- )
- )
- end
- def touch_circle(other)
- return false unless self.touch_rect(other)
- self.ox, self.oy, other.ox, other.oy = 0
- return (
- Math.sqrt((x1 - x2) ** 2 + (y1 - y2) ** 2) <=
- self.bitmap.width / 2 + other.bitmap.width / 2
- )
- end
- def touch_opacity(other)
- return false unless self.touch_rect(other)
- self.ox, self.oy, other.ox, other.oy = 0
- tab_self = Table.new(self.bitmap.width, self.bitmap.height)
- for x in 0...(self.bitmap.width)
- for y in 0...(self.bitmap.height)
- tab_self[x, y] = (self.bitmap.get_pixel(x, y).alpha > 0)
- end
- end
- tab_other = Table.new(other.bitmap.width, other.bitmap.height)
- for x in 0...(other.bitmap.width)
- for y in 0...(other.bitmap.height)
- tab_other[x, y] = (other.bitmap.get_pixel(x, y).alpha > 0)
- end
- end
- ary = []
- for self_x in 0...(self.bitmap.width)
- for self_y in 0...(self.bitmap.height)
- for other_x in 0...(other.bitmap.width)
- for other_y in 0...(other.bitmap.height)
- ary += (tab_self[self_x, self_y] and
- tab_other[other_x, other_y] and
- self.x + self_x == other.x + other_x and
- self.y + self_y == other.y + other_y
- )
- end
- end
- end
- end
- return ary.include?(true)
- end
- end
复制代码- # 测试代码如下(此代码经过测试,没有BUG):
- class Sprite
- def touch_rect(other)
- return (self.x.between?(
- other.x - self.bitmap.width,
- other.x + other.bitmap.width
- ) and
- self.y.between?(
- other.y - self.bitmap.height,
- other.y + other.bitmap.height
- )
- )
- end
- end
- module SceneManager
- def self.first_scene_class
- return Scene_Test
- end
- end
- class Scene_Test < Scene_Base
- def start
- super
- @test = Sprite.new
- @test.bitmap = Bitmap.new(32, 32)
- @test.bitmap.fill_rect(0, 0, 32, 32, Color.new(255, 0, 0))
- @test.y = (640 - 32) / 2
- @sprite = Sprite.new
- @sprite.bitmap = Bitmap.new(12, 416)
- @sprite.bitmap.fill_rect(0, 0, 12, 416, Color.new(255, 255, 255))
- @sprite.x = 544 - 12 - 12
- end
- def update
- super
- @test.update
- @sprite.update
- @test.x += 1
- if @test.touch_rect(@sprite)
- p 'OK.'
- SceneManager.goto(Scene_Title)
- end
- end
- def terminate
- super
- @test.bitmap.dispose
- @sprite.bitmap.dispose
- @test.dispose
- @sprite.dispose
- end
- end
复制代码 |
|