0
$\begingroup$

I'm trying to render sprites/textures in my raycasting engine, but I don't quite understand the math behind drawing the columns of the texture I intend to project. I've tried looking at several tutorials, e.g., lodev, Wynnliam, and several posts on Allegro.cc, but none of them seem to explain the sprite-casting component in an easy-to-digest way. Can anyone help? Note that I'm currently drawing a yellow square in the location of the sprite and it appears as if the sprite is not positioned in the correct spot... My main problem is that I don’t understand how to compute the column of the texture to render. Once I figure this out, I can easily add z-depth sorting, but I really have no idea how to do this step.

        final int TEXTURE_SIZE = 64;
        final int PROJ_HEIGHT = 640;
        final int PROJ_WIDTH = 640;
        ArrayList<TextureSprite> sprites = this.RAYCASTER_PANEL.getTileMap().getSprites();
        for (int s = 0; s < sprites.size(); s++) {
            TextureSprite sp = sprites.get(s);
            // computes the distance and angle of the sprite...
            double fov = this.RAYCASTER_PANEL.getCamera().getFov();
            double ca = this.getCamera().getCurrentAngle();
            double dx = sp.getX() - this.RAYCASTER_PANEL.getCamera().getX();
            double dy = sp.getY() - this.RAYCASTER_PANEL.getCamera().getY();
            double d = Point2D.distanceSq(sp.getX(), sp.getY(), this.RAYCASTER_PANEL.getCamera().getX(), this.RAYCASTER_PANEL.getCamera().getY());
            double theta_temp = Math.toDegrees(Math.atan2(dy, dx));
            if(theta_temp < 0) theta_temp += 360;
            if (theta_temp > 360) theta_temp -= 360;

            double y = ca + fov/2 - theta_temp;

            if(theta_temp > 270 && ca < 90) y = ca + fov/2 - theta_temp + 360;
            if(ca > 270 && theta_temp < 90) y = ca + fov/2 - theta_temp - 360;
     
            // attempt to compute the sprite's x, y, width, and height
            double sw = (TEXTURE_SIZE / Math.sqrt(d)) * this.getCamera().getDistanceToProjectionPlane();
            double sh = sw;
            double sx = (y * PROJ_HEIGHT / fov) - sw/2.f;
            double sy = (PROJ_HEIGHT / 2.f) - (TEXTURE_SIZE / 2.f);

            // Just a temporary until I understand how to draw the textures themselves...
            g2.setColor(Color.YELLOW);
            g2.fillRect((int)sx,(int)sy,(int)sw,(int)sh);

Example of the problem

Code after @lightxbulb's post suggestion:

            final int PROJ_WIDTH=1280; // changed 
            TextureSprite sp = sprites.get(s);
            double fov = this.getCamera().getFov();
            double ca = this.getCamera().getCurrentAngle();
            double px = this.getCamera().getX();
            double py = this.getCamera().getY();
            double sx = sp.getX();
            double sy = sp.getY();

            double dx = sx - px;
            double dy = sy - py;
            double sprite_dir = Math.toDegrees(Math.atan2(dy, dx));
            while (sprite_dir - ca > 180) sprite_dir -= 360;
            while (sprite_dir - ca < -180) sprite_dir += 360;

            double sprite_dist = Math.sqrt(Math.pow(px - sp.getX(), 2) + Math.pow(py - sp.getY(), 2));
            double sprite_screen_size = Math.min(2000, PROJ_HEIGHT / sprite_dist);
            int h_offset = (int) ((sprite_dir - ca) * (PROJ_WIDTH/2) / (fov) + (PROJ_WIDTH/2)/2 - sprite_screen_size / 2);
            int v_offset = (int) (PROJ_HEIGHT/2 - sprite_screen_size / 2);
            g2.setColor(Color.YELLOW);
            for (int i = 0; i < sprite_screen_size; i++) {
                // Adding these range guards prevents any rendering whatsoever
                if (h_offset+i<0||h_offset+i>PROJ_WIDTH/2) continue;
                for (int j = 0; j < sprite_screen_size; j++) {
                    g2.fillRect(PROJ_WIDTH/2+h_offset+i,v_offset+j,1,1);
                }
            }
$\endgroup$
2
  • $\begingroup$ I can recommend this: github.com/ssloy/tinyraycaster/wiki/Part-1:-crude-3D-renderings $\endgroup$
    – lightxbulb
    Jul 16, 2022 at 9:46
  • $\begingroup$ @lightxbulb So, I tried following their tutorial and my code still isn't rendering the shapes correctly. Even when just trying to draw a simple square on the screen, it doesn't show up at all if I try to add the bounds (e.g., if (h_offset + i < 0 || ...). If I remove those, the square shows up but it's never rendered correctly. I can move up close to it and it'll zoom in really fast then fade out... I've added my new code to the post. $\endgroup$ Jul 16, 2022 at 13:18

0

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Browse other questions tagged or ask your own question.