Exit Full View

Games Cupboard / gamescupboard-server / src / main / kotlin / uk / co / nickthecoder / gamescupboard / server / AvatarPositions.kt

package uk.co.nickthecoder.gamescupboard.server

import uk.co.nickthecoder.gamescupboard.common.Avatar
import uk.co.nickthecoder.gamescupboard.common.playingAreaHeight
import uk.co.nickthecoder.gamescupboard.common.playingAreaWidth

interface AvatarPositions {
    fun position(avatar: Avatar, players: Int)
}

data class Vector2i(val x: Int, val y: Int)

class FixedAvatarPositions(private val positions: List<Vector2i>, val sides: List<Int> = emptyList()) :
    AvatarPositions {
    override fun position(avatar: Avatar, players: Int) {
        val index = (avatar.playerId - 1) % positions.size
        val pos = positions[index]
        avatar.x = pos.x
        avatar.y = pos.y
        avatar.side = sides.getOrNull(index) ?: 0
    }
}

class CornerAvatarPositions(
    private val left: Int,
    private val top: Int,
    private val bottom: Int,
    private val right: Int

) : AvatarPositions {

    override fun position(avatar: Avatar, players: Int) {

        avatar.x = if ((avatar.playerId - 1) % 2 == 0) {
            left
        } else {
            right
        }
        avatar.y = if (avatar.playerId / 2 % 2 == 0) {
            avatar.side = 0
            top
        } else {
            avatar.side = 2
            bottom
        }
    }
}

/**
 * Arranged in a vertical line.
 * The top and bottom margins are half the size of the spacing between the Avatars.
 */
class VerticalAvatarPositions(
    private val x: Int,
    private val side : Int = 1

) : AvatarPositions {
    override fun position(avatar: Avatar, players: Int) {
        avatar.x = x
        avatar.y = ((avatar.playerId - 0.5) * playingAreaHeight / players).toInt()
        avatar.side = side
    }
}

/**
 * Arranged in a vertical line.
 * The top and bottom margins are half the size of the spacing between the Avatars.
 */
class SpacedVerticalAvatarPositions(
    private val x: Int,
    private val y: Int,
    private val spacing: Int,
    private val side : Int = 1

) : AvatarPositions {
    override fun position(avatar: Avatar, players: Int) {
        avatar.x = x
        avatar.y = y + spacing * avatar.playerId
        avatar.side = side
    }
}

class HorizontalAvatarPositions(
    private val y: Int,
    private val side : Int = 0

) : AvatarPositions {
    override fun position(avatar: Avatar, players: Int) {
        avatar.y = y
        avatar.x = ((avatar.playerId - 0.5) * playingAreaWidth / players).toInt()
        avatar.side = side
    }
}

class TopAndBottomAvatarPositions(
    private val top: Int,
    private val bottom: Int,
    private val margin: Int = 0,

    /**
     * Make the avatars follow a clockwise order.
     * Otherwise, they will be left to right at the top and the bottom.
     */
    private val around: Boolean = true

) : AvatarPositions {

    override fun position(avatar: Avatar, players: Int) {
        val isTop = (avatar.playerId - 1) % 2 == 0
        avatar.y = if (isTop) {
            avatar.side = 0
            top
        } else {
            avatar.side = 2
            bottom
        }
        val n = (avatar.playerId - 1) / 2
        val from = if (players % 2 == 0 || !isTop) players / 2 else players / 2 + 1
        // When margin==0, we calculate the margins based on the number of seats on this side of the table.
        if (margin == 0) {
            // Spread across the whole width, with an automatic margin left and right
            avatar.x = ((n + 0.5) * playingAreaWidth / from).toInt()
        } else {
            if (from == 1) {
                // In the middle
                avatar.x = playingAreaWidth / 2
            } else {
                // Spread from margin to playingAreaWidth-margin
                avatar.x = margin + n * (playingAreaWidth - margin * 2) / (from - 1)
            }
        }
        if (around && !isTop) {
            avatar.x = playingAreaWidth - avatar.x
        }
    }
}