Project1

标题: 【4月13日更新】≮炸弹人≯【教程、范例,手稿】 - 人人可 [打印本页]

作者: end55rpg    时间: 2012-4-4 14:10
标题: 【4月13日更新】≮炸弹人≯【教程、范例,手稿】 - 人人可
本帖最后由 end55rpg 于 2012-5-6 21:43 编辑

让我们来学着做一个炸弹人游戏吧!


4月4号                                                               

首先,不要考虑效率问题。
然后来确定制作的列表吧




1.PP爆炸可以用动画的形式
(不足处:动画会建立至少15个sprite,影响移动时候的流畅。)
2.泡泡事件的制作内容
(需要涉及爆炸范围的碰撞检查:如事件,图块通行)
3.敌人的设置




目前就这些吧,开工!

遵循一个规律:先把简单的做好再慢慢完善:
泡泡爆炸时候威力我们先设为一个定值吧,就取2吧,也就是说泡泡爆炸的范围如下:
       ○
       ○
○○ X ○○
       ○

       ○
  1. $power = 2 #威力设置为2
复制代码
现在制作泡泡了吧
1.先设置好图像(随便)
2.当按下C(空格)就会放炮所以如下:


3.如图设置好后,必须要把事件移动到主角位置上并显示图像
所以我们可以在按下空格后切换事件页:
在第一个事件页中我们必须把泡泡传送过去:

其实红框中的部分可以替代为:
  1. x = $game_player.x                 #代入角色X坐标
  2. y = $game_player.y                 #代入角色Y坐标
  3. id = @event_id                         #获取本事件ID
  4. event = $game_map.events[id]#用ID获取本事件
  5. event.moveto(x,y)                   #移动到指定位置
复制代码
4.继续在第2张事件页里做,要勾一些选项如下图:

5.看完图了吧,然后进入3事件页,我们真正的制作就开始了!!

看完图片了吧?
下面讲解一下方块中的脚本:


  1. #自己的坐标
  2. ox = $game_map.events[@event_id].x
  3. oy = $game_map.events[@event_id].y
  4. #遍历地图所有事件
  5. for event in $game_map.events.values
  6. #获取事件XY
  7. x = event.x
  8. y = event.y
  9. if (x - ox).abs <= 2 and (y - oy).abs <= 2
  10. event.erase
  11. end
  12. end
复制代码
for event in $game_map.events.values这一句的意思是循环查询地图上的事件,
用来判断事件是否被炸。
(如果地图上事件越多查询就会越久,优化方案以后说明)
if (x - ox).abs <= 2 and (y - oy).abs <= 2
event.erase
end
这一句可能较难理解吧。
翻译过来是:
如果查询事件的X坐标 减去 自己的X坐标 的绝对值 小于等于 2(威力为2) 并且 查询事件的Y坐标 减去 自己的Y坐标 的绝对值 小于等于 2
       那么此事件将被炸掉(消除)
完毕


好了,基本如此,如果想制作炸掉名字为带有“ENEMY”的事件需要慢慢完善。
这只是炸掉事件的简单部分,更复杂的元件通行阻碍泡泡需要完全颠覆上面的内容,而且动画也要随之变化。。。。
(说明:用4个动画来显示泡泡爆炸实在不是一种高效的办法,会发现FPS骤降)
这只是一个泡泡,如果要有许多泡泡还需要制作哦

= =废话少说!
5。制作爆炸后的页面并返回循环泡泡的一生!







今天的功课就这样了!!
以后持续更新最终完全成为一个炸弹人范例!
如果对这种游戏做法感兴趣可以下载去年我发布的QQ堂作为参考:
http://www.66rpg.com/articles/2679


‘‘──end55rpg于2012-4-4 15:28补充以下内容


4月8号                                                  
今天添加教程咯:添加了手稿= =

看不到下载范例吧= =!!!!!
4月9号                                                  

今天发布最后完整版的PP事件内容,还有爆炸时候的完整脚本哦:
那几个月制作脚本不知挖空了多少心思,前几个月,为了效率不知改了多少次:
下面有图有脚本:




脚本如下:
  1. #4。0更新的东西:
  2. #准备把CHECK_EVENT2建立一个HASH查询!
  3. #全方面把BUG取缔,革命性的转折。
  4. #-------------------------------如果要出ver5
  5. #那么把4个方向的每块坐标运算改成范围只运算4次,并且还有……
  6. #找出放15泡FPS降低的根源。。。。。
  7. module QQT
  8. def self.pp_data(event_id)
  9. #===============================NEW这玩意儿比的是全局更新,故可以是全局变量
  10. $phash = {}
  11. for event in $game_map.events.values
  12. if $phash[[event.x,event.y]]
  13. $phash[[event.x,event.y]] += [event]
  14. else
  15. $phash[[event.x,event.y]] = [event]
  16. end
  17. end
  18. #===============================
  19. #begin-------------
  20. id = $game_map.events[event_id]
  21. x,y = id.x,id.y
  22. po = $pp_power.to_i
  23. event = $game_map.check_all_event(x, y,"敌人") rescue []
  24. map_id = $game_map.map_id
  25. damage = $game_party.actors[0].base_atk
  26. suipian = []
  27. person = "主角"
  28. #Center Bing Bong

  29. event.each{|e|
  30. e.damage_hp(po*100)
  31. }
  32. event = $game_map.check_event2(x, y,"普通")
  33. if $game_player.x == x and $game_player.y == y
  34. $game_player.damage_hp_player2(damage)
  35. end
  36. if $game_player2.x == x and $game_player2.y == y
  37. $game_player2.damage_hp_player2(damage)
  38. end
  39. if event != nil
  40. event.each{|a|
  41. $game_self_switches[[map_id,a.id,"A"]]=true
  42. a.refresh
  43. }
  44. end
  45. #Four Diraction
  46. #UP
  47. for yi in 1..po
  48. event = $game_map.check_all_event(x, y-yi,"敌人") rescue []
  49. if $game_map.tag_down(x, y-yi) == 1
  50. $suipian.push Sprite_Suipian.new($v,x,y-yi)
  51. suipian.push [x,y-yi]
  52. yi -= 1
  53. break
  54. elsif $game_map.through?(x,y-yi,2) == false
  55. yi -= 1
  56. break
  57. end
  58. event.each{|e|e.damage_hp(damage)}
  59. if $game_player.x == x and $game_player.y == y-yi
  60. $game_player.damage_hp_player2(damage)
  61. end
  62. if $game_player2.x == x and $game_player2.y == y-yi
  63. $game_player2.damage_hp_player2(damage)
  64. end
  65. event = $game_map.check_event2(x, y-yi,"普通")
  66. if event != []
  67. event.each{|a|
  68. $game_self_switches[[map_id,a.id,"A"]]=true
  69. a.refresh}
  70. break
  71. end
  72. if $game_map.tag_down(x, y-yi) == 6 # 炸掉元件道具
  73. edit(map_id,x,y-yi,1,0)
  74. end
  75. end
  76. up=yi
  77. #DOWN::3处修改加减号:y-yi
  78. for yi in 1..po
  79. event = $game_map.check_all_event(x, y+yi,"敌人") rescue []
  80. if $game_map.tag_down(x, y+yi) == 1
  81. $suipian.push Sprite_Suipian.new($v,x,y+yi)
  82. suipian.push [x,y+yi]
  83. yi -= 1
  84. break
  85. elsif $game_map.through?(x,y+yi,2) == false
  86. yi -= 1
  87. break
  88. end
  89. event.each{|e|e.damage_hp(damage)}
  90. if $game_player.x == x and $game_player.y == y+yi
  91. $game_player.damage_hp_player2(damage)
  92. end
  93. if $game_player2.x == x and $game_player2.y == y+yi
  94. $game_player2.damage_hp_player2(damage)
  95. end
  96. event = $game_map.check_event2(x, y+yi,"普通")
  97. if event != []
  98. event.each{|a|
  99. $game_self_switches[[map_id,a.id,"A"]]=true
  100. a.refresh}
  101. break
  102. end
  103. if $game_map.tag_down(x, y+yi) == 6
  104. edit(map_id,x,y+yi,1,0)
  105. end
  106. end
  107. down=yi

  108. #LEFT
  109. for xi in 1..po
  110. event = $game_map.check_all_event(x-xi, y,"敌人") rescue []
  111. if $game_map.tag_down(x-xi, y) == 1
  112. #p"这里是可炸地,待会爆炸,并跳出FOR循环结束左泡浆!"
  113. $suipian.push Sprite_Suipian.new($v,x-xi,y)
  114. suipian.push [x-xi,y]
  115. xi -= 1
  116. break
  117. elsif $game_map.through?(x-xi,y,2) == false
  118. xi -= 1
  119. break
  120. end
  121. event.each{|e|e.damage_hp(damage)}
  122. if $game_player.x == x-xi and $game_player.y == y
  123. $game_player.damage_hp_player2(damage)
  124. end
  125. if $game_player2.x == x-xi and $game_player2.y == y
  126. $game_player2.damage_hp_player2(damage)
  127. end
  128. event = $game_map.check_event2(x-xi, y,"普通")
  129. if event != []
  130. event.each{|a|
  131. $game_self_switches[[map_id,a.id,"A"]]=true
  132. a.refresh}
  133. break
  134. end
  135. if $game_map.tag_down(x-xi, y) == 6
  136. edit(map_id,x-xi,y,1,0)
  137. end
  138. end
  139. left=xi

  140. ###==RIGHT===========
  141. for xi in 1..po
  142. event = $game_map.check_all_event(x+xi, y,"敌人") rescue []
  143. if $game_map.tag_down(x+xi, y) == 1
  144. $suipian.push Sprite_Suipian.new($v,x+xi,y)
  145. suipian.push [x+xi,y]
  146. xi -= 1
  147. break
  148. elsif $game_map.through?(x+xi,y,2) == false
  149. xi -= 1
  150. break
  151. end
  152. event.each{|e|e.damage_hp(damage)}
  153. if $game_player.x == x+xi and $game_player.y == y
  154. $game_player.damage_hp_player2(damage)
  155. end
  156. if $game_player2.x == x+xi and $game_player2.y == y
  157. $game_player2.damage_hp_player2(damage)
  158. end
  159. event = $game_map.check_event2(x+xi, y,"普通")
  160. if event != []
  161. event.each{|a|
  162. $game_self_switches[[map_id,a.id,"A"]]=true
  163. a.refresh}
  164. break
  165. end
  166. if $game_map.tag_down(x+xi, y) == 6
  167. edit(map_id,x+xi,y,1,0)
  168. end
  169. end
  170. edit(map_id,x,y,1,0)
  171. right=xi

  172. return [up, down, left, right] , suipian
  173. $game_map.events[event_id].animation_id = up-1+130
  174. $game_map.events[event_id].animation_id = down-1+137 unless down-1+137 == 136
  175. $game_map.events[event_id].animation_id = left-1+144 unless left-1+144 == 143
  176. $game_map.events[event_id].animation_id = right-1+151 unless left-1+151 == 150

  177. end
  178. end

  179. #=====================================================
  180. class Game_Map
  181. #--------------------------------------------------------------------------
  182. # ● 获取指定位置的事件 ID
  183. # x : X 坐标
  184. # y : Y 坐标
  185. #--------------------------------------------------------------------------
  186. def check_event(x, y)
  187. for event in $game_map.events.values
  188. if event.x == x and event.y == y
  189. next if event.character_name == ""
  190. return ev_id
  191. end

  192. end

  193. end

  194. end
  195. #New
  196. class Game_Map
  197. #--------------------------------------------------------------------------
  198. # ● 获取指定位置的事件 ID
  199. # x : X 坐标
  200. # y : Y 坐标
  201. #--------------------------------------------------------------------------
  202. def check_event2(x, y,name)#name = 普通
  203. for event in $game_map.events.values
  204. if event.x == x and event.y == y
  205. if event.character_name.index(name) or
  206. (name == '敌人' and event.name.index('en='))
  207. return event.id
  208. end
  209. end
  210. end
  211. return 0
  212. end

  213. end
  214. #New
  215. class Game_Map
  216. #--------------------------------------------------------------------------
  217. # ● 获取指定位置的事件 ID
  218. # x : X 坐标
  219. # y : Y 坐标
  220. #--------------------------------------------------------------------------
  221. def check_all_event(x, y,name)#name = 敌人
  222. a = $phash[[x,y]].to_a
  223. c = []
  224. a.each{|b|c.push b if b.character_name.index(name) or (b.name.index('en=') and b.hp > 0)}
  225. return c
  226. end
  227. def check_event2(x, y,name)#name = 普通
  228. a = $phash[[x,y]].to_a
  229. c = []
  230. a.each{|b|c.push b if b.character_name.index(name)}
  231. return c
  232. end
  233. end
  234. #========================
  235. ↑找怪脚本↓爆炸动画
  236. #=====================
  237. class Sprite_PPJS < Sprite
  238. #--------------------------------------------------------------------------
  239. # ● 初始化对像
  240. # viewport : 显示端口
  241. #--------------------------------------------------------------------------
  242. def initialize(viewport, cha, power, dir)
  243. super(viewport)
  244. @cha, @power, @dir = cha, power, dir
  245. @count = 0
  246. self.bitmap = RPG::Cache.picture("PPJS3")
  247. # 将活动块设置为可见
  248. self.visible = true
  249. # 设置活动块的坐标
  250. case @dir
  251. when 2
  252. self.angle = -90
  253. @x2 = 32
  254. @y2 = 32
  255. when 4
  256. self.angle = -180
  257. @y2 = 32
  258. when 6
  259. self.angle = -0
  260. @power += 1
  261. when 8
  262. self.angle = 90
  263. end
  264. self.x = @cha.screen_x - 16 + @x2.to_i
  265. self.y = @cha.screen_y - 32 + @y2.to_i
  266. self.z = @cha.screen_z(32)
  267. self.opacity = 225
  268. self.src_rect.set((10-@power)*32, 0, @power*32, 32)
  269. self.zoom_x, self.zoom_y = 0.95,0.95
  270. update
  271. end
  272. #--------------------------------------------------------------------------
  273. # ● 释放
  274. #--------------------------------------------------------------------------
  275. def dispose
  276. if self.bitmap != nil
  277. self.bitmap.dispose
  278. end
  279. super
  280. end
  281. #--------------------------------------------------------------------------
  282. # ● 释放
  283. #--------------------------------------------------------------------------
  284. def dispose2
  285. if self.bitmap != nil
  286. self.visible = false
  287. end
  288. #super
  289. end
  290. #--------------------------------------------------------------------------
  291. # ● 更新画面
  292. #--------------------------------------------------------------------------
  293. def update
  294. @count += 1
  295. self.x = @cha.screen_x - 16 + @x2.to_i
  296. self.y = @cha.screen_y - 32 + @y2.to_i

  297. 渐变x()

  298. return false if @count == 15
  299. super
  300. end
  301. def 渐变x()
  302. self.zoom_x += 0.005
  303. end
  304. end
复制代码
因为那个动画效率太低,所以替换为自制类显示动画,图像也尽量改进加速!
泡泡动画图:请放在PICTURE包包里:(通过旋转,截取形成4方向爆炸和威力可改)


还是把范例拿出来吧:

(自己玩自己游戏玩疯了)
这个区人怎么这么少啊!
哇哈哈我的图没有崩!
请提问吧!
’’
4月13号                                                  
今天已经没有任务了哦,现在就动手制作吧,对了
有什么疑难请回复!!!






win.PNG (273.71 KB, 下载次数: 40)

win.PNG

Super Mouse System v1.15.rar

467.75 KB, 阅读权限: 10, 下载次数: 501

ok


作者: end55rpg    时间: 2012-4-5 19:13
本帖最后由 end55rpg 于 2012-4-9 19:53 编辑

@kimuafhjbfsa
给分啊!
分享快乐如此简单
作者: lxd986729825    时间: 2012-4-5 20:45
va可以试一下不?
作者: 迷糊的安安    时间: 2012-4-6 13:43
lxd986729825 发表于 2012-4-5 20:45
va可以试一下不?

VA的话更好做,因为VA有“获得指定位置的信息”还有区域功能,一句脚本都不用就能用纯事件做出来……
我以前写过一个用炸弹炸墙壁来开拓迷宫隐藏区域的功能。
http://rpg.blue/thread-225861-1-1.html
这个是用区域来判定的。

对于炸移动目标的话,可以用“获取指定位置的信息”来获取事件ID,然后用“分支条件”功能操作指定的开关使事件爆炸。
作者: Wind2010    时间: 2012-4-6 17:53
动画连续显示4个的话最后一个不会把其他3个覆盖么……我记得播放动画的时候再播放个动画的话原来的动画会中断的
作者: end55rpg    时间: 2012-4-9 19:53
本帖最后由 end55rpg 于 2012-4-11 21:52 编辑
end55rpg 发表于 2012-4-5 19:13
@kimuafhjbfsa
给分啊!
分享快乐如此简单


@冰舞蝶恋
版主再来看看分值再来改改


‘‘──end55rpg于2012-4-11 14:13补充以下内容

[@]冰舞蝶恋[/@]版主求更新加分啊
我晕班主任快来
拿东西不回复者,可恶
’’


‘‘──end55rpg于2012-4-13 22:08补充以下内容

@kimu更新求查看
’’
作者: wyongcan2008    时间: 2012-4-14 12:50
对于取出指定位置的事件,我有个可以不循环所有事件的想法,就是在初始化events时,
一起初始个eventinfo的哈希表,表的结构如下{"X坐标Y坐标" => 事件ID},这样要取出事件ID只需要
eventinfo就有了.

不知道实际运用怎么样
作者: end55rpg    时间: 2012-4-14 12:54
wyongcan2008 发表于 2012-4-14 12:50
对于取出指定位置的事件,我有个可以不循环所有事件的想法,就是在初始化events时,
一起初始个eventinfo的 ...

娃终于有知音来访了!您说的没错,好像我的泡泡脚本就是这样的,一个全局变量记录了事件的以ID为序的哈希组在放泡泡的时候更新一下这个变量然后读取。。。目前ver4.0泡泡脚本就是这样滴哦,效率不见得多大改进,因为地图上事件没有成百上千哦
作者: wyongcan2008    时间: 2012-4-14 13:03
本帖最后由 wyongcan2008 于 2012-4-14 13:05 编辑

我想还可以优化一下,在泡泡的判断中
如果炮炮威力*4+1>地图事件数,
就循环所有事件来判断,
如果小于的话就循环判断泡泡炸到的位置有没有事件。

我按照的做eventinfo的想法自己写了段脚本,用到了提取放置物脚本简洁版。
不过你说的事件是移动的这一点还真没考虑到。
  1. module Event
  2.   def self.xy_tos (x,y)
  3.     ox = x.to_s
  4.     oy = y.to_s
  5.     while ox.size < 3
  6.       ox = "0" + ox
  7.     end
  8.     while oy.size < 3
  9.       oy = "0" + oy
  10.     end
  11.     ox + oy
  12.   end
  13.   def self.id_byxy(x,y)
  14.     $game_map.eventinfo[xy_tos(x,y)]
  15.   end
  16.   def self.id_byxys(xy)
  17.     $game_map.eventinfo[xy]
  18.   end
  19.   def self.event_byxy(x,y)
  20.     $game_map.events[$game_map.eventinfo[xy_tos(x,y)]]
  21.   end
  22.   def self.event_byxys(xy)
  23.     $game_map.events[$game_map.eventinfo[xy]]
  24.   end
  25. end

  26. module Drop_Item
  27.     def self.make_events(map_id,event_id,item_x,item_y,save=false)
  28.       return unless self.is_map?        
  29.       map = load_data(sprintf("Data/Map%03d.rxdata", map_id))     
  30.       temp = Marshal.load(Marshal.dump(map))      
  31.       if !$game_system.map_events_number
  32.          $game_system.map_events_number = {}
  33.       end  
  34.       sum = $game_system.map_events_number      
  35.       m_id = $game_map.map_id      
  36.       sum[m_id] == nil ? sum[m_id] = 2000 : sum[m_id] += 1
  37.       new_event_id = sum[m_id]      
  38.       temp.events[event_id].id = new_event_id      
  39.       temp.events[event_id].x,temp.events[event_id].y = item_x,item_y      
  40.       $game_map.events[new_event_id] = Game_Event.new(m_id,temp.events[event_id])
  41.       #在添加事件时将事件也添加到eventinfo
  42.       $game_map.eventinfo[Event.xy_tos(item_x,item_y)] = new_event_id
  43.       refresh_map   
  44.   end
  45.    
  46.   def self.delete_events(event_id)
  47.       return unless self.is_map?   
  48.       #在删除事件时将eventinfo中的事件也删除
  49.       $game_map.eventinfo.delete(Event.xy_tos($game_map.events[event_id].x,$game_map.events[event_id].y))
  50.       $game_map.events.delete(event_id)
  51.       self.refresh_map
  52.   end
  53. end

  54. class Game_Map
  55.     attr_reader   :eventinfo                # 事件信息
  56.   #--------------------------------------------------------------------------
  57.   # ● 设置
  58.   #     map_id : 地图 ID
  59.   #--------------------------------------------------------------------------
  60.   def setup(map_id)
  61.     # 地图 ID 记录到 @map_id
  62.     @map_id = map_id
  63.     # 地图文件装载后、设置到 @map
  64.     @map = load_data(sprintf("Data/Map%03d.rxdata", @map_id))
  65.     # 定义实例变量设置地图元件信息
  66.     tileset = $data_tilesets[@map.tileset_id]
  67.     @tileset_name = tileset.tileset_name
  68.     @autotile_names = tileset.autotile_names
  69.     @panorama_name = tileset.panorama_name
  70.     @panorama_hue = tileset.panorama_hue
  71.     @fog_name = tileset.fog_name
  72.     @fog_hue = tileset.fog_hue
  73.     @fog_opacity = tileset.fog_opacity
  74.     @fog_blend_type = tileset.fog_blend_type
  75.     @fog_zoom = tileset.fog_zoom
  76.     @fog_sx = tileset.fog_sx
  77.     @fog_sy = tileset.fog_sy
  78.     @battleback_name = tileset.battleback_name
  79.     @passages = tileset.passages
  80.     @priorities = tileset.priorities
  81.     @terrain_tags = tileset.terrain_tags
  82.     # 初始化显示坐标
  83.     @display_x = 0
  84.     @display_y = 0
  85.     # 清除刷新要求标志
  86.     @need_refresh = false
  87.     # 设置地图事件数据************
  88.     @events = {}
  89.     @eventinfo = {}
  90.     for i in @map.events.keys
  91.       @events[i] = Game_Event.new(@map_id, @map.events[i])
  92.       @eventinfo[Event.xy_tos(@events[i].x,@events[i].y)] = i #####
  93.     end
  94.     # 设置公共事件数据
  95.     @common_events = {}
  96.     for i in 1...$data_common_events.size
  97.       @common_events[i] = Game_CommonEvent.new(i)
  98.     end
  99.     # 初始化雾的各种信息
  100.     @fog_ox = 0
  101.     @fog_oy = 0
  102.     @fog_tone = Tone.new(0, 0, 0, 0)
  103.     @fog_tone_target = Tone.new(0, 0, 0, 0)
  104.     @fog_tone_duration = 0
  105.     @fog_opacity_duration = 0
  106.     @fog_opacity_target = 0
  107.     # 初始化滚动信息
  108.     @scroll_direction = 2
  109.     @scroll_rest = 0
  110.     @scroll_speed = 4
  111.   end
  112. end

  113. class Game_Event < Game_Character
  114.   #--------------------------------------------------------------------------
  115.   # ● 暂时消失****
  116.   #--------------------------------------------------------------------------
  117.   def erase
  118.     @erased = true
  119.     $game_map.eventinfo.delete(Event.xy_tos(@x,@y))
  120.     refresh
  121.   end
  122. end
复制代码

作者: end55rpg    时间: 2012-4-14 13:22
wyongcan2008 发表于 2012-4-14 13:03
我想还可以优化一下,在泡泡的判断中
如果炮炮威力*4+1>地图事件数,
就循环所有事件来判断,

的你代码看得云里雾里,你的文字我怎么理解不了了?请再说详细点吧
作者: chd114    时间: 2012-5-16 13:37
和魔塔样板不兼容···
作者: 雷欧亦炫    时间: 2013-9-8 08:20
谢谢教程,收下了
作者: yyq8092    时间: 2013-9-10 15:00
lz写的真可怕,一个这样的游戏需要那么多脚本吗?
作者: 1745236314    时间: 2015-8-31 07:39
我还要学呢图片怎么失效了啊{:4_147:}{:4_147:}
作者: 1745236314    时间: 2015-8-31 07:40
不用管我挖没挖坟,我是来学习的,这么精品的帖子沉在下边= =




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