{"id":846,"date":"2024-10-11T22:34:00","date_gmt":"2024-10-11T20:34:00","guid":{"rendered":"https:\/\/wesleydegraaf.com\/?page_id=846"},"modified":"2025-04-14T23:47:45","modified_gmt":"2025-04-14T21:47:45","slug":"signaller","status":"publish","type":"page","link":"https:\/\/wesleydegraaf.com\/en\/signaller\/","title":{"rendered":"Signaller"},"content":{"rendered":"\n<div class=\"wp-block-cover\" style=\"min-height:280px;aspect-ratio:unset;\"><span aria-hidden=\"true\" class=\"wp-block-cover__background has-palette-color-1-background-color has-background-dim-100 has-background-dim\"><\/span><div class=\"wp-block-cover__inner-container is-layout-flow wp-block-cover-is-layout-flow\">\n<p class=\"has-text-align-center has-x-large-font-size wp-block-paragraph\"><strong>Signaller<\/strong><\/p>\n<\/div><\/div>\n\n\n\n<figure class=\"wp-block-embed alignright 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=\"Signaller Gameplay\" width=\"1290\" height=\"726\" src=\"https:\/\/www.youtube.com\/embed\/0m8Ys7OovRM?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=\"wp-block-paragraph\">Tijdens keuzedeel moesten we een game maken voor een museum. Wij kozen voor het Spoorwegmuseum. Signaller is een game waarbij de speler de rol van een trein verkeersleider speelt. De speler moet treinen van punt A naar punt B brengen door seinen op groen te zetten en de baan vrij te maken voor de trein. De speler heeft ook controle over de wissels. Zorg dat treinen optijd rijden en niet tegen elkaar op rijden. De game heeft 2 levels, hierbij is geen rekening gehouden met de moeilijkheidsgraad. Het 1e level bestaat uit 2 stations en het 2e level uit 3. Het doel van de game is om een zo hoog mogelijke score te halen. Deze score komt op een scoreboard met Dagelijks, Wekelijks en lifetime scores. De art style van de game is simple, omdat een trein verkeersleider een heel simpel scherm heeft. Wij wouden dit namaken, maar nog wel wat meer detail geven dan normaal.<br><br>Signaller is origineel ontworpen voor een museum en ook een groot scherm met touchscreen. De game is speelbaar op een desktop, maar de ervaring is het best op een groot touchscreen scherm (Input support meerdere vingers). Dingen zoals inactiviteits timers zijn dus aanwezig in de reguliere versie. <\/p>\n\n\n\n<hr class=\"wp-block-separator has-alpha-channel-opacity is-style-default\"\/>\n\n\n\n<h4 class=\"wp-block-heading\"><mark style=\"background-color:rgba(0, 0, 0, 0)\" class=\"has-inline-color has-palette-color-1-color\">Project Info:<\/mark><\/h4>\n\n\n\n<p class=\"wp-block-paragraph\">Teamleden: David van Rijn &amp; Robin van den Dungen<br>Project tijd: Jaar 4 Periode 3 (2023)<br>Engine: Unity<br>Code Languages: C#<br>Design Patterns: Singleton &amp; FlyWeight<\/p>\n\n\n\n<div class=\"wp-block-columns is-layout-flex wp-container-core-columns-is-layout-995f960e wp-block-columns-is-layout-flex\">\n<div class=\"wp-block-column is-layout-flow wp-block-column-is-layout-flow\" style=\"flex-basis:100%\">\n<figure class=\"wp-block-gallery has-nested-images columns-default is-cropped wp-block-gallery-1 is-layout-flex wp-block-gallery-is-layout-flex\">\n<figure class=\"wp-block-image size-large\"><a href=\"https:\/\/wesleydegraaf.com\/wp-content\/uploads\/2024\/10\/image-3.png\" target=\"_blank\" rel=\"noopener\"><img loading=\"lazy\" decoding=\"async\" width=\"1024\" height=\"576\" data-id=\"955\" src=\"https:\/\/wesleydegraaf.com\/wp-content\/uploads\/2024\/10\/image-3-1024x576.png\" alt=\"\" class=\"wp-image-955\" srcset=\"https:\/\/wesleydegraaf.com\/wp-content\/uploads\/2024\/10\/image-3-1024x576.png 1024w, https:\/\/wesleydegraaf.com\/wp-content\/uploads\/2024\/10\/image-3-300x169.png 300w, https:\/\/wesleydegraaf.com\/wp-content\/uploads\/2024\/10\/image-3-768x432.png 768w, https:\/\/wesleydegraaf.com\/wp-content\/uploads\/2024\/10\/image-3-1536x864.png 1536w, https:\/\/wesleydegraaf.com\/wp-content\/uploads\/2024\/10\/image-3-18x10.png 18w, https:\/\/wesleydegraaf.com\/wp-content\/uploads\/2024\/10\/image-3.png 1919w\" sizes=\"auto, (max-width: 1024px) 100vw, 1024px\" \/><\/a><\/figure>\n\n\n\n<figure class=\"wp-block-image size-large\"><a href=\"https:\/\/wesleydegraaf.com\/wp-content\/uploads\/2024\/10\/SignallerTitle.png\" target=\"_blank\" rel=\"noopener\"><img loading=\"lazy\" decoding=\"async\" width=\"1024\" height=\"576\" data-id=\"957\" src=\"https:\/\/wesleydegraaf.com\/wp-content\/uploads\/2024\/10\/SignallerTitle-1024x576.png\" alt=\"\" class=\"wp-image-957\" srcset=\"https:\/\/wesleydegraaf.com\/wp-content\/uploads\/2024\/10\/SignallerTitle-1024x576.png 1024w, https:\/\/wesleydegraaf.com\/wp-content\/uploads\/2024\/10\/SignallerTitle-300x169.png 300w, https:\/\/wesleydegraaf.com\/wp-content\/uploads\/2024\/10\/SignallerTitle-768x432.png 768w, https:\/\/wesleydegraaf.com\/wp-content\/uploads\/2024\/10\/SignallerTitle-1536x864.png 1536w, https:\/\/wesleydegraaf.com\/wp-content\/uploads\/2024\/10\/SignallerTitle-18x10.png 18w, https:\/\/wesleydegraaf.com\/wp-content\/uploads\/2024\/10\/SignallerTitle.png 1919w\" sizes=\"auto, (max-width: 1024px) 100vw, 1024px\" \/><\/a><\/figure>\n\n\n\n<figure class=\"wp-block-image size-large\"><a href=\"https:\/\/wesleydegraaf.com\/wp-content\/uploads\/2024\/10\/image-4.png\" target=\"_blank\" rel=\"noopener\"><img loading=\"lazy\" decoding=\"async\" width=\"1024\" height=\"578\" data-id=\"956\" src=\"https:\/\/wesleydegraaf.com\/wp-content\/uploads\/2024\/10\/image-4-1024x578.png\" alt=\"\" class=\"wp-image-956\" srcset=\"https:\/\/wesleydegraaf.com\/wp-content\/uploads\/2024\/10\/image-4-1024x578.png 1024w, https:\/\/wesleydegraaf.com\/wp-content\/uploads\/2024\/10\/image-4-300x169.png 300w, https:\/\/wesleydegraaf.com\/wp-content\/uploads\/2024\/10\/image-4-768x433.png 768w, https:\/\/wesleydegraaf.com\/wp-content\/uploads\/2024\/10\/image-4-1536x866.png 1536w, https:\/\/wesleydegraaf.com\/wp-content\/uploads\/2024\/10\/image-4-2048x1155.png 2048w, https:\/\/wesleydegraaf.com\/wp-content\/uploads\/2024\/10\/image-4-18x10.png 18w\" sizes=\"auto, (max-width: 1024px) 100vw, 1024px\" \/><\/a><\/figure>\n<\/figure>\n<\/div>\n<\/div>\n\n\n\n<div style=\"height:100px\" aria-hidden=\"true\" class=\"wp-block-spacer\"><\/div>\n\n\n\n<h2 class=\"wp-block-heading has-palette-color-1-color has-text-color has-link-color wp-elements-c2360c2104768b3fd3293a7ac3b17e79\">Tools<\/h2>\n\n\n\n<p class=\"wp-block-paragraph\">Tijdens het maken van Signaller heb ik voornamelijk gewerkt aan tools voor het bouwen van de levels. Deze tools zorgde ervoor dat levels maken een heel stuk sneller ging. Het waren simpele buttons, maar op de achtergrond stelde ze veel in voor het rail network. Je kon RailNodes voor en na andere Railnodes maken en deze verplaatsen. Later heb ik ook nog de &#8220;Enter Rail Placemode&#8221; toegevoegd deze functionaliteit plaatste een railnode aan het einde waar je klikte met je muis. Door deze tool ging het bouwen van een level sneller dan zonder. Het snel ittereren op level design was ook zeer makkelijk met 1 knop een signal toevoegen. De tool kon ook een mesh maken van het gemaakte level, hierdoor was het level exact hetzelfde als de debug liet zien. De game gebruikt ook vertex painting om de switch state aan te duiden.<\/p>\n\n\n\n<figure class=\"wp-block-image aligncenter size-large is-resized\"><img loading=\"lazy\" decoding=\"async\" width=\"1024\" height=\"736\" src=\"https:\/\/wesleydegraaf.com\/wp-content\/uploads\/2024\/10\/Signaller-Tool-1-1024x736.png\" alt=\"\" class=\"wp-image-975\" style=\"width:882px;height:auto\" srcset=\"https:\/\/wesleydegraaf.com\/wp-content\/uploads\/2024\/10\/Signaller-Tool-1-1024x736.png 1024w, https:\/\/wesleydegraaf.com\/wp-content\/uploads\/2024\/10\/Signaller-Tool-1-300x216.png 300w, https:\/\/wesleydegraaf.com\/wp-content\/uploads\/2024\/10\/Signaller-Tool-1-768x552.png 768w, https:\/\/wesleydegraaf.com\/wp-content\/uploads\/2024\/10\/Signaller-Tool-1-18x12.png 18w, https:\/\/wesleydegraaf.com\/wp-content\/uploads\/2024\/10\/Signaller-Tool-1.png 1380w\" sizes=\"auto, (max-width: 1024px) 100vw, 1024px\" \/><\/figure>\n\n\n<div class=\"dm-code-snippet light no-background  dm-normal-version\" style=\"background-color:#abb8c3;\" snippet-height=\"600px\">\n\t\t\t<div class=\"control-language\">\n                <div class=\"dm-buttons\">\n                    <div class=\"dm-buttons-left\">\n                        <div class=\"dm-button-snippet red-button\"><\/div>\n                        <div class=\"dm-button-snippet orange-button\"><\/div>\n                        <div class=\"dm-button-snippet green-button\"><\/div>\n                    <\/div>\n                    <div class=\"dm-buttons-right\">\n                        <a id=\"dm-copy-raw-code\">\n                        <span class=\"dm-copy-text\">Get the Code!<\/span>\n                        <span class=\"dm-copy-confirmed\" style=\"display:none\">You have it!<\/span>\n                        <span class=\"dm-error-message\" style=\"display:none\">Use a different Browser<\/span><\/a>\n                    <\/div>\n                <\/div>\n                <pre class=\"line-numbers\"><code id=\"dm-code-raw\" class=\"wrap language-typescript\">\n<pre>\n    private Transform CreateRailNode(bool isParent, Transform node)\n    {\n        Transform nodeTransform = node;\n        if (!isParent) nodeTransform = node.parent;\n\n        RailBlock railBlock = nodeTransform.GetComponent<RailBlock>();\n        RailNode lastRailNode = railBlock.railNodes[railBlock.railNodes.Count - 1];\n\n        railBlock.railNodes.Add(CreateNewRailNode(nodeTransform, lastRailNode.transform.localPosition, lastRailNode.transform.localRotation));\n\n        GameObject railNode = railBlock.railNodes[railBlock.railNodes.Count - 1].gameObject;\n        Selection.activeGameObject = railNode;\n\n        EditorUtility.SetDirty(railNode);\n        return railNode.transform;\n    }\n\n    private T CreateOtherNode<T>(string name) where T : RailNode \n    {\n        GameObject currentNode = Selection.activeGameObject;\n\n        RailBlock railBlock = currentNode.transform.parent.GetComponent<RailBlock>();\n        RailNode currentRailNode = currentNode.GetComponent<RailNode>();\n\n        int railNodeIndex = railBlock.railNodes.IndexOf(currentRailNode);\n        railBlock.railNodes.Remove(currentRailNode);\n\n        DestroyImmediate(currentRailNode);\n        T stationNode = currentNode.AddComponent<T>();\n        railBlock.railNodes.Insert(railNodeIndex, stationNode);\n        currentNode.name = $\"{name} {currentNode.name.Split(' ')[1].Split(\"-\")[0]}-{railBlock.name.Split(' ')[1]}\";\n\n        Selection.activeGameObject = stationNode.gameObject;\n\n        EditorUtility.SetDirty(stationNode);\n        return stationNode;\n    }\n<\/pre>\n<\/code><\/pre>\n\t\t\t<\/div>\n        <\/div>\n\n\n\n<p class=\"has-text-align-center wp-block-paragraph\">Met CreateOtherNode kunnen we elke RailNode aanmaken die gebruik maakt van RailNode, hierdoor hoeven we niet voor elke node een script aan te maken.<\/p>\n\n\n\n<div style=\"height:67px\" aria-hidden=\"true\" class=\"wp-block-spacer\"><\/div>\n\n\n\n<h2 class=\"wp-block-heading has-palette-color-1-color has-text-color has-link-color wp-elements-06aacc7bf15eca9a29fb4e9df5962cdb\">RailNodes<\/h2>\n\n\n\n<p class=\"wp-block-paragraph\">RailNodes zijn objecten in de scene. Deze kunnen uit de volgende nodes bestaan: RailNode, DirectionNode, DespawnNode, ExitNode, SignalNode, SpawningNode, StationNode en SwitchNode. Alle nodes zitten in een RailBlock vanaf hier wordt ook de mesh beheert van de lijn. Treinen weten op welk RailBlock ze rijden en op welke Node. Alle RailBlocks zitten in de RailRoot het hoofd object van de RailObjecten. Treinen kunnen instructies negeren als de directie niet hetzelfde is als de rij richting (DirectionNode).<br><br>De Signalnode en Switchnode waren het meest complex om te implemeteren. Signals kunnen ook op oranje\/geel staan. Dit is afhankelijk van de sein die er na komt, maar een switch kan ervoor zorgen dat een eerst volgende sein anders is dan de sein die &#8220;rechtdoor&#8221; is. Een sein checkt dus het sein voor hem, maar update ook het sein achter hem. SwitchNodes sturen ook updates naar signals, zodat deze altijd correct gedisplayed worden.<\/p>\n\n\n<div class=\"dm-code-snippet light no-background  dm-normal-version\" style=\"background-color:#abb8c3;\" snippet-height=\"600px\">\n\t\t\t<div class=\"control-language\">\n                <div class=\"dm-buttons\">\n                    <div class=\"dm-buttons-left\">\n                        <div class=\"dm-button-snippet red-button\"><\/div>\n                        <div class=\"dm-button-snippet orange-button\"><\/div>\n                        <div class=\"dm-button-snippet green-button\"><\/div>\n                    <\/div>\n                    <div class=\"dm-buttons-right\">\n                        <a id=\"dm-copy-raw-code\">\n                        <span class=\"dm-copy-text\">Get the Code!<\/span>\n                        <span class=\"dm-copy-confirmed\" style=\"display:none\">You have it!<\/span>\n                        <span class=\"dm-error-message\" style=\"display:none\">Use a different Browser<\/span><\/a>\n                    <\/div>\n                <\/div>\n                <pre class=\"line-numbers\"><code id=\"dm-code-raw\" class=\"wrap language-typescript\">\n<pre>\n    private void UpdateSignalsInFront(RailBlock block)\n    {\n        int signalIndex = block.railNodes.IndexOf(this);\n        for (int i = signalIndex + 1; i < block.railNodes.Count; i++)\n        {\n            if (block.railNodes[i].GetComponent<SwitchNode>()) return;\n            \n            if(block.railNodes[i].TryGetComponent<ExitNode>(out ExitNode exitNode))\n            {\n                UpdateSignalsInFront(exitNode.transform.parent.GetComponent<RailBlock>());\n                return;\n            }\n\n            if (block.railNodes[i].TryGetComponent<SignalNode>(out SignalNode signal))\n            {\n                if (signal.nodeDirection == nodeDirection)\n                {\n                    signal.SwitchUpdate();\n                    return;\n                }\n            }\n        }\n    }\n<\/pre>\n<\/code><\/pre>\n\t\t\t<\/div>\n        <\/div>\n\n\n\n<p class=\"has-text-align-center wp-block-paragraph\">Gaat door de RailNodes heen en update het eerst volgende sein. Bij exit node switcht hij naar het RailBlock van de exit node.<\/p>\n\n\n\n<figure class=\"wp-block-gallery has-nested-images columns-default is-cropped wp-block-gallery-2 is-layout-flex wp-block-gallery-is-layout-flex\">\n<figure class=\"wp-block-image size-large\"><img loading=\"lazy\" decoding=\"async\" width=\"600\" height=\"338\" data-id=\"1008\" src=\"https:\/\/wesleydegraaf.com\/wp-content\/uploads\/2024\/10\/SignallerSwitch-ezgif.com-video-to-gif-converter.gif\" alt=\"\" class=\"wp-image-1008\"\/><\/figure>\n\n\n\n<figure class=\"wp-block-image size-large\"><img loading=\"lazy\" decoding=\"async\" width=\"600\" height=\"338\" data-id=\"1007\" src=\"https:\/\/wesleydegraaf.com\/wp-content\/uploads\/2024\/10\/SignallerSignal-ezgif.com-video-to-gif-converter.gif\" alt=\"\" class=\"wp-image-1007\"\/><\/figure>\n<\/figure>\n\n\n<p><iframe loading=\"lazy\" frameborder=\"0\" src=\"https:\/\/itch.io\/embed\/1985550?link_color=189c00\" width=\"552\" height=\"167\"><a href=\"https:\/\/double-gezicht.itch.io\/signaller\">Signaller by Double_Gezicht, Blybe, Dafiedoe<\/a><\/iframe><\/p>\n\n\n\n<p class=\"wp-block-paragraph\"><\/p>\n","protected":false},"excerpt":{"rendered":"<p>Tijdens keuzedeel moesten we een game maken voor een museum. Wij kozen voor het Spoorwegmuseum. Signaller is een game waarbij de speler de rol van een trein verkeersleider speelt. De speler moet treinen van punt A naar punt B brengen door seinen op groen te zetten en de baan vrij te maken voor de trein. [&hellip;]<\/p>\n","protected":false},"author":2,"featured_media":0,"parent":0,"menu_order":0,"comment_status":"closed","ping_status":"closed","template":"","meta":{"footnotes":""},"class_list":["post-846","page","type-page","status-publish","hentry"],"blocksy_meta":{"styles_descriptor":{"styles":{"desktop":"","tablet":"","mobile":""},"google_fonts":[],"version":6}},"_links":{"self":[{"href":"https:\/\/wesleydegraaf.com\/en\/wp-json\/wp\/v2\/pages\/846","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/wesleydegraaf.com\/en\/wp-json\/wp\/v2\/pages"}],"about":[{"href":"https:\/\/wesleydegraaf.com\/en\/wp-json\/wp\/v2\/types\/page"}],"author":[{"embeddable":true,"href":"https:\/\/wesleydegraaf.com\/en\/wp-json\/wp\/v2\/users\/2"}],"replies":[{"embeddable":true,"href":"https:\/\/wesleydegraaf.com\/en\/wp-json\/wp\/v2\/comments?post=846"}],"version-history":[{"count":38,"href":"https:\/\/wesleydegraaf.com\/en\/wp-json\/wp\/v2\/pages\/846\/revisions"}],"predecessor-version":[{"id":1356,"href":"https:\/\/wesleydegraaf.com\/en\/wp-json\/wp\/v2\/pages\/846\/revisions\/1356"}],"wp:attachment":[{"href":"https:\/\/wesleydegraaf.com\/en\/wp-json\/wp\/v2\/media?parent=846"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}