Project1

标题: 请问如何检测角色的图片与怪物的图片重叠? [打印本页]

作者: kojoy    时间: 2010-6-29 21:03
提示: 作者被禁止或删除 内容自动屏蔽
作者: 紫苏    时间: 2010-7-2 11:12
碰撞检测有很多前辈们留给我们的现成算法,这些在网上一搜就能找到,比较常用的方法是把你的 Sprite 用很多顶点组成的数个三角形拼接起来,然后检测碰撞的时候就是检测三角形的相交。当然这只是一个近似的检测,但精确度可以由三角形的个数来调节
作者: 古明地馨    时间: 2010-7-2 11:14
提示: 作者被禁止或删除 内容自动屏蔽
作者: 紫苏    时间: 2010-7-2 11:24
目前网上流行的一些高端碰撞检测算法我也没实践过,只和之前做赛车游戏的叶子讨论过一点,很想找机会学习一下
楼主的 FPS 掉到 20,不知道是用的什么算法?可以发出来一起探讨,共同改进
作者: kojoy    时间: 2010-7-2 11:29
提示: 作者被禁止或删除 内容自动屏蔽
作者: 古明地馨    时间: 2010-7-2 11:32
提示: 作者被禁止或删除 内容自动屏蔽
作者: david50407    时间: 2010-7-2 11:54
可以扩展Sprite(或Bitmap)类
在读取图片时建立一个空阵列(大小与图片大小相当)
然后把透明(false) 或非透明(true) 写入此阵列
到时再一一比对会比临时读取像素还快
作者: kojoy    时间: 2010-7-2 12:01
提示: 作者被禁止或删除 内容自动屏蔽
作者: 紫苏    时间: 2010-7-2 12:21
回复 kojoy 的帖子

不需要判断点,直接判断矩形相交即可~如果你的图形能用矩形逼近的话,那就是最简单的了,比三角形简单
作者: kojoy    时间: 2010-7-2 12:30
提示: 作者被禁止或删除 内容自动屏蔽
作者: david50407    时间: 2010-7-2 16:40
RGE这样写
  1. include RGE

  2. RGE.init

  3. logo = Sprite.new
  4. logo.bitmap = Bitmap.new("logo.png") #这是一张图
  5. logo.ox = logo.bitmap.width / 2
  6. logo.oy = logo.bitmap.height / 2
  7. logo.x = 50
  8. logo.y = 50

  9. logo2 = Sprite.new
  10. logo2.bitmap = Bitmap.new("logo2.png") #这是另一张图
  11. logo2.ox = logo.bitmap.width / 2
  12. logo2.oy = logo.bitmap.height / 2
  13. logo2.x = 200
  14. logo2.y = 40

  15. # 建立映射表
  16. map = Array.new
  17. map[0] = Array.new
  18. map[1] = Array.new
  19. for i in 0...logo.bitmap.width
  20.   map[0][i] = Array.new
  21.   for j in 0...logo.bitmap.height
  22.     map[0][i][j] = (logo.bitmap.get_pixel(i, j).alpha == 0) #判断是否透明
  23.   end
  24. end
  25. for i in 0...logo2.bitmap.width
  26.   map[1][i] = Array.new
  27.   for j in 0...logo2.bitmap.height
  28.     map[1][i][j] = (logo2.bitmap.get_pixel(i, j).alpha == 0) #判断是否透明
  29.   end
  30. end


  31. def cover?(map1, x1, y1, map2, x2, y2)
  32.   map1_w = map1.length
  33.   map1_h = map1[0].length
  34.   map2_w = map2.length
  35.   map2_h = map2[0].length
  36.   for i in 0...map1_w
  37.     next unless (i + x1).between?(x2, x2 + map2_w - 1)
  38.     for j in 0...map1_h
  39.       next unless (j + y1).between?(y2, y2 + map2_h - 1)
  40.       return (map1[i][j] && map2[i + x1 - x2][j + y1 - y2])
  41.     end
  42.   end
  43.   return false
  44. end
  45. Graphics.update
  46. if cover?(map[0], logo.x - logo.ox, logo.y - logo.oy, map[1], logo2.x - logo2.ox, logo2.y - logo2.oy)
  47.   p "cover"
  48. end

  49. begin
  50.   Graphics.update
  51.   Input.update
  52. end until Input.press?(13)
复制代码

作者: kojoy    时间: 2010-7-2 16:55
提示: 作者被禁止或删除 内容自动屏蔽
作者: 紫苏    时间: 2010-7-3 01:28
回复 kojoy 的帖子

设:
(x11, y11) 为矩形1左上角坐标,(x12, y12) 为矩形1右下角坐标
(x21, y21) 为矩形1左上角坐标,(x22, y22) 为矩形1右下角坐标
(坐标为屏幕空间坐标)
if x12 < x21 then 不相交,矩形1在矩形2左边
else if x11 > x22 then 不相交,矩形1在矩形2右边
else if y12 < y21 then 不相交,矩形1在矩形2上面
else if y11 > y22 then 不相交,矩形1在矩形2下面
else 矩形1矩形2相交

回复 古明地馨 的帖子

哦~包围盒的兄弟似乎很多呀,没怎么研究过……如果是基于像素运算的不就完全可以精确判断了吗……以前也用过四叉树来表示 2D 场景,可以做一些简单的碰撞检测。3D 的 BSP 就是判断凸集和平面的相交了吧,不知和八叉树相比如何?

另外 david 的那个算法不知是不是八云在3楼说的那个像素算法,这个如果 get_pixel 是和 RM 的一样基于 GDI 的话,那慢是肯定的了,因为 get_pixel(以及 set_pixel)本身就很慢。位图资源在内存中初始是可被内存管理器移动的,如果 CPU 需要访问一块内存,那需要先锁定。get_pixel 和 set_pixel 都会先锁定位图资源,然后更新像素,最后解锁,这个过程做一次没什么,放在循环里面做就能看到速度的差别。解决方法也不少,第一种是在 set/get_pixel 之前预先通过 LockBits 锁定位图数据,然后再逐点 set/get_pixel,循环结束后解锁,这样就不会每次调用 set/get_pixel 都去锁定/解锁了;第二种是通过 GetBitmapBits 把位图数据一次性拷贝到系统内存的缓冲区中,然后直接在这个缓冲区中随机访问,这样效率也是很高
作者: 古明地馨    时间: 2010-7-3 09:00
提示: 作者被禁止或删除 内容自动屏蔽
作者: david50407    时间: 2010-7-3 09:12
回复 紫苏 的帖子

大可把這些映射表先存成一個檔
到時再讀取也不錯 = =b
作者: 古明地馨    时间: 2010-7-3 09:19
提示: 作者被禁止或删除 内容自动屏蔽
作者: 紫苏    时间: 2010-7-3 10:19
回复 古明地馨 的帖子

关于那个不透明数据的缓冲区在空间上其实还可以优化的,由于只需要一个布尔数据,所以用一个位元来保存就行了,而不需要一个 32 位的整型指针(Ruby 的动态数组)
作者: 古明地馨    时间: 2010-7-3 10:24
提示: 作者被禁止或删除 内容自动屏蔽
作者: 紫苏    时间: 2010-7-3 10:44
回复 古明地馨 的帖子

背景是指什么? o.o
david 的方法只是需要某个像素点透明或者不透明的情况,所以只需要 0 或者 1,然后最后可以每 64 位与运算一下,如果有任何一位是 1 都表示有碰撞
作者: 古明地馨    时间: 2010-7-3 10:55
提示: 作者被禁止或删除 内容自动屏蔽




欢迎光临 Project1 (https://rpg.blue/) Powered by Discuz! X3.1