0

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);
                }
            }
  • I can recommend this: https://github.com/ssloy/tinyraycaster/wiki/Part-1:-crude-3D-renderings – lightxbulb Jul 16 '22 at 09:46
  • @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. – Joshua Crotts Jul 16 '22 at 13:18

0 Answers0