{"id":24072928,"url":"https://github.com/markusmoenig/raycaster","last_synced_at":"2025-04-28T15:32:28.289Z","repository":{"id":65166911,"uuid":"584316440","full_name":"markusmoenig/raycaster","owner":"markusmoenig","description":"A Raycaster engine written in Rust","archived":false,"fork":false,"pushed_at":"2023-03-18T04:28:01.000Z","size":5973,"stargazers_count":18,"open_issues_count":0,"forks_count":0,"subscribers_count":3,"default_branch":"master","last_synced_at":"2025-03-30T10:51:10.931Z","etag":null,"topics":["game-engine","graphics","raycaster","raycasting","rust"],"latest_commit_sha":null,"homepage":"","language":"Rust","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"mit","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/markusmoenig.png","metadata":{"files":{"readme":"Readme.md","changelog":null,"contributing":null,"funding":".github/FUNDING.yml","license":"License.txt","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null},"funding":{"github":"markusmoenig"}},"created_at":"2023-01-02T08:00:18.000Z","updated_at":"2025-03-30T00:33:09.000Z","dependencies_parsed_at":"2023-02-14T06:02:20.438Z","dependency_job_id":null,"html_url":"https://github.com/markusmoenig/raycaster","commit_stats":null,"previous_names":[],"tags_count":0,"template":false,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/markusmoenig%2Fraycaster","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/markusmoenig%2Fraycaster/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/markusmoenig%2Fraycaster/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/markusmoenig%2Fraycaster/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/markusmoenig","download_url":"https://codeload.github.com/markusmoenig/raycaster/tar.gz/refs/heads/master","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":251338650,"owners_count":21573590,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2022-07-04T15:15:14.044Z","host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":["game-engine","graphics","raycaster","raycasting","rust"],"created_at":"2025-01-09T17:23:17.921Z","updated_at":"2025-04-28T15:32:28.170Z","avatar_url":"https://github.com/markusmoenig.png","language":"Rust","funding_links":["https://github.com/sponsors/markusmoenig"],"categories":[],"sub_categories":[],"readme":"# A Rust based Raycaster engine\n\n![Image](images/demo.gif)\n\nThis is a full featured raycaster engine to produce game graphics similar to Wolfenstein 3D. I need it to create 3D dungeons for my retro RPG creator [Eldiron](https://github.com/markusmoenig/Eldiron).\n\nThe caster renders into a ```Vec\u003cu8\u003e``` frame. Next to [rayon](https://crates.io/crates/rayon), which is needed for multithreading, the only other dependency of the crate right now is [rustc-hash](https://crates.io/crates/rustc-hash) for a fast HashMap.\n\nFor single threaded rendering enable the *\"single_threaded\"* feature (for example for WASM targets). Multi threaded rendering is about 2-4 times faster than single threaded on my machine.\n\nA demo application using [pixels](https://crates.io/crates/pixels) is available in the *demo* directory.\n\n## Features\n\n* Textured or colored walls, ceiling and floor\n* Adjustable fog color and distance\n* Sprites\n* Animation support\n* Multi-threaded or single-threaded rendering\n* Tile based lighting\n\n## Todo\n\n* Doors\n\n## Multi-threaded Rendering\n\nAs a raycaster works with stripes of pixels (instead of slices) the internal rendering stores the image 90 percent rotated so that it can work with slices. This helps with memory access and makes it possible to use rayon for multithreading. The image is than rotated back into the destination frame, this too is done in parallel.\n\nMultithreaded rendering of an 1280x800 image is done in about 2-3 ms on my machine. Single threaded rendering takes about 7-8 ms. The renderer should be fast enough to handle 4k resolutions.\n\n## Usage\n\nCreate a world map:\n\n```rust\nuse raycaster::prelude::*;\n\nlet mut world = WorldMap::new();\n\n// Add an image containing the tilemap to the world\nlet image_id = world.add_image(tilemap, tilemap_width, tilemap_height);\n\n// Create a textured tile and use it for the ceiling default\n// The rectangle defines the tile in the tilemap\nlet ceiling_tile = Tile::textured(image_id, (0, 0, 24, 24));\nworld.set_ceiling_tile();\n\n// Set a colored tile for the floor\nworld.set_floor_tile(Tile::colored([50, 50, 50, 255]));\n\n// Add a wall with a tile at the given location\n// Add as many walls as you like\nworld.set_wall(5, 7, tile...);\n\n// Add a bat sprite at the given location.\n// You can manage the sprites yourself as WorldMap::sprites is public.\nlet sprite = Sprite::new(7.0, 7.0, tile...);\nworld.add_sprite(sprite);\n\n// Torch Sprite\nlet mut sprite = Sprite::new(4.1, 6.1, Tile::textured_anim(image_id, calc_tile_rect(14, 14, 24,), 2));\nsprite.shrink = 2; // Scale the sprite down\nsprite.move_y = -100.0; // Move the sprite up\nworld.add_sprite(sprite);\nworld.add_light(4, 6, 2); // Add a light source at the torch position\n\n// Set the fog color and the fog distance, the distance is in tiles.\nworld.set_fog([10, 10, 10, 255], 6.0);\n```\n\nWhen we have set up the world we can render it:\n\n```rust\n\nconst width: usize = 800;\nconst height: usize = 600;\n\nlet frame = vec![0; width * height * 4];\n\nlet mut caster = Raycaster::new();\n\n// Set the position pf the player\ncaster.set_pos(9, 7);\n\n// Render into the given rectangle inside the frame (here the full frame), the stride (i.e. the width of the frame) and the world.\ncaster.render(\u0026mut frame[..], (0, 0, width, height), width, \u0026mut world);\n```\n\n## Acknowledgements\n\n* Inspiration was provided by Pikumas excellent [Raycaster Tutorial Series](https://pikuma.com/courses/raycasting-engine-tutorial-algorithm-javascript).\n* The basic idea of the raycaster is based on the [Lodev's Raycaster Tutorial](https://lodev.org/cgtutor/raycasting.html).\n\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fmarkusmoenig%2Fraycaster","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fmarkusmoenig%2Fraycaster","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fmarkusmoenig%2Fraycaster/lists"}