基于Ruby的回合制策略游戏开发:地图与单位系统解析
立即解锁
发布时间: 2025-08-21 02:25:31 订阅数: 2 


实用Ruby项目:探索编程的无限可能
### 基于 Ruby 的回合制策略游戏开发:地图与单位系统解析
#### 1. 单位与地图的基础操作
在游戏开发中,单位(units)是重要的元素,它们具有 `x` 和 `y` 坐标访问器。`place` 方法会将单位存储在 `@units` 矩阵中,并设置单位的 `x` 和 `y` 字段。初始放置单位后,就可以使用 `move` 方法,该方法接收旧的和新的 `x`、`y` 坐标,将对象移动到新位置并从旧位置移除。
为了避免意外,虽然 `LocationOccupiedError` 异常理论上不应被触发(因为只应向玩家展示未被占用位置的移动选项),但做好防范总是没错的。
地图方面,`@units` 矩阵初始为空,而 `@terrain` 矩阵需要进行填充。在大型游戏中,游戏设计师或艺术家会使用地图编辑器创建地图,完成后保存为特定文件格式供游戏引擎加载。但对于业余开发者,手动编写代码填充地图很繁琐,例如:
```ruby
map = Map.new(20, 20)
map.terrain[0,0] = forest
map.terrain[1,0] = forest
map.terrain[2,0] = plains
```
可以采用一种巧妙的方法,使用简单的 ASCII 编码字符串来表示地图,结合地形键(terrain key)进行解析。示例如下:
```ruby
terrain_key = {
"f" => forest,
"g" => grass,
"m" => mountains,
"p" => plains,
"w" => water,
}
```
地图布局字符串:
```
gggggggggg
gggggggwww
ggggggwwff
gggppppppp
ggppggwfpf
ggpgggwwff
```
#### 2. 地图类的实现
通过 `Map` 类的 `initialize` 方法可以将上述字符串转换为地图。具体代码如下:
```ruby
class Map
def initialize(key, layout)
rows = layout.split("\n")
rows.collect! {|row| row.gsub(/\s+/, '').split(//) }
y = rows.size
x = rows[0].size
@terrain = Matrix.new(x, y)
@units = Matrix.new(x, y)
rows.each_with_index do |row, y|
row.each_with_index do |glyph, x|
@terrain[x, y] = key[glyph]
end
end
end
end
```
这个方法的步骤如下:
1. 将布局字符串按行分割。
2. 去除每行的空白字符,并将每行拆分为字符数组。
3. 获取地图的行数和列数。
4. 创建 `@terrain` 和 `@units` 矩阵。
5. 遍历字符数组,根据地形键将地形类型填充到 `@terrain` 矩阵中。
以下是使用示例:
```ruby
terrain_key = {
"f" => forest,
"g" => grass,
"m" => mountains,
"p" => plains,
"w" => water,
}
map = Map.new terrain_key, <<-END
gggggggggg
gggggggwww
ggggggwwff
gggppppppp
ggppggwfpf
ggpgggwwff
END
map.terrain[0,0].name # => "Grass"
```
#### 3. 地图类的辅助方法
为了方便操作地图,还可以添加一些辅助方法,如 `all_positions`、`within?` 和 `near_positions`。
```ruby
class Map
def all_positions
@terrain.all_positions
end
def within?(distance, x1, y1, x2, y2)
(x1 - x2).abs + (y1 - y2).abs <= distance
end
def near_positions(distance, x, y)
all_positions.find_all{|x2, y2| within?(distance, x, y, x2, y2) }
end
end
```
- `all_positions` 方法将获取地形矩阵的所有位置信息。
- `within?` 方法用于计算两点之间的曼哈顿距离是否小于指定值。
- `near_positions` 方法利用前两个方法返回指定位置附近的位置列表。
#### 4. 地图的表示方法
地图需要一个合适的表示方法,以便传递给玩家界面。这里采用简单的列表形式,包含地形和单位的表示信息。
```ruby
class Map
def rep
return [@terrain.rep, @units.rep]
end
end
class Matrix
def rep
@data.collect do |row|
row.collect do |item|
item.rep
end
end
end
end
class NilClass
def rep
nil
end
end
```
`Map` 类的 `rep` 方法返回一个包含地形和单位表示的列表。`Matrix` 类的 `rep` 方法将矩阵中的每个元素转换为其表示形式。由于 `@units` 矩阵可能存在空位置,需要为 `NilClass` 定义 `rep` 方法,使其返回 `nil`。
#### 5. 单位类的设计
游戏中的角色和敌人恐龙可以用不同的类来表示,它们都继承自 `Unit` 基类。
```ruby
class Unit; end
class Human < Unit; end
class Soldier < Human; end
class Doctor < Human; end
class Dinosaur < Unit; end
class VRaptor < Dinosaur; end
class TRex < Dinosaur; end
```
所有 `Unit` 类都有一些共同的属性,如名称、生命值、移动能力和行动列表。
```ruby
class Unit
attr_reader :name, :health, :movement, :actions
attr_accessor :x, :y
def initialize(player, name)
```
0
0
复制全文
相关推荐










