{"id":648,"date":"2023-12-10T12:42:08","date_gmt":"2023-12-10T12:42:08","guid":{"rendered":"https:\/\/timohonig.nl\/?p=648"},"modified":"2024-10-09T06:54:28","modified_gmt":"2024-10-09T06:54:28","slug":"game-1","status":"publish","type":"post","link":"https:\/\/timohonig.nl\/index.php\/2023\/12\/10\/game-1\/","title":{"rendered":"Smoke Out"},"content":{"rendered":"\n<p><strong>About<\/strong><br>Smoke out is a first person shooter which focusses on defeating AI enemies which take on the roles of a drugs cartel. As a police officer you must defeat all the cartel members and secure the objectives to win. <\/p>\n\n\n\n<figure class=\"wp-block-embed is-type-video is-provider-youtube wp-block-embed-youtube wp-embed-aspect-16-9 wp-has-aspect-ratio\"><div class=\"wp-block-embed__wrapper\">\n<iframe loading=\"lazy\" title=\"Cops &amp; Robbers Game\" width=\"500\" height=\"281\" src=\"https:\/\/www.youtube.com\/embed\/AtUYJrtbyHQ?feature=oembed\" frameborder=\"0\" allow=\"accelerometer; autoplay; clipboard-write; encrypted-media; gyroscope; picture-in-picture; web-share\" referrerpolicy=\"strict-origin-when-cross-origin\" allowfullscreen><\/iframe>\n<\/div><\/figure>\n\n\n\n<p class=\"has-medium-font-size\"><strong>Project Info<\/strong><br>Group Size: 3<br>Project Length: 4 Weeks<br>Project Date: February 2024<br>Engine &amp; Tools: Unity, Visual Studio Code &amp; Trello<\/p>\n\n\n\n<p><br><strong>Finite State Machines<\/strong><br>In this project, I took charge of designing and implementing the enemy AI and behavior, a task that allowed me to get a better understanding of game AI. One of the key components I developed was a finite state machine (FSM) to manage the behavior of cartel members within the game.<\/p>\n\n\n\n<p class=\"has-text-align-left\">Rather than settling for conventional enemy AI that simply advances towards the player or wanders aimlessly, I sought to create a more dynamic and engaging experience. My solution involved crafting a system where AI characters prioritize seeking cover before strategically peeking around corners to take shots at the player. <\/p>\n\n\n\n<p>Here you can see the enemies getting a cover position and entering the &#8220;taking cover&#8221; state.<\/p>\n\n\n\n<details class=\"wp-block-details is-layout-flow wp-block-details-is-layout-flow\"><summary>Partial AI Movement Code<\/summary>\n<pre class=\"wp-block-code\"><code>private void LookForCoverState(AState pState, float pDeltaTime)\n{\n    CheckForDisengage();\n    if (!_coverIsFound)\n    {\n        _newCover = AISeekCover.Instance.GetCover(Target.transform.position);\n        _coverIsFound = true;\n    }\n\n    if (_newCover == null)\n    {\n        _stateMachine.Goto(EStates.Wander);\n        return;\n    }\n\n    \/\/ Set the location for the AI and move towards it\n    _animator.SetBool(\"IsWalking\", true);\n    Vector3 locationToGo = _newCover.transform.position;\n    _agent.SetDestination(locationToGo);\n    ApplyRotation();\n\n    float distance = Vector3.Distance(transform.position, locationToGo);\n\n    \/\/ If target arrived at cover\n    if (distance &lt;= 2)\n    {\n        _animator.SetBool(\"IsWalking\", false);\n        _stateMachine.Goto(EStates.LookForEnemy);\n        return;\n    }\n}<\/code><\/pre>\n<\/details>\n\n\n\n<figure data-wp-context=\"{&quot;imageId&quot;:&quot;6a045416e343a&quot;}\" data-wp-interactive=\"core\/image\" data-wp-key=\"6a045416e343a\" class=\"wp-block-image size-full wp-lightbox-container\"><img loading=\"lazy\" decoding=\"async\" width=\"2033\" height=\"1141\" data-wp-class--hide=\"state.isContentHidden\" data-wp-class--show=\"state.isContentVisible\" data-wp-init=\"callbacks.setButtonStyles\" data-wp-on--click=\"actions.showLightbox\" data-wp-on--load=\"callbacks.setButtonStyles\" data-wp-on-window--resize=\"callbacks.setButtonStyles\" src=\"https:\/\/timohonig.nl\/wp-content\/uploads\/2024\/05\/Smokeout_AI_Movement.gif\" alt=\"\" class=\"wp-image-707\"\/><button\n\t\t\tclass=\"lightbox-trigger\"\n\t\t\ttype=\"button\"\n\t\t\taria-haspopup=\"dialog\"\n\t\t\taria-label=\"Enlarge\"\n\t\t\tdata-wp-init=\"callbacks.initTriggerButton\"\n\t\t\tdata-wp-on--click=\"actions.showLightbox\"\n\t\t\tdata-wp-style--right=\"state.imageButtonRight\"\n\t\t\tdata-wp-style--top=\"state.imageButtonTop\"\n\t\t>\n\t\t\t<svg xmlns=\"http:\/\/www.w3.org\/2000\/svg\" width=\"12\" height=\"12\" fill=\"none\" viewBox=\"0 0 12 12\">\n\t\t\t\t<path fill=\"#fff\" d=\"M2 0a2 2 0 0 0-2 2v2h1.5V2a.5.5 0 0 1 .5-.5h2V0H2Zm2 10.5H2a.5.5 0 0 1-.5-.5V8H0v2a2 2 0 0 0 2 2h2v-1.5ZM8 12v-1.5h2a.5.5 0 0 0 .5-.5V8H12v2a2 2 0 0 1-2 2H8Zm2-12a2 2 0 0 1 2 2v2h-1.5V2a.5.5 0 0 0-.5-.5H8V0h2Z\" \/>\n\t\t\t<\/svg>\n\t\t<\/button><\/figure>\n\n\n\n<p>Here you can see the enemies when they reach a cover position. They decide to shoot at the target, and take cover after firing for a while. <\/p>\n\n\n\n<details class=\"wp-block-details is-layout-flow wp-block-details-is-layout-flow\"><summary>Partial AI Shooting Code<\/summary>\n<pre class=\"wp-block-code\"><code>    private void ShootState(AState pState, float pDeltaTime)\n    {\n        CheckForDisengage();\n\n        RotateTowardsTarget();\n\n        _animator.SetBool(\"TakingCover\", false);\n        _animator.SetBool(\"AbleToShoot\", true);\n\n        _gun.CanShoot = true;\n\n        if (_targetToShoot == null)\n        {\n            return;\n        }\n\n        _gun.SetTarget(_targetToShoot.transform);\n\n        \/\/ Checks if this state is active for _MinTimer amount of time\n        if (pState.Lifetime &lt; _MinTimer)\n        {\n            return;\n        }\n        else if (pState.Lifetime &gt; _MinTimer)\n        {\n            _stateMachine.Goto(EStates.TakeCover);\n        }\n    }<\/code><\/pre>\n<\/details>\n\n\n\n<figure data-wp-context=\"{&quot;imageId&quot;:&quot;6a045416e3a83&quot;}\" data-wp-interactive=\"core\/image\" data-wp-key=\"6a045416e3a83\" class=\"wp-block-image size-large wp-lightbox-container\"><img loading=\"lazy\" decoding=\"async\" width=\"1024\" height=\"574\" data-wp-class--hide=\"state.isContentHidden\" data-wp-class--show=\"state.isContentVisible\" data-wp-init=\"callbacks.setButtonStyles\" data-wp-on--click=\"actions.showLightbox\" data-wp-on--load=\"callbacks.setButtonStyles\" data-wp-on-window--resize=\"callbacks.setButtonStyles\" src=\"https:\/\/timohonig.nl\/wp-content\/uploads\/2024\/05\/Smokeout_AI_Shooting-4-1024x574.gif\" alt=\"\" class=\"wp-image-716\" srcset=\"https:\/\/timohonig.nl\/wp-content\/uploads\/2024\/05\/Smokeout_AI_Shooting-4-1024x574.gif 1024w, https:\/\/timohonig.nl\/wp-content\/uploads\/2024\/05\/Smokeout_AI_Shooting-4-300x168.gif 300w, https:\/\/timohonig.nl\/wp-content\/uploads\/2024\/05\/Smokeout_AI_Shooting-4-768x431.gif 768w, https:\/\/timohonig.nl\/wp-content\/uploads\/2024\/05\/Smokeout_AI_Shooting-4-1536x861.gif 1536w\" sizes=\"auto, (max-width: 1024px) 100vw, 1024px\" \/><button\n\t\t\tclass=\"lightbox-trigger\"\n\t\t\ttype=\"button\"\n\t\t\taria-haspopup=\"dialog\"\n\t\t\taria-label=\"Enlarge\"\n\t\t\tdata-wp-init=\"callbacks.initTriggerButton\"\n\t\t\tdata-wp-on--click=\"actions.showLightbox\"\n\t\t\tdata-wp-style--right=\"state.imageButtonRight\"\n\t\t\tdata-wp-style--top=\"state.imageButtonTop\"\n\t\t>\n\t\t\t<svg xmlns=\"http:\/\/www.w3.org\/2000\/svg\" width=\"12\" height=\"12\" fill=\"none\" viewBox=\"0 0 12 12\">\n\t\t\t\t<path fill=\"#fff\" d=\"M2 0a2 2 0 0 0-2 2v2h1.5V2a.5.5 0 0 1 .5-.5h2V0H2Zm2 10.5H2a.5.5 0 0 1-.5-.5V8H0v2a2 2 0 0 0 2 2h2v-1.5ZM8 12v-1.5h2a.5.5 0 0 0 .5-.5V8H12v2a2 2 0 0 1-2 2H8Zm2-12a2 2 0 0 1 2 2v2h-1.5V2a.5.5 0 0 0-.5-.5H8V0h2Z\" \/>\n\t\t\t<\/svg>\n\t\t<\/button><\/figure>\n\n\n\n<p>By implementing this FSM-based AI, I worked on my ability to make enemy AI and worked with this type of system for the first time. This project served as a stepping stone for my knowledge about AI and i have a greater knowledge about how Finite State Machines work.<\/p>\n","protected":false},"excerpt":{"rendered":"<p>Smoke out is a first person shooter which focusses on defeating AI enemies which take on the roles of a drugs cartel. As a police officer you must defeat all the cartel members and secure the objectives to win. <\/p>\n","protected":false},"author":1,"featured_media":703,"comment_status":"closed","ping_status":"closed","sticky":false,"template":"","format":"standard","meta":{"footnotes":""},"categories":[9,8],"tags":[],"class_list":["post-648","post","type-post","status-publish","format-standard","has-post-thumbnail","hentry","category-all-projects","category-favorite"],"_links":{"self":[{"href":"https:\/\/timohonig.nl\/index.php\/wp-json\/wp\/v2\/posts\/648","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/timohonig.nl\/index.php\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/timohonig.nl\/index.php\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/timohonig.nl\/index.php\/wp-json\/wp\/v2\/users\/1"}],"replies":[{"embeddable":true,"href":"https:\/\/timohonig.nl\/index.php\/wp-json\/wp\/v2\/comments?post=648"}],"version-history":[{"count":11,"href":"https:\/\/timohonig.nl\/index.php\/wp-json\/wp\/v2\/posts\/648\/revisions"}],"predecessor-version":[{"id":718,"href":"https:\/\/timohonig.nl\/index.php\/wp-json\/wp\/v2\/posts\/648\/revisions\/718"}],"wp:featuredmedia":[{"embeddable":true,"href":"https:\/\/timohonig.nl\/index.php\/wp-json\/wp\/v2\/media\/703"}],"wp:attachment":[{"href":"https:\/\/timohonig.nl\/index.php\/wp-json\/wp\/v2\/media?parent=648"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/timohonig.nl\/index.php\/wp-json\/wp\/v2\/categories?post=648"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/timohonig.nl\/index.php\/wp-json\/wp\/v2\/tags?post=648"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}