Theo Dõi Sự Thay Đổi Của Các Đối Tượng Lua Trong Phát Triển Game - nói dối e blog

Theo Dõi Sự Thay Đổi Của Các Đối Tượng Lua Trong Phát Triển Game

Trong bản demo game mà tôi đang xây dựng, mọi logic của đối tượng đều tồn tại trong không gian 2D. Tuy nhiên, Ant Engine lại sử dụng phương pháp render 3D để hiển thị các đối tượng này. Để tối ưu hóa quy trình phát triển, tôi cần một bộ API tiện lợi giúp kiểm soát vị trí và góc xoay theo trục Y của các đối tượng này.

Bối Cảnh Kỹ Thuật

Ant Engine sử dụng các thành phần cảnh (scene components) để quản lý trạng thái không gian của entity khi render, bao gồm hệ thống SRT (Scale - Rotation - Translation) trong không gian 3D. Tuy nhiên, dự án của tôi chỉ yêu cầu kiểm soát:

  • Vị trí trên 2 trục tọa độ (X và Z)
  • Góc xoay trên trục Y (thường dùng để điều chỉnh hướng nhìn của nhân vật)

Việc trực tiếp thao tác SRT không chỉ phức tạp mà còn gây khó khăn trong việc đánh dấu các entity cần cập nhật mỗi frame. Trong kiến trúc ECS, giải pháp tối ưu là tạo một thành phần phụ trợ chứa 3 giá trị x, y, r. Một hệ thống (system) sẽ chuyển đổi giá trị này sang SRT 3D tương ứng. Tuy nhiên, việc cập nhật toàn bộ entity mỗi frame sẽ gây lãng phí tài nguyên vì đa số entity không thay đổi liên tục.

Giải Pháp Sáng Tạo Với Lua

Tôi đã áp dụng kỹ thuật meta-programming trong Lua để tạo cơ chế theo dõi sự thay đổi của các đối tượng logic. Dưới đây là đoạn mã triển khai:

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
local monitor = {}
local function new_type()
  local changes = {}
  
  local function touch(obj, k, v)
    local raw = obj.__raw
    changes[raw] = true
    raw[k] = v
    obj.__newindex = raw
  end
  
  local function new(obj)
    obj.__index = obj
    obj.__newindex = touch
    changes[obj] = true
    return setmetatable({ __raw = obj }, obj)
  end
  
  local function next_raw(t, key)
    local nkey, nvalue = next(t, key)
    if nkey then
      nkey.__newindex = touch
      return nkey, nvalue
    end
  end
  
  local function pairs()
    if next(changes) then
      local t = changes
      changes = {}
      return next_raw, t
    else
      return next, changes
    end
  end
  
  return { pairs = pairs, new = new }
end

local types = setmetatable({}, {
  __index = function(self, name)
    local t = new_type()
    self[name] = t
    return t
  end 
})

function monitor.new(typename)
  return types[typename].new
end

function monitor.pairs(typename)
  return types[typename].pairs()
end

-- Kích hoạt chế độ test
TEST = true
if TEST then
  local a = monitor.new "test" { x = 1, y = 2 }
  local b = monitor.new "test" { x = 10, y = 20 }
  
  local function flush()
    print "====="
    for obj in monitor.pairs "test" do
      print(obj.x, obj.y)
    end
  end
  
  a.x = -1
  flush()  -- In ra: -1 2 và 10 20
  
  b.y = -20
  flush()  -- In ra: 10 -20
  
  local c = monitor.new "test" { x = 0, y = 0 }
  flush()  -- In ra: 0 0
else
  return monitor
end

Cách Thức Hoạt Động

  1. Tạo Đối Tượng Logic
    Sử dụng monitor.new "typename" {} để tạo các đối tượng với thuộc tính x, y (và r nếu cần). Ví dụ:

    1
    
    local player = monitor.new "character" { x = 100, y = 50, r = 45 }
  2. Theo Dõi Thay Đổi
    Khi sửa đổi thuộc tính của đối tượng:

    1
    2
    
    player.x = 150
    player.r = 90

    Đối tượng sẽ tự động được đánh dấu vào danh sách thay đổi.

  3. Xử Lý Các Đối Tượng Bị Sửa
    Hàm monitor.pairs "typename" cho phép lặp qua tất cả đối tượng đã thay đổi (kể cả đối tượng mới tạo):

    1
    2
    3
    
    for obj in monitor.pairs "character" do
      update_3d_position(obj)  -- Hàm cập nhật vị trí 3D tương ứng
    end

Ưu Điểm Nổi Bật

  • Tối Ưu Hiệu Suất: Chỉ xử lý các đối tượng thực sự thay đổi, tránh lãng phí tài nguyên CPU/GPU
  • Dễ Tích Hợp: Có thể thêm eid (entity ID) vào đối tượng để ánh xạ với hệ thống ECS
  • Mã Sạch Sẽ: Giảm độ phức tạp khi làm việc với hệ tọa độ 3D trong logic 2D

Ứng Dụng Thực Tế

Trong game của tôi, cơ chế này được sử dụng để:

  • Cập nhật vị trí nhân vật theo thời gian thực
  • Đồng bộ hóa animation dựa trên hướng di chuyển
  • Quản lý hệ thống camera theo dõi đối tượng chính

Bạn có thể tùy chỉnh đoạn mã này để hỗ trợ thêm các thuộc tính khác như scale, z-position, hoặc tích hợp với hệ thống event của engine. Đây là một giải pháp linh hoạt và hiệu quả cho các dự án game sử dụng Lua làm ngôn ngữ script chính.

0%