Chunk collision improvement test
This commit is contained in:
parent
4a02a0e0de
commit
d9c4b0aee2
@ -113,6 +113,8 @@ fun main() {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
chunkA!!.foreground[18, 14] = tile
|
||||||
|
|
||||||
/*val rand = Random()
|
/*val rand = Random()
|
||||||
|
|
||||||
for (i in 0 .. 400) {
|
for (i in 0 .. 400) {
|
||||||
@ -172,7 +174,7 @@ fun main() {
|
|||||||
client.camera.pos.y = 10f
|
client.camera.pos.y = 10f
|
||||||
|
|
||||||
client.gl.box2dRenderer.drawShapes = true
|
client.gl.box2dRenderer.drawShapes = true
|
||||||
client.gl.box2dRenderer.drawPairs = false
|
client.gl.box2dRenderer.drawPairs = true
|
||||||
client.gl.box2dRenderer.drawAABB = false
|
client.gl.box2dRenderer.drawAABB = false
|
||||||
client.gl.box2dRenderer.drawJoints = false
|
client.gl.box2dRenderer.drawJoints = false
|
||||||
|
|
||||||
@ -186,8 +188,8 @@ fun main() {
|
|||||||
Starbound.pollCallbacks()
|
Starbound.pollCallbacks()
|
||||||
|
|
||||||
//ent.think(client.frameRenderTime)
|
//ent.think(client.frameRenderTime)
|
||||||
client.camera.pos.x = ent.position.x.toFloat()
|
//client.camera.pos.x = ent.position.x.toFloat()
|
||||||
client.camera.pos.y = ent.position.y.toFloat()
|
//client.camera.pos.y = ent.position.y.toFloat()
|
||||||
|
|
||||||
//println(client.camera.velocity.toDoubleVector() * client.frameRenderTime * 0.1)
|
//println(client.camera.velocity.toDoubleVector() * client.frameRenderTime * 0.1)
|
||||||
|
|
||||||
|
@ -336,6 +336,389 @@ class MutableTileChunkView(
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private data class TileExposure(
|
||||||
|
var pos: Vector2d,
|
||||||
|
val left: Boolean,
|
||||||
|
val right: Boolean,
|
||||||
|
val up: Boolean,
|
||||||
|
val down: Boolean,
|
||||||
|
)
|
||||||
|
|
||||||
|
private class TileFlooder(
|
||||||
|
private val tiles: Array<ChunkTile?>,
|
||||||
|
private val seen: BooleanArray,
|
||||||
|
rootx: Int,
|
||||||
|
rooty: Int
|
||||||
|
) {
|
||||||
|
/**
|
||||||
|
* Tile positions which have at least one face free of neighbours
|
||||||
|
*/
|
||||||
|
val exposed = ArrayList<TileExposure>()
|
||||||
|
|
||||||
|
private fun get(x: Int, y: Int): Boolean {
|
||||||
|
if (x < 0 || x > CHUNK_SIZE_FF) {
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
|
||||||
|
if (y < 0 || y > CHUNK_SIZE_FF) {
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
|
||||||
|
return tiles[x or (y shl CHUNK_SHIFT)] != null
|
||||||
|
}
|
||||||
|
|
||||||
|
private fun visit(x: Int, y: Int) {
|
||||||
|
if (seen[x or (y shl CHUNK_SHIFT)])
|
||||||
|
return
|
||||||
|
|
||||||
|
seen[x or (y shl CHUNK_SHIFT)] = true
|
||||||
|
|
||||||
|
val left = get(x - 1, y)
|
||||||
|
val right = get(x + 1, y)
|
||||||
|
val up = get(x, y + 1)
|
||||||
|
val down = get(x, y - 1)
|
||||||
|
|
||||||
|
if (!left || !right || !up || !down) {
|
||||||
|
exposed.add(TileExposure(Vector2d(x.toDouble() + 0.5, y.toDouble() + 0.5), !left, !right, !up, !down))
|
||||||
|
}
|
||||||
|
|
||||||
|
if (left) {
|
||||||
|
visit(x - 1, y)
|
||||||
|
}
|
||||||
|
|
||||||
|
if (right) {
|
||||||
|
visit(x + 1, y)
|
||||||
|
}
|
||||||
|
|
||||||
|
if (up) {
|
||||||
|
visit(x, y + 1)
|
||||||
|
}
|
||||||
|
|
||||||
|
if (down) {
|
||||||
|
visit(x, y - 1)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
init {
|
||||||
|
visit(rootx, rooty)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private class RectTileFlooderDepthFirst(
|
||||||
|
private val tiles: Array<ChunkTile?>,
|
||||||
|
private val seen: BooleanArray,
|
||||||
|
rootx: Int,
|
||||||
|
rooty: Int
|
||||||
|
) {
|
||||||
|
val mins: Vector2i
|
||||||
|
val maxs: Vector2i
|
||||||
|
|
||||||
|
private fun filled(x: Int, y: Int): Boolean {
|
||||||
|
if (x < 0 || x > CHUNK_SIZE_FF) {
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
|
||||||
|
if (y < 0 || y > CHUNK_SIZE_FF) {
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
|
||||||
|
return !seen[x or (y shl CHUNK_SHIFT)] && tiles[x or (y shl CHUNK_SHIFT)] != null
|
||||||
|
}
|
||||||
|
|
||||||
|
init {
|
||||||
|
// expand wide
|
||||||
|
var widthPositive = 1
|
||||||
|
|
||||||
|
while (true) {
|
||||||
|
if (!filled(rootx + widthPositive, rooty)) {
|
||||||
|
break
|
||||||
|
}
|
||||||
|
|
||||||
|
widthPositive++
|
||||||
|
}
|
||||||
|
|
||||||
|
var widthNegative = 1
|
||||||
|
|
||||||
|
while (true) {
|
||||||
|
if (!filled(rootx - widthNegative, rooty)) {
|
||||||
|
break
|
||||||
|
}
|
||||||
|
|
||||||
|
widthNegative++
|
||||||
|
}
|
||||||
|
|
||||||
|
// expand tall
|
||||||
|
var heightPositive = 1
|
||||||
|
|
||||||
|
while (true) {
|
||||||
|
if (!filled(rootx, rooty + heightPositive)) {
|
||||||
|
break
|
||||||
|
}
|
||||||
|
|
||||||
|
heightPositive++
|
||||||
|
}
|
||||||
|
|
||||||
|
var heightNegative = 1
|
||||||
|
|
||||||
|
while (true) {
|
||||||
|
if (!filled(rootx, rooty - heightNegative)) {
|
||||||
|
break
|
||||||
|
}
|
||||||
|
|
||||||
|
heightNegative++
|
||||||
|
}
|
||||||
|
|
||||||
|
widthPositive -= 1
|
||||||
|
widthNegative -= 1
|
||||||
|
|
||||||
|
heightNegative -= 1
|
||||||
|
heightPositive -= 1
|
||||||
|
|
||||||
|
if (heightPositive + heightNegative > widthPositive + widthNegative) {
|
||||||
|
// height is bigger
|
||||||
|
// try to expand wide
|
||||||
|
widthPositive = 0
|
||||||
|
widthNegative = 0
|
||||||
|
|
||||||
|
while (true) {
|
||||||
|
var escape = false
|
||||||
|
|
||||||
|
for (i in -heightNegative .. heightPositive) {
|
||||||
|
if (!filled(rootx + widthPositive, rooty + i)) {
|
||||||
|
escape = true
|
||||||
|
break
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (escape) {
|
||||||
|
break
|
||||||
|
}
|
||||||
|
|
||||||
|
widthPositive++
|
||||||
|
}
|
||||||
|
|
||||||
|
while (true) {
|
||||||
|
var escape = false
|
||||||
|
|
||||||
|
for (i in -heightNegative .. heightPositive) {
|
||||||
|
if (!filled(rootx - widthNegative, rooty + i)) {
|
||||||
|
escape = true
|
||||||
|
break
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (escape) {
|
||||||
|
break
|
||||||
|
}
|
||||||
|
|
||||||
|
widthNegative++
|
||||||
|
}
|
||||||
|
|
||||||
|
widthNegative -= 1
|
||||||
|
widthPositive -= 1
|
||||||
|
} else {
|
||||||
|
// height is equal or lesser than width
|
||||||
|
// expand high
|
||||||
|
heightNegative = 0
|
||||||
|
heightPositive = 0
|
||||||
|
|
||||||
|
while (true) {
|
||||||
|
var escape = false
|
||||||
|
|
||||||
|
for (i in -widthNegative .. widthPositive) {
|
||||||
|
if (!filled(rootx + i, rooty + heightPositive)) {
|
||||||
|
escape = true
|
||||||
|
break
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (escape) {
|
||||||
|
break
|
||||||
|
}
|
||||||
|
|
||||||
|
heightPositive++
|
||||||
|
}
|
||||||
|
|
||||||
|
while (true) {
|
||||||
|
var escape = false
|
||||||
|
|
||||||
|
for (i in -widthNegative .. widthPositive) {
|
||||||
|
if (!filled(rootx + i, rooty - heightNegative)) {
|
||||||
|
escape = true
|
||||||
|
break
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (escape) {
|
||||||
|
break
|
||||||
|
}
|
||||||
|
|
||||||
|
heightNegative++
|
||||||
|
}
|
||||||
|
|
||||||
|
heightNegative -= 1
|
||||||
|
heightPositive -= 1
|
||||||
|
}
|
||||||
|
|
||||||
|
mins = Vector2i(rootx - widthNegative, rooty - heightNegative)
|
||||||
|
maxs = Vector2i(rootx + widthPositive, rooty + heightPositive)
|
||||||
|
}
|
||||||
|
|
||||||
|
fun markSeen() {
|
||||||
|
for (x in mins.x .. maxs.x) {
|
||||||
|
for (y in mins.y .. maxs.y) {
|
||||||
|
seen[x or (y shl CHUNK_SHIFT)] = true
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private class RectTileFlooderSizeFirst(
|
||||||
|
private val tiles: Array<ChunkTile?>,
|
||||||
|
private val seen: BooleanArray,
|
||||||
|
private val rootx: Int,
|
||||||
|
private val rooty: Int
|
||||||
|
) {
|
||||||
|
val mins: Vector2i
|
||||||
|
val maxs: Vector2i
|
||||||
|
|
||||||
|
private fun filled(x: Int, y: Int): Boolean {
|
||||||
|
if (x < 0 || x > CHUNK_SIZE_FF) {
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
|
||||||
|
if (y < 0 || y > CHUNK_SIZE_FF) {
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
|
||||||
|
return !seen[x or (y shl CHUNK_SHIFT)] && tiles[x or (y shl CHUNK_SHIFT)] != null
|
||||||
|
}
|
||||||
|
|
||||||
|
private var widthPositive = 0
|
||||||
|
private var widthNegative = 0
|
||||||
|
private var heightPositive = 0
|
||||||
|
private var heightNegative = 0
|
||||||
|
|
||||||
|
private fun checkLeft(): Boolean {
|
||||||
|
for (i in -heightNegative .. heightPositive) {
|
||||||
|
if (!filled(rootx - widthNegative, rooty + i)) {
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
|
||||||
|
private fun checkRight(): Boolean {
|
||||||
|
for (i in -heightNegative .. heightPositive) {
|
||||||
|
if (!filled(rootx + widthPositive, rooty + i)) {
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
|
||||||
|
private fun checkUp(): Boolean {
|
||||||
|
for (i in -widthNegative .. widthPositive) {
|
||||||
|
if (!filled(rootx + i, rooty + heightPositive)) {
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
|
||||||
|
private fun checkDown(): Boolean {
|
||||||
|
for (i in -widthNegative .. widthPositive) {
|
||||||
|
if (!filled(rootx + i, rooty - heightNegative)) {
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
|
||||||
|
init {
|
||||||
|
var expanded = true
|
||||||
|
var hitLeft = false
|
||||||
|
var hitRight = false
|
||||||
|
var hitUp = false
|
||||||
|
var hitDown = false
|
||||||
|
|
||||||
|
while (expanded) {
|
||||||
|
expanded = false
|
||||||
|
|
||||||
|
// expand left
|
||||||
|
if (!hitLeft) {
|
||||||
|
widthNegative++
|
||||||
|
|
||||||
|
if (!checkLeft()) {
|
||||||
|
widthNegative--
|
||||||
|
hitLeft = true
|
||||||
|
} else {
|
||||||
|
expanded = true
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// expand up
|
||||||
|
if (!hitUp) {
|
||||||
|
heightPositive++
|
||||||
|
|
||||||
|
if (!checkUp()) {
|
||||||
|
heightPositive--
|
||||||
|
hitUp = true
|
||||||
|
} else {
|
||||||
|
expanded = true
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// expand right
|
||||||
|
if (!hitRight) {
|
||||||
|
widthPositive++
|
||||||
|
|
||||||
|
if (!checkRight()) {
|
||||||
|
widthPositive--
|
||||||
|
hitRight = true
|
||||||
|
} else {
|
||||||
|
expanded = true
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// expand down
|
||||||
|
if (!hitDown) {
|
||||||
|
heightNegative++
|
||||||
|
|
||||||
|
if (!checkDown()) {
|
||||||
|
heightNegative--
|
||||||
|
hitDown = true
|
||||||
|
} else {
|
||||||
|
expanded = true
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
mins = Vector2i(rootx - widthNegative, rooty - heightNegative)
|
||||||
|
maxs = Vector2i(rootx + widthPositive, rooty + heightPositive)
|
||||||
|
}
|
||||||
|
|
||||||
|
fun markSeen() {
|
||||||
|
for (x in mins.x .. maxs.x) {
|
||||||
|
for (y in mins.y .. maxs.y) {
|
||||||
|
seen[x or (y shl CHUNK_SHIFT)] = true
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private fun ccwSortScore(point: Vector2d, axis: Vector2d): Double {
|
||||||
|
if (point.x > 0.0) {
|
||||||
|
return point.dot(axis)
|
||||||
|
} else {
|
||||||
|
return -2 - point.dot(axis)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Чанк мира
|
* Чанк мира
|
||||||
*
|
*
|
||||||
@ -393,7 +776,7 @@ abstract class Chunk<WorldType : World<WorldType, This>, This : Chunk<WorldType,
|
|||||||
position = pos.firstBlock.toDoubleVector(),
|
position = pos.firstBlock.toDoubleVector(),
|
||||||
))
|
))
|
||||||
|
|
||||||
private val collisionBoxes = ArrayList<B2Fixture>()
|
private val collisionChains = ArrayList<B2Fixture>()
|
||||||
|
|
||||||
fun bakeCollisions() {
|
fun bakeCollisions() {
|
||||||
if (collisionChangeset == changeset)
|
if (collisionChangeset == changeset)
|
||||||
@ -402,59 +785,138 @@ abstract class Chunk<WorldType : World<WorldType, This>, This : Chunk<WorldType,
|
|||||||
collisionChangeset = changeset
|
collisionChangeset = changeset
|
||||||
collisionCache.clear()
|
collisionCache.clear()
|
||||||
|
|
||||||
for (box in collisionBoxes) {
|
for (box in collisionChains) {
|
||||||
body.destroyFixture(box)
|
body.destroyFixture(box)
|
||||||
}
|
}
|
||||||
|
|
||||||
collisionBoxes.clear()
|
collisionChains.clear()
|
||||||
|
|
||||||
val xAdd = pos.x * CHUNK_SIZEd
|
val xyAdd = Vector2d(pos.x * CHUNK_SIZEd, pos.y * CHUNK_SIZEd)
|
||||||
val yAdd = pos.y * CHUNK_SIZEd
|
val seen = BooleanArray(CHUNK_SIZE * CHUNK_SIZE)
|
||||||
|
|
||||||
for (y in 0 .. CHUNK_SIZE_FF) {
|
for (y in 0 .. CHUNK_SIZE_FF) {
|
||||||
var first: Int? = null
|
for (x in 0..CHUNK_SIZE_FF) {
|
||||||
var last = 0
|
if (!seen[x or (y shl CHUNK_SHIFT)] && tiles[x or (y shl CHUNK_SHIFT)] != null) {
|
||||||
|
val depthFirst = RectTileFlooderDepthFirst(tiles, seen, x, y)
|
||||||
|
val sizeFirst = RectTileFlooderSizeFirst(tiles, seen, x, y)
|
||||||
|
val xSpanDepth = depthFirst.maxs.x - depthFirst.mins.x
|
||||||
|
val ySpanDepth = depthFirst.maxs.y - depthFirst.mins.y
|
||||||
|
val xSpanSize = sizeFirst.maxs.x - sizeFirst.mins.x
|
||||||
|
val ySpanSize = sizeFirst.maxs.y - sizeFirst.mins.y
|
||||||
|
|
||||||
for (x in 0 .. CHUNK_SIZE_FF) {
|
val aabb: AABB
|
||||||
if (tiles[x or (y shl CHUNK_SHIFT)] != null) {
|
|
||||||
if (first == null) {
|
if (xSpanDepth + ySpanDepth > xSpanSize + ySpanSize) {
|
||||||
first = x
|
depthFirst.markSeen()
|
||||||
|
aabb = AABB(depthFirst.mins.toDoubleVector(), depthFirst.maxs.toDoubleVector() + Vector2d.POSITIVE_XY)
|
||||||
|
} else {
|
||||||
|
sizeFirst.markSeen()
|
||||||
|
aabb = AABB(sizeFirst.mins.toDoubleVector(), sizeFirst.maxs.toDoubleVector() + Vector2d.POSITIVE_XY)
|
||||||
}
|
}
|
||||||
|
|
||||||
last = x
|
collisionChains.add(body.createFixture(FixtureDef(
|
||||||
} else {
|
shape = PolygonShape().also { it.setAsBox(aabb.width / 2.0, aabb.height / 2.0, aabb.centre, 0.0) },
|
||||||
if (first != null) {
|
friction = 0.4,
|
||||||
val aabb = AABB(
|
)))
|
||||||
Vector2d(x = xAdd + first.toDouble(), y = y.toDouble() + yAdd),
|
|
||||||
Vector2d(x = xAdd + last.toDouble() + 1.0, y = y.toDouble() + 1.0 + yAdd),
|
|
||||||
)
|
|
||||||
|
|
||||||
collisionCache.add(aabb)
|
collisionCache.add(aabb + xyAdd)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
body.createFixture(FixtureDef(
|
/*
|
||||||
shape = PolygonShape().also { it.setAsBox(aabb.width / 2.0, aabb.height / 2.0, aabb.centre - pos.firstBlock.toDoubleVector(), 0.0) },
|
val seen = BooleanArray(CHUNK_SIZE * CHUNK_SIZE)
|
||||||
|
|
||||||
|
for (y in 0 .. CHUNK_SIZE_FF) {
|
||||||
|
for (x in 0 .. CHUNK_SIZE_FF) {
|
||||||
|
if (!seen[x or (y shl CHUNK_SHIFT)] && tiles[x or (y shl CHUNK_SHIFT)] != null) {
|
||||||
|
val exposed = TileFlooder(tiles, seen, x, y).exposed
|
||||||
|
|
||||||
|
if (exposed.size > 0) {
|
||||||
|
val vertices = ArrayList<Vector2d>()
|
||||||
|
var centroid = Vector2d.ZERO
|
||||||
|
|
||||||
|
for (pos in exposed) {
|
||||||
|
centroid += pos.pos
|
||||||
|
}
|
||||||
|
|
||||||
|
centroid /= exposed.size.toDouble()
|
||||||
|
|
||||||
|
for (pos in exposed) {
|
||||||
|
if (pos.left) {
|
||||||
|
vertices.addU(pos.pos + Vector2d(-0.5, -0.5))
|
||||||
|
vertices.addU(pos.pos + Vector2d(-0.5, 0.5))
|
||||||
|
}
|
||||||
|
|
||||||
|
if (pos.up) {
|
||||||
|
vertices.addU(pos.pos + Vector2d(-0.5, 0.5))
|
||||||
|
vertices.addU(pos.pos + Vector2d(0.5, 0.5))
|
||||||
|
}
|
||||||
|
|
||||||
|
if (pos.right) {
|
||||||
|
vertices.addU(pos.pos + Vector2d(0.5, 0.5))
|
||||||
|
vertices.addU(pos.pos + Vector2d(0.5, -0.5))
|
||||||
|
}
|
||||||
|
|
||||||
|
if (pos.down) {
|
||||||
|
vertices.addU(pos.pos + Vector2d(0.5, -0.5))
|
||||||
|
vertices.addU(pos.pos + Vector2d(-0.5, -0.5))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
for (i in vertices.indices) {
|
||||||
|
vertices[i] -= centroid
|
||||||
|
}
|
||||||
|
|
||||||
|
vertices.sortWith { a, b ->
|
||||||
|
val scoreA = ccwSortScore(a.normalized, Vector2d.POSITIVE_Y)
|
||||||
|
val scoreB = ccwSortScore(b.normalized, Vector2d.POSITIVE_Y)
|
||||||
|
|
||||||
|
if (scoreA == scoreB) {
|
||||||
|
return@sortWith 0
|
||||||
|
} else if (scoreA > scoreB) {
|
||||||
|
return@sortWith 1
|
||||||
|
} else {
|
||||||
|
return@sortWith -1
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
for (i in vertices.indices) {
|
||||||
|
vertices[i] += centroid
|
||||||
|
}
|
||||||
|
|
||||||
|
val deflated = ArrayList<Vector2d>()
|
||||||
|
var edge = vertices[0]
|
||||||
|
deflated.add(edge)
|
||||||
|
|
||||||
|
for (i in 1 until vertices.size) {
|
||||||
|
if (vertices[i].x == edge.x) {
|
||||||
|
// expand along X axis
|
||||||
|
continue
|
||||||
|
} else if (vertices[i].y == edge.y) {
|
||||||
|
// expand along Y axis
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
|
||||||
|
// completely different direction
|
||||||
|
|
||||||
|
if (deflated.indexOf(vertices[i - 1]) == -1)
|
||||||
|
deflated.add(vertices[i - 1])
|
||||||
|
|
||||||
|
if (deflated.indexOf(vertices[i]) == -1)
|
||||||
|
deflated.add(vertices[i])
|
||||||
|
|
||||||
|
edge = vertices[i]
|
||||||
|
}
|
||||||
|
|
||||||
|
collisionChains.add(body.createFixture(FixtureDef(
|
||||||
|
shape = ChainShape().also { it.createLoop(vertices) },
|
||||||
friction = 0.4,
|
friction = 0.4,
|
||||||
))
|
)))
|
||||||
|
|
||||||
first = null
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
}*/
|
||||||
if (first != null) {
|
|
||||||
val aabb = AABB(
|
|
||||||
Vector2d(x = first.toDouble() + xAdd, y = y.toDouble() + yAdd),
|
|
||||||
Vector2d(x = last.toDouble() + 1.0 + xAdd, y = y.toDouble() + 1.0 + yAdd),
|
|
||||||
)
|
|
||||||
|
|
||||||
collisionCache.add(aabb)
|
|
||||||
|
|
||||||
body.createFixture(FixtureDef(
|
|
||||||
shape = PolygonShape().also { it.setAsBox(aabb.width / 2.0, aabb.height / 2.0, aabb.centre - pos.firstBlock.toDoubleVector(), 0.0) },
|
|
||||||
friction = 0.4,
|
|
||||||
))
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -575,3 +1037,9 @@ abstract class Chunk<WorldType : World<WorldType, This>, This : Chunk<WorldType,
|
|||||||
)
|
)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private fun <E> AbstractList<E>.addU(e: E) {
|
||||||
|
if (indexOf(e) == -1) {
|
||||||
|
add(e)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user