littlektframework / littlekt

A multiplatform WebGPU 2D game framework written in Kotlin. Build your own game engine on top.
https://littlekt.com
Apache License 2.0
321 stars 12 forks source link

Tilemap rendering glitching when moving camera, on FitViewport #239

Closed ValleyDragon888 closed 7 months ago

ValleyDragon888 commented 7 months ago

I have some code that renders a tilemap onto a FitViewport, and a script that moves the camera up when you press W. However, as soon as you press W, all of the tilemap dissapears, and you are just left with one tile.

Before pressing W: image After pressing W: image

Here is the code:


class Game(context: Context) : ContextListener(context) {

    override suspend fun Context.start() {
        val batch = SpriteBatch(this)
        val shapeRenderer = ShapeRenderer(batch)
        val viewport = FitViewport(960, 540)
        val camera = viewport.camera
        val tiledMap: TiledMap = resourcesVfs["level.tmj"].readTiledMap()
        var cameraX = 0f

        onResize { width, height ->
            viewport.update(width, height, context)
        }

        onRender { dt ->
            gl.clearColor(Color.DARK_GRAY)
            gl.clear(ClearBufferMask.COLOR_BUFFER_BIT)

            batch.use(camera.viewProjection) {
                // You can use multiple viewports, so, maybe we could usethis new
                // FitViewport for rendering the tilemap, and a different viewport
                // for some sort of border. (THE DOCS, NOT THE DOKKA, THE PLAIN ENGLISH ONES)
                var x = -viewport.virtualWidth/2
                var y = -viewport.virtualHeight/2
                tiledMap.render(it, camera, x=x, y=y)

                camera.lookAt(cameraX, 0f, 0f)
                if(input.isKeyPressed(Key.W)) { cameraX += 1f }
            }
        }
    }

    companion object {
        private val logger = Logger<Game>()
    }
}  

I'm using Tiled.

ValleyDragon888 commented 7 months ago

This contains all of the needed tiled files

level.zip

LeHaine commented 7 months ago

Camera.lookAt() shouldn't be used to reposition the camera. That function is recalculating the camera direction. For OrthographicCamera that is set to Vec3f.Z_AXIS which is (0,0,1). To move the camera you should use the position property and update it directly. E.g. camera.position.x += 1f.

One other thing you need to do is call camera.update() before you use the viewProjection matrix in order for the matrices to be updated for rendering.



class Game(context: Context) : ContextListener(context) {

    override suspend fun Context.start() {
        val batch = SpriteBatch(this)
        val shapeRenderer = ShapeRenderer(batch)
        val viewport = FitViewport(960, 540)
        val camera = viewport.camera
        val tiledMap: TiledMap = resourcesVfs["level.tmj"].readTiledMap()
        var cameraX = 0f

        onResize { width, height ->
            viewport.update(width, height, context)
        }

        onRender { dt ->
            gl.clearColor(Color.DARK_GRAY)
            gl.clear(ClearBufferMask.COLOR_BUFFER_BIT)

+         camera.update()
            batch.use(camera.viewProjection) {
                // You can use multiple viewports, so, maybe we could usethis new
                // FitViewport for rendering the tilemap, and a different viewport
                // for some sort of border. (THE DOCS, NOT THE DOKKA, THE PLAIN ENGLISH ONES)
                var x = -viewport.virtualWidth/2
                var y = -viewport.virtualHeight/2
                tiledMap.render(it, camera, x=x, y=y)

-               camera.lookAt(cameraX, 0f, 0f)
+                if(input.isKeyPressed(Key.W)) { camera.position.x += 1f }
            }
        }
    }

    companion object {
        private val logger = Logger<Game>()
    }
}
ValleyDragon888 commented 7 months ago

Thanks for the info!