davidaramant / RayCaster

A ray casting game engine
4 stars 0 forks source link

Textures restricted to 40x40 #1

Open Wrathchild34 opened 6 years ago

Wrathchild34 commented 6 years ago

Is this correct? Array runs over when a larger or smaller png file is used.

davidaramant commented 6 years ago

I'm pretty sure that's not true; the textures I was using earlier were not 40x40. Are you just replacing the pngs that are already there or are you updating the Content.mgcb too? What size textures are you trying to use? Where is the exception happening?

I haven't touched this code in several years so I don't remember all the intricacies but I can take a look when I get home.

davidaramant commented 6 years ago

LOL I just found this comment in GameEngine.cs: // * Why does it calculate texture offsets beyond the bounds sometimes?????? I'm sure there's some off-by-one error somewhere, but a lot of the code was copied from other sites/tutorials so I don't fully understand the cases that would cause them.

Wrathchild34 commented 6 years ago

Oh! I hadn't replaced every single texture! Now it works!

Cool stuff, blast from the past for you, I guess. Thanks!

davidaramant commented 6 years ago

No problem! If you end up doing anything with the code, I would love to see it :)

Wrathchild34 commented 6 years ago

Yeah, I'll see. What I want to add is some fog, roaming monsters, bullets (so essentially sprites...) and picking up stuff with the mouse. Most of the other stuff you e.g. stated in the TO-DO comments aren't that interesting to me. Do you think this will be complicated to do so? And, BTW, CPU use goes up to 97% occasionally (in debug mode) with this, but it doesn't slow down... isn't that odd...

davidaramant commented 6 years ago

Fog should be pretty easy since the raycaster already determines the distance to whatever is being shown. I noticed that I already even pass the distance into the drawing function for floors/ceilings but it isn't used yet. There is a sector-based lighting system already in the engine; the map is just set up to show something really boring currently. If you switch lines 115 and 116 in MapData.cs it will put in random light levels in all the tiles instead.

I never got around to sprite rendering, but I think the Lode fellow had some tutorials on that too.

I would expect the engine to always use 100% CPU. The main rendering loop uses Parallel.For because it was way too slow single-threaded. I'm not sure TPL is intended to be used in a real-time game engine like this but it seems to work OK. You should definitely use Release mode as much as possible because it is dramatically faster.

Wrathchild34 commented 6 years ago

Hi friend,

I have found some time last weekend and for fun I provisionally hacked the Lodev tutorial about the sprites into the code. It draws the sprite and scales them, but the screen positions are wrong and move weirdly. I don't find any deviation in the code so I wonder if you have changed something that does not make this work. You must not hurry with the answer, but it would be nice if you'd could glimpse over it ;)

` for (int i = 0; i < _mapData.ReturnGameObjectListSize(); i++) {

            byte lightLevel = 3;

            var spriteTexture = _mapData.ReturnGameObjectTexture(i);

            double spriteX = _mapData.ReturnGameObject(i).x - _player.Position.X;
            double spriteY = _mapData.ReturnGameObject(i).y - _player.Position.Y;

            double invDet = 1.0 / (_player.CameraPlane.X * _player.Direction.Y - _player.Direction.X * _player.CameraPlane.Y);

            double transformX = invDet * (_player.Direction.Y * spriteX - _player.Direction.X * spriteY);
            double transformY = invDet * (-_player.CameraPlane.Y * spriteX + _player.CameraPlane.X * spriteY);

            int spriteScreenX = (int)((buffer.Width / 2) * (1 + (transformX / transformY)));

            Console.WriteLine(spriteScreenX + " SPRITE SCREEN X"); // IS WRONG

            int spriteHeight = Math.Abs((int)(buffer.Height / (transformY))); 

            Console.WriteLine(spriteHeight + " SPRITE HEIGHT"); // [seems ok]

            int drawStartY = -spriteHeight / 2 + buffer.Height / 2;
            if (drawStartY < 0) { drawStartY = 0; }

            Console.WriteLine(drawStartY + "START DRAW Y");

            int drawEndY = spriteHeight / 2 + buffer.Height / 2;
            if (drawEndY >= buffer.Height) { drawEndY = buffer.Height - 1; }
            if (drawEndY < 0) { drawEndY = 1;  }

            Console.WriteLine(drawEndY + "END DRAW Y");

            int spriteWidth = Math.Abs((int)(buffer.Height / (transformY))); 

            Console.WriteLine(spriteWidth + " SPRITE WIDTH X"); // [seems ok]

            int drawStartX = -spriteWidth / 2 + spriteScreenX;
            if (drawStartX < 0) { drawStartX = 0; }

            Console.WriteLine(drawStartY + "START DRAW X");

            int drawEndX = spriteWidth / 2 + spriteScreenX;
            if (drawEndX >= buffer.Width) { drawEndX = buffer.Width - 1; }

            Console.WriteLine(drawEndY + "END DRAW X");

            for (int stripe = drawStartX; stripe < drawEndX; stripe++)
            {
                int texXX = (int)(256 * (stripe - (-spriteWidth / 2 + spriteScreenX)) * spriteTexture.Width / spriteWidth) / 256;

                if (transformY > 0 && stripe > 0 && stripe < buffer.Width && transformY < buffer.ReturnZBuffer(stripe))
                {
                    for (int y = drawStartY; y < drawEndY; y++)
                    {
                        int d = (y) * 256 - buffer.Height * 128 + spriteHeight * 128;

                        int texYY = ((d * spriteTexture.Height) / spriteHeight) / 256;

                        int color = 0;

                        if(texXX < 1200 && texYY < 800)
                        {
                            color = spriteTexture[texXX, texYY];
                        }
                        else
                        {
                            color = spriteTexture[77, 66];

                        }

                        if ((color != 0) && (0x00FFFFFF != color))
                        {

                            if (stripe < 810)
                            {

                                buffer[y, stripe] = _mapData.Shade(color, lightLevel);

                            }

                        } //paint pixel if it isn't black, black is the invisible color

                    }

                }

            }

        }`
davidaramant commented 6 years ago

I don't remember any specifics that far back, but I don't think I did anything weird with coordinates.

Can you push your repo clone so I can see it running?

Wrathchild34 commented 6 years ago

Hi, sorry that I didn't answer, it worked with multiplying the x coordinate with -1, for whatever reason. ;)

Do you actually have an idea how to incorporate thin walls? I think DDA jumps from grid to grid, so how do you find something that's supposed to be within the grid?

davidaramant commented 6 years ago

"thin wall" - a zero-width wall between two tile spaces?

How projects like ECWolf handle it is that those would be represented by a different tile type. The relevant part of its level format spec is tile definitions.

You can think of a map as two parts - a palette of tile types and then a big grid that references those.

For example, lets define three tile types: . = empty space # = a solid wall with textures on all four sides _ = a tile with no texture on the east/north/west sides but a see-through chain-link fence on the south side (I assume this might be what you're going for)

#...#
#___#
#...#
#...#

This snippet would then describe a hallway that appears to be evenly divided by a section of fence.

In this code base, you would have to extend the SectorInfo class in MapData to hold this data. Textures and a blocking boolean (whether you can walk through that side or not) for all four sides should be enough.