{"id":21441489,"url":"https://github.com/slideshow776/terfenstein-3d","last_synced_at":"2025-07-14T16:32:18.123Z","repository":{"id":45734814,"uuid":"513472102","full_name":"Slideshow776/Terfenstein-3D","owner":"Slideshow776","description":":star: My first 3D shooter game, made with LibGDX :star:","archived":false,"fork":false,"pushed_at":"2024-11-06T07:45:00.000Z","size":177989,"stargazers_count":22,"open_issues_count":1,"forks_count":2,"subscribers_count":2,"default_branch":"master","last_synced_at":"2024-11-06T08:31:45.993Z","etag":null,"topics":["3d-game","libgdx","pixel-art","shooter-game","women-in-tech"],"latest_commit_sha":null,"homepage":"https://sandramoen.no","language":"Java","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":null,"status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/Slideshow776.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":".github/FUNDING.yml","license":null,"code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null},"funding":{"github":"slideshow776","patreon":null,"open_collective":null,"ko_fi":null,"tidelift":null,"community_bridge":null,"liberapay":null,"issuehunt":null,"otechie":null,"lfx_crowdfunding":null,"custom":null}},"created_at":"2022-07-13T10:10:39.000Z","updated_at":"2024-11-06T07:45:05.000Z","dependencies_parsed_at":"2023-02-09T19:01:17.451Z","dependency_job_id":null,"html_url":"https://github.com/Slideshow776/Terfenstein-3D","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/Slideshow776%2FTerfenstein-3D","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/Slideshow776%2FTerfenstein-3D/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/Slideshow776%2FTerfenstein-3D/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/Slideshow776%2FTerfenstein-3D/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/Slideshow776","download_url":"https://codeload.github.com/Slideshow776/Terfenstein-3D/tar.gz/refs/heads/master","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":225988916,"owners_count":17555941,"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":["3d-game","libgdx","pixel-art","shooter-game","women-in-tech"],"created_at":"2024-11-23T01:27:12.501Z","updated_at":"2024-11-23T01:27:14.018Z","avatar_url":"https://github.com/Slideshow776.png","language":"Java","funding_links":["https://github.com/sponsors/slideshow776"],"categories":[],"sub_categories":[],"readme":"# Terfenstein 3D\n\n[Official Trailer](https://youtu.be/BUj2IYbL-zI)\n\n[![Trailer thumbnaik](https://user-images.githubusercontent.com/4059636/201704064-5a339898-6c23-4ee2-8d4f-5ac62d32c9a0.png)](https://youtu.be/BUj2IYbL-zI)\n\n[Buy it on Steam?](https://store.steampowered.com/app/2192840/Terfenstein_3D/?beta=0)\n\n[![Main Capsule](https://user-images.githubusercontent.com/4059636/200133991-84551e8a-26b2-4126-8695-40a6689ac5de.png)](https://store.steampowered.com/app/2192840/Terfenstein_3D/?beta=0)\n\n![image](https://user-images.githubusercontent.com/4059636/184866741-be475fb3-9945-4740-a251-5781a98a6eea.gif)\n\nRead on below for project specifics.\n\n1. [Game Design Document](#game-design-document-sparkling_heart)\n2. [Credits](#credits)\n3. [Project Comments](#project-comments)\n4. [Other](#other)\n5. [Project Kanban Board](https://github.com/Slideshow776/3D-shooting-game/projects/1)\n\n## Game Design Document :sparkling_heart:\n\n1. :blue_heart: Overall Vision \n    * **Write a short paragraph explaining the game:**\n    \n       This is a first person shooter (fps) about infiltrating gender fascists facility and disabling their weapons of mass destruction.       \n            \n    * **Describe the genre:**\n\n         \u003e First-person shooter (FPS) is a sub-genre of shooter video games centered on gun and other weapon-based combat in a first-person perspective, with the player experiencing the action through the eyes of the protagonist and controlling the player character in a three-dimensional space. --[wikipedia](https://en.wikipedia.org/wiki/First-person_shooter)\n        \n    * **What is the target audience?**\n    \n    The average player is assumed to be aware of the transphobic pressure that exists to transgendered peope by the media and TERFs\n        \n    * **Why play this game?**\n    \n2. :purple_heart: Mechanics: the rules of the game world\n    * **What are the character's goals?**\n           \n    * **What abilities does the character have?**\n        \n    * **What obstacles or difficulties will the character face?**\n        \n    * **What items can the character obtain**\n        \n    * **What resources must be managed?**  \n        \n 3. :heart: Dynamics: the interaction between the player and the game mechanics\n    * **What hardware is required by the game?** \n\n        * Desktop needs to have a functional mouse, keyboard, and screen. This game will not require a powerful computer.\n        \n    * **What type of proficiency will the player need to develop to become proficient at the game?**\n       \n    * **What gameplay data is displayed during the game?**\n    \n    * **What menus, screens, or overlays will there be?**\n   \n    * **How does the player interact with the game at the software level?**\n    \n4. :green_heart: Aesthetics: the visual, audio, narrative, and psychological aspects of the game\n    * **Describe the style and feel of the game.**\n   \n    * **Does the game use pixel art, line art, or realistic graphics?**\n        \n    * **What style of background music, ambient sounds will the game use?**\n           \n    * **What is the relevant backstory for the game?** \n        \n    * **What emotional state(s) does the game try to provoke?**\n       \n    * **What makes the game fun?**\n        \n5. :yellow_heart: Development \n    \n    * **List the team members and their roles, responsibilities, and skills.**  \n      \n        This project will be completed individually; graphics and audio will be obtained from third-party websites that make their assets available under the Creative Commons license, and so the main task will be programming and creating some graphics.\n    \n    * **What equipment is needed for this project?**   \n\n        A computer (with keyboard, mouse, and speakers) and internet access will be necessary to complete this project.\n    \n    * **What are the tasks that need to be accomplished to create this game?**    \n        \n        This project will use a simple Kanban board hosted on the project's GitHub page.\n        The main sequence of steps to complete this project is as follows:    \n        * Setting up a project scaffold\n        * **Programming game mechanics and UI**\n        * **Creating and obtaining graphical assets**\n        * Obtaining audio assets\n        * Controller support\n        * **Polishing**\n        * Deployment\n\n    * **What points in the development process are suitable for playtesting?**    \n        \n        The main points for playtesting are when the basic game mechanics of the level screen are implemented, and when it is visualised. The questions that will be asked are:         \n        * Is the gameplay and UI understandable?\n        * Is the gameplay interesting?\n        * How do the controls feel?\n        * How is the pace of the game?\n        * Are there any improvement suggestions?        \n    \n    * **What are the plans for publication?**\n\n## Credits\n\n## Project comments\n### Wall clipping\nTo stop the wall from clipping out of sight it is necessary to set the `camera.near` to a very tiny amount, like so:\n```\ncamera = new PerspectiveCamera(67, Gdx.graphics.getWidth(), Gdx.graphics.getHeight());\ncamera.lookAt(0, 0, 0);\ncamera.near = .01f;\ncamera.far = 100f;\ncamera.update();\n```\n### Player movement\nThe cursor can be locked to the window like this line of code: `Gdx.input.setCursorCatched(true);`. In HTML this needs to be triggered multiple times to ensure the correct application behaviour.\n\nKeyboard movement is as simple as this: \n```\nprivate void keyboardPolling(float dt) {\n   if (Gdx.input.isKeyPressed(Input.Keys.W))\n      stage.moveCameraForward(speed * dt);\n   if (Gdx.input.isKeyPressed(Input.Keys.A))\n      stage.moveCameraRight(speed * dt);\n   if (Gdx.input.isKeyPressed(Input.Keys.S))\n      stage.moveCameraForward(-speed * dt);\n   if (Gdx.input.isKeyPressed(Input.Keys.D))\n      stage.moveCameraRight(-speed * dt);\n}\n```\n\nMouse movement is this simple line:\n```\nprivate void mousePolling() {\n    turnBy(rotateSpeed * Gdx.input.getDeltaX() * BaseGame.mouseMovementSensitivity);\n    stage.turnCamera(rotateSpeed * Gdx.input.getDeltaX() * BaseGame.mouseMovementSensitivity);\n}\n```\n\n### Collisions\nWhile the game is 3D viewed from a birds perspective the area of movement is 2D, and thus we can implement a simple/standard 2D collision detection system using these functions found in [`BaseActor3D.java`](https://github.com/Slideshow776/Terfenstein-3D/blob/master/source%20code/core/src/no/sandramoen/commanderqueen/actors/utils/baseActors/BaseActor3D.java): \n* `setBaseRectangle()`\n* `setBasePolygon()`\n* `getBoundaryPolygon()`\n* `overlaps(BaseActor3D other)`\n* `preventOverlap(BaseActor3D other)`\n\n### Frustum Culling\n![demo](https://user-images.githubusercontent.com/4059636/179392342-22c26f1b-775d-49b6-8f44-ed7992cc1aa7.gif)\n\nAs explained in [this blog](https://xoppa.github.io/blog/3d-frustum-culling-with-libgdx/) one can save computer resources by only drawing the 3D world entities that are visible, this is called frustum culling. Feature added in [this commit](https://github.com/Slideshow776/3D-shooting-game/commit/b8b4f9183c6923a61a60fabbc4b729be8523ebe2).\n\n### Ray Picking\n![image](https://user-images.githubusercontent.com/4059636/179480413-eb9409c7-0b68-4168-aa83-17a3e187834a.png)\n\u003e Mathematically, a ray is the portion of a line that originates from a fixed point and extends indefinitely in a particular direction. A ray always travels in a straight line in a medium until it hits the boundary of the medium that it is traveling in. \n\u003e\n\u003eOnce it hits that boundary, it can either get reflected, refracted, absorbed, or undergo all three operations partially. \u003e-- \u003ccite\u003e[techcenturion.com](https://www.techcenturion.com/ray-tracing)\u003c/cite\u003e\n\nRay picking was implemented following [this tutorial](https://xoppa.github.io/blog/interacting-with-3d-objects/) and can be seen in [this commit](https://github.com/Slideshow776/3D-shooting-game/commit/55d86d4240be404148fd7d3fe5502e6591f9f13b).\n\n### Tile Maps\nTile maps were implemented [like so](https://github.com/Slideshow776/3D-shooting-game/commit/edddec5d5e640447599fe48c0d940af20ee898e7).\n\n![image](https://user-images.githubusercontent.com/4059636/179554378-55590c98-aa44-45e3-a6ce-30da743743ed.png)\n\n### Directional Sprites\nEight directional sprites were added in [this commit](https://github.com/Slideshow776/3D-shooting-game/commit/1191866abdba55cc8dbda692d030d859626b2033).\nThe play can now circle an enemy and see it from behind, etc. This allows for gameplay where the enemy is not always facing the player ready to attack.\n\n![eight directional sprites example](https://user-images.githubusercontent.com/4059636/181704832-6e015a4c-68b3-4573-94fe-c12480758664.gif)\n\n\n### Enemy Ray Picking\nYou don't need a camera to ray pick. The algorithm was expanded to support simple non-camera rays too =\u003e \n```\npublic static int getRayPickedListIndex(Vector3 origin, Vector3 direction, Array\u003cBaseActor3D\u003e list) {\n    Ray ray = new Ray(origin, direction);\n    return getClosestListIndex(ray, list);\n}\n\npublic static int getRayPickedListIndex(int screenX, int screenY, Array\u003cBaseActor3D\u003e list, PerspectiveCamera camera) {\n    Ray ray = camera.getPickRay(screenX, screenY);\n    return getClosestListIndex(ray, list);\n}\n\nprivate static int getClosestListIndex(Ray ray, Array\u003cBaseActor3D\u003e list) {\n    int index = -1;\n    float distance = -1;\n    for (int i = 0; i \u003c list.size; ++i) {\n        final float dist2 = list.get(i).modelData.intersects(ray);\n        if (dist2 \u003e= 0f \u0026\u0026 (distance \u003c 0f || dist2 \u003c= distance)) {\n            index = i;\n            distance = dist2;\n        }\n    }\n    return index;\n}\n```\nThis allows for the enemy to scan for the player to detect them, and also to be able to shoot them.\nRaypicking should be used sparingly, this game runs the algorithm for all enemies not dead, facing the player, at it's own interval.\n\n### Pathfinding\nLibGDX's [AI library](https://github.com/libgdx/gdx-ai) was included in [this](https://github.com/Slideshow776/3D-shooting-game/commit/85b5b903a4aa80ca0621bc0a6462f40481b43761) and [this](https://github.com/Slideshow776/3D-shooting-game/commit/7aaa1c3a9080e70785d45faa4b5848deb7654dfc) commits following [this excellent tutorial](https://happycoding.io/tutorials/libgdx/pathfinding).\nThe pathfinding is a directional improvement upon [Dijkstra's algorithm](https://en.wikipedia.org/wiki/Dijkstra%27s_algorithm) and enables us to tell the enemies where to go.\nThis algorithm is used sparingly whenever there is a sound the enemy should respond to or get the last position of the player's last sighting. This opens up more interesting gameplay.\n\n![Dijkstra's improved algorithm A*](https://happycoding.io/tutorials/libgdx/images/dijkstra-search.gif)\n\n### Decals\nA [decal](https://libgdx.com/wiki/graphics/3d/decals) is a 2D image in a 3D world. In this project it's used to generate an effect where the bullet hits stuff, e.g. a wall.\nThis project implements this with a parent [class manager](https://github.com/Slideshow776/Terfenstein-3D/blob/master/source%20code/core/src/no/sandramoen/commanderqueen/actors/decals/DecalsManager.java) that can be [extended](https://github.com/Slideshow776/Terfenstein-3D/blob/master/source%20code/core/src/no/sandramoen/commanderqueen/actors/decals/BulletDecals.java), and then used [like so](https://github.com/Slideshow776/Terfenstein-3D/blob/master/source%20code/core/src/no/sandramoen/commanderqueen/screens/gameplay/LevelScreen.java).\n```\nVector3 temp = new Vector3().set(ray.direction).scl(player.distanceBetween(shootable.get(i)) - (Tile.diagonalLength / 2)).add(ray.origin);\nbulletDecals.addDecal(temp.x, temp.y, temp.z);\n```\nThis code will get the wall's position, and create a new `Decal` at roughly the wall's facing surface.\n\n### Camera Rolling\nFor a lean-into-walking-direction effect:\n![roll demo](https://user-images.githubusercontent.com/4059636/188260161-cc00ca97-c036-4eb5-8391-6f4f9b4064d1.gif)\n![camera-movement](https://user-images.githubusercontent.com/4059636/188260208-71410b8b-cc0d-4922-868f-d2067d1bebdd.png)\n```\nprivate void keyboardPolling(float dt) {\n    if (Gdx.input.isKeyPressed(Keys.A))\n        rollAngle = MathUtils.clamp(rollAngle -= ROLL_INCREMENT, -ROLL_ANGLE_MAX, ROLL_ANGLE_MAX);\n\n    if (Gdx.input.isKeyPressed(Keys.D))\n        rollAngle = MathUtils.clamp(rollAngle += ROLL_INCREMENT, -ROLL_ANGLE_MAX, ROLL_ANGLE_MAX);\n\n    if (!Gdx.input.isKeyPressed(Keys.A) \u0026\u0026 !Gdx.input.isKeyPressed(Keys.D)) {\n      if (rollAngle \u003e 0)\n          rollAngle -= ROLL_INCREMENT;\n      else if (rollAngle \u003c 0)\n          rollAngle += ROLL_INCREMENT;\n    }\n}   \n```\n```\npublic void rollCamera(float angle) {\n    camera.up.set(Vector3.X);\n    camera.rotate(camera.direction, angle);\n}\n```\n\n### Level Design\nSome level design facets that are used are:\n* lights\n* affordances\n* visual guidance\n* pickups\n* pacing (remember downbeats)\n* leading lines\n* local landmarks\n* avoid straights\n* junctions\n* choices of traversal\n* gating\n* bread crumbs\n* negative space\n* readability (is it easy to know where to go?)\n* environmental storytelling\n* illusion of space\n\nThese, and more, are covered in [this book](https://www.lulu.com/shop/max-pears/lets-design-exploration/paperback/product-zerwr7.html?page=1\u0026pageSize=4).\n\n[![image](https://user-images.githubusercontent.com/4059636/194706249-e244466e-0cb2-41e9-9599-3f78370f1d86.png)](https://www.lulu.com/shop/max-pears/lets-design-exploration/paperback/product-zerwr7.html?page=1\u0026pageSize=4)\n\n### Convert `.jar` to `.exe`\nFollow [this tutorial](https://fullstackdeveloper.guru/2020/06/17/how-to-create-a-windows-native-java-application-generating-exe-file/) to do so.\nTo automate this process checkout the [desktop build file](https://github.com/Slideshow776/Terfenstein-3D/blob/master/source%20code/desktop/build.gradle).\n\nAlternatively use [packr](https://github.com/libgdx/packr#usage) with the following commands\n```\njava -jar packr-all-4.0.0.jar \n--platform \"windows64\" \n--jdk \"C:\\Program Files\\Java\\jdk-15.0.1\" \n--useZgcIfSupportedOs \n--executable \"Terfenstein 3D\" \n--classpath \"C:\\Users\\Sandra Moen\\dev\\Terfenstein 3D\\source code\\desktop\\build\\lib\\Terfenstein 3D.jar\" \n--mainclass \"no.sandramoen.terfenstein3D.DesktopLauncher\" \n--resources \"C:\\Users\\Sandra Moen\\dev\\Terfenstein 3D\\source code\\assets\" \n--output \"C:\\Users\\Sandra Moen\\Desktop\\Terfenstein 3D\\packr build files\"\n```\n\n## Other\nFor other project specifics check out the [commits](https://github.com/Slideshow776/3D-shooting-game/commits/master).\n\n[Go back to the top](https://github.com/Slideshow776/Terfenstein-3D#terfenstein-3d).\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fslideshow776%2Fterfenstein-3d","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fslideshow776%2Fterfenstein-3d","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fslideshow776%2Fterfenstein-3d/lists"}