Not a member of Pastebin yet?
Sign Up,
it unlocks many cool features!
- class_name PackGrid2D extends RefCounted
- var _flat := PackedVector4Array()
- const _CONTAINER_MAX_SIZE: int = 4
- const _GRID_MAX_SIZE: = 46340 # sqrt(INT32_MAX)
- const _MAX_FLOAT_INTEGER = 16777216 # 24^2 ограничение мантиссы float в 64 бита, дальше точность целых чисел не гарантируется.
- var _offset: int
- #region API
- func setup(size: int) -> PackGrid2D:
- if _badSize(size):
- return
- _offset = size
- _flat.resize(size * size)
- return self
- static func calcFlatIndex(gridIndex: Vector2i, size: int) -> int:
- return size * gridIndex.y + gridIndex.x
- func has(index: Vector2i) -> bool:
- return index.x >= 0 and index.y >= 0 and index.x < _offset and index.y < _offset
- func getId(gridIndex: Vector2i, containerIndex: int) -> int:
- if _badContainerIndex(containerIndex):
- return INT32_MIN - 1 #DS: у нас не было исключений, выживали как могли (нужно отдать не валидное INT32, чтобы крашнулось где-то)
- if _badGridIndex(gridIndex):
- return INT32_MIN - 1
- return int(_flat[calcFlatIndex(gridIndex, _offset)][containerIndex])
- func setId(gridIndex: Vector2i, containerIndex: int, ValueId) -> void:
- if _badValueId(ValueId):
- return
- if _badContainerIndex(containerIndex):
- return
- if _badGridIndex(gridIndex):
- return
- _flat[calcFlatIndex(gridIndex, _offset)][containerIndex] = ValueId
- func resetGrid(gridIndex: Vector2i) -> void:
- setId(gridIndex, 0, 0)
- setId(gridIndex, 1, 0)
- setId(gridIndex, 2, 0)
- setId(gridIndex, 3, 0)
- #endregion
- #region Error
- func _fatalError(msg: String) -> void:
- if __test_isTesting:
- __test_errorResult = msg
- return
- push_error(msg)
- breakpoint
- func _badSize(size: int) -> bool:
- if size < 1 or size >= _GRID_MAX_SIZE:
- _fatalError("GAME_ERROR: bad size: {0}".format([size]))
- return true
- return false
- func _badContainerIndex(containerIndex: int) -> bool:
- if containerIndex < 0 or containerIndex >= _CONTAINER_MAX_SIZE:
- _fatalError("GAME_ERROR: container index out of bounds: {0}".format([containerIndex]))
- return true
- return false
- func _badGridIndex(gridIndex: Vector2i) -> bool:
- if not has(gridIndex):
- _fatalError("GAME_ERROR: array index out of bounds: {0}".format([gridIndex]))
- return true
- return false
- func _badValueId(i: int) -> bool:
- if i < 0 or i > _MAX_FLOAT_INTEGER:
- _fatalError("GAME_ERROR: ValueId out of bounds: {0}".format([i]))
- return true
- return false
- #endregion
- #region Test
- var __test_isTesting := false
- var __test_errorResult := ""
- func __test_init() -> PackGrid2D:
- var t := PackGrid2D.new()
- t.__test_isTesting = true
- return t
- func __test():
- __test___badSize()
- __test___badContainerIndex()
- __test___badGridIndex()
- __test___badInt32()
- __test___work()
- # WARNING: Просто так не раскомментируй. Читай описание метода.
- #__test___integerIntegrityTest()
- print("TEST OK")
- func __test___badSize():
- const STATUS = 0
- const ITEM = 1
- const DIRT = 2
- const _RESERVE_ = 3
- var result: int
- var t: PackGrid2D
- t = __test_init()
- t.setup(0)
- assert("GAME_ERROR: bad size: 0" == t.__test_errorResult)
- t = __test_init()
- t.setup(-1)
- assert("GAME_ERROR: bad size: -1" == t.__test_errorResult)
- t = __test_init()
- t.setup(_GRID_MAX_SIZE + 1)
- assert("GAME_ERROR: bad size: 46341" == t.__test_errorResult, t.__test_errorResult)
- func __test___badContainerIndex():
- const STATUS = 0
- const ITEM = 1
- const DIRT = 2
- const _RESERVE_ = 3
- var result: int
- var t: PackGrid2D
- t = __test_init()
- t.setup(4)
- result = t.getId(Vector2i(2, 1), 5)
- assert("GAME_ERROR: container index out of bounds: 5" == t.__test_errorResult, t.__test_errorResult)
- #DS: Зафиксируем эту проверку здесь
- assert(result == INT32_MIN - 1)
- t = __test_init()
- t.setup(4)
- t.setId(Vector2i(2, 1), 5, 7)
- assert("GAME_ERROR: container index out of bounds: 5" == t.__test_errorResult, t.__test_errorResult)
- t = __test_init()
- t.setup(4)
- result = t.getId(Vector2i(2, 1), -1)
- assert("GAME_ERROR: container index out of bounds: -1" == t.__test_errorResult, t.__test_errorResult)
- t = __test_init()
- t.setup(4)
- t.setId(Vector2i(2, 1), -1, 8)
- assert("GAME_ERROR: container index out of bounds: -1" == t.__test_errorResult, t.__test_errorResult)
- t = __test_init()
- t.setup(4)
- result = t.getId(Vector2i(2, 4), ITEM)
- assert("GAME_ERROR: array index out of bounds: (2, 4)" == t.__test_errorResult, t.__test_errorResult)
- t = __test_init()
- t.setup(4)
- t.setId(Vector2i(2, 4), ITEM, 401)
- assert("GAME_ERROR: array index out of bounds: (2, 4)" == t.__test_errorResult, t.__test_errorResult)
- func __test___badGridIndex():
- const STATUS = 0
- const ITEM = 1
- const DIRT = 2
- const _RESERVE_ = 3
- var result: int
- var t: PackGrid2D
- t = __test_init()
- t.setup(4)
- result = t.getId(Vector2i(2, -1), ITEM)
- assert("GAME_ERROR: array index out of bounds: (2, -1)" == t.__test_errorResult, t.__test_errorResult)
- t = __test_init()
- t.setup(4)
- t.setId(Vector2i(2, -1), ITEM, 208)
- assert("GAME_ERROR: array index out of bounds: (2, -1)" == t.__test_errorResult, t.__test_errorResult)
- t = __test_init()
- t.setup(4)
- result = t.getId(Vector2i(4, 2), ITEM)
- assert("GAME_ERROR: array index out of bounds: (4, 2)" == t.__test_errorResult, t.__test_errorResult)
- t = __test_init()
- t.setup(4)
- t.setId(Vector2i(4, 2), ITEM, 435)
- assert("GAME_ERROR: array index out of bounds: (4, 2)" == t.__test_errorResult, t.__test_errorResult)
- t = __test_init()
- t.setup(4)
- result = t.getId(Vector2i(-1, 2), ITEM)
- assert("GAME_ERROR: array index out of bounds: (-1, 2)" == t.__test_errorResult, t.__test_errorResult)
- t = __test_init()
- t.setup(4)
- t.setId(Vector2i(-1, 2), ITEM, 3)
- assert("GAME_ERROR: array index out of bounds: (-1, 2)" == t.__test_errorResult, t.__test_errorResult)
- func __test___badInt32():
- const STATUS = 0
- const ITEM = 1
- const DIRT = 2
- const _RESERVE_ = 3
- var result: int
- var t: PackGrid2D
- t = __test_init()
- t.setup(4)
- t.setId(Vector2i(1, 2), ITEM, -1)
- assert("GAME_ERROR: ValueId out of bounds: -1" == t.__test_errorResult, t.__test_errorResult)
- t = __test_init()
- t.setup(4)
- t.setId(Vector2i(1, 2), ITEM, INT32_MAX + 1)
- assert("GAME_ERROR: ValueId out of bounds: 2147483648" == t.__test_errorResult, t.__test_errorResult)
- func __test___work():
- const STATUS = 0
- const ITEM = 1
- const DIRT = 2
- const _RESERVE_ = 3
- var result: int
- var t: PackGrid2D
- # COMM: этот тест слишком долгий. Он создает массив _GRID_MAX_SIZE^2
- # Оставлен для напоминания
- #t = __test_init()
- #t.setup(_GRID_MAX_SIZE)
- #assert("" == t.__test_errorResult)
- t = __test_init()
- t.setup(1)
- assert("" == t.__test_errorResult)
- t = __test_init()
- t.setup(4)
- result = t.getId(Vector2i(1,0), ITEM)
- assert(result == 0)
- result = t.getId(Vector2i(1,0), DIRT)
- assert(result == 0)
- result = t.getId(Vector2i(1,0), STATUS)
- assert(result == 0)
- result = t.getId(Vector2i(1,0), _RESERVE_)
- assert(result == 0)
- t.setId(Vector2i(3,2), STATUS, 20)
- result = t.getId(Vector2i(3,2), STATUS)
- assert(result == 20)
- t.setId(Vector2i(3,2), STATUS, 0)
- result = t.getId(Vector2i(3,2), STATUS)
- assert(result == 0)
- t.setId(Vector2i(3,2), _RESERVE_, 20)
- result = t.getId(Vector2i(3,2), _RESERVE_)
- assert(result == 20)
- t.setId(Vector2i(3,2), ITEM, 4031)
- result = t.getId(Vector2i(3,2), ITEM)
- assert(result == 4031)
- t.setId(Vector2i(3,2), DIRT, 1323)
- result = t.getId(Vector2i(3,2), DIRT)
- assert(result == 1323)
- t.setId(Vector2i(3,2), DIRT, _MAX_FLOAT_INTEGER)
- result = t.getId(Vector2i(3,2), DIRT)
- assert(result == _MAX_FLOAT_INTEGER)
- t = __test_init()
- t.setup(2)
- t.setId(Vector2i(1,0), ITEM, 1234)
- t.setId(Vector2i(1,0), DIRT, 4321)
- result = t.getId(Vector2i(1,0), ITEM)
- assert(result == 1234)
- result = t.getId(Vector2i(1,0), DIRT)
- assert(result == 4321)
- t.resetGrid(Vector2i(1,0))
- result = t.getId(Vector2i(1,0), ITEM)
- assert(result == 0)
- result = t.getId(Vector2i(1,0), DIRT)
- assert(result == 0)
- ## Это безумно долгий тест (до ~3 минут), чтобы проверить конвертацию и сохранность точности целых чисел при конвертации int -> float -> int
- ## Тест может занимать занимает до минут. Лучше один раз запустить в _proccess(). В _ready() может подвиснуть окно и не будет видно вывод итераций.
- ## Хотя _MAX_FLOAT_INTEGER гарантирует сохранность целостность целых чисел при точности мантиссы = 24 значащих бита,
- ## но в случае магических проблем на какой либо платформе, лучше прогнать тест на этой платформе (для PC проблем не должно быть).
- func __test___integerIntegrityTest():
- const ITEM = 1
- var t = __test_init()
- t.setup(2)
- var r: int
- for i in _MAX_FLOAT_INTEGER:
- if i % 100_000 == 0:
- print(i)
- t.setId(Vector2i(1,1), ITEM, i)
- r = t.getId(Vector2i(1,1), ITEM)
- assert(r == i, "{0} == {1}".format([r, i]))
- #endregion
Advertisement
Add Comment
Please, Sign In to add comment