{"id":576,"date":"2010-12-18T06:48:57","date_gmt":"2010-12-18T06:48:57","guid":{"rendered":"https:\/\/astrofra.com\/wordpress\/?p=576"},"modified":"2010-12-18T06:48:57","modified_gmt":"2010-12-18T06:48:57","slug":"mgt-project-devlog-4","status":"publish","type":"post","link":"https:\/\/astrofra.com\/wordpress\/index.php\/2010\/12\/18\/mgt-project-devlog-4\/","title":{"rendered":"MGT Project DevLog #4"},"content":{"rendered":"<h3>Game Items<\/h3>\n<p>There&#8217;s no <strong>adventure game<\/strong> without <strong>powerups, keys<\/strong> and <strong>doors<\/strong>. For this prupose, I needed a generic class that handles the basic operations on items :<br \/>\n&#8211; the item <strong>knows when it interacts<\/strong> with the player and calls the proper method\/function.<br \/>\n&#8211; the item can be <strong>picked, destroyed, unlocked<\/strong>, and this <strong>state<\/strong> should remain if the player left the room.<br \/>\n&#8211; the item can increase the vitals\/energy\/shield of the player, or <strong>appear in the game inventory<\/strong><\/p>\n<div class=\"screenshot\"><img decoding=\"async\" src=\"http:\/\/gamestart3d.com\/sites\/default\/files\/mgt_devlog_4_shot1.jpg\" alt=\"\" \/><\/div>\n<p>To perform these actions, and any other kind of possible future needs, I wrote a very simple class called &#8216;<em>GameItem<\/em>&#8216;<\/p>\n<p><code><br \/>\n\/\/--------------<br \/>\nclass GameItem<br \/>\n\/\/--------------<br \/>\n{<\/code><\/p>\n<p>item_trigger = 0<br \/>\ninside_trigger = false<\/p>\n<p>enabled = true<\/p>\n<p>project_script = 0<\/p>\n<p>tank = 0<br \/>\ntank_script = 0<\/p>\n<p>function OnUpdate(item)<br \/>\n{<br \/>\nif (!enabled)<br \/>\nreturn<\/p>\n<p>if (tank == 0)<br \/>\n{<br \/>\ntank = SceneFindItem(ItemGetScene(item), &#8220;tank&#8221;)<br \/>\ntank_script = ItemGetScriptInstanceFromClass(tank, &#8220;SteamTank&#8221;)<br \/>\n}<br \/>\nelse<br \/>\n{<br \/>\n\/\/ Test the player against the trigger<br \/>\nif (item_trigger != 0)<br \/>\n{<br \/>\nif (TriggerTestItem(item_trigger, tank))<br \/>\n{<br \/>\nif (!inside_trigger)<br \/>\n{<br \/>\nprint(&#8220;GameItem::OnUpdate() tank inside&#8221;)<br \/>\nItemTaken(item)<br \/>\ninside_trigger = true<br \/>\n}<br \/>\n}<br \/>\nelse<br \/>\ninside_trigger = false<br \/>\n}<br \/>\n}<br \/>\n}<\/p>\n<p>function ItemTaken(item)<br \/>\n{<br \/>\nprint(&#8220;GameItem::ItemTaken() &#8211; Stub method called.&#8221;)<br \/>\n}<\/p>\n<p>function OnSetup(item)<br \/>\n{<br \/>\nprint(&#8220;GameItem::OnSetup(&#8221; + ItemGetName(item) + &#8220;)&#8221;)<\/p>\n<p>local _item_trigger<br \/>\n_item_trigger = ItemGetChild(item, &#8220;item_trigger&#8221;)<br \/>\nif (ObjectIsValid(_item_trigger))<br \/>\nitem_trigger = ItemCastToTrigger(_item_trigger)<\/p>\n<p>project_script = ProjectGetScriptInstance(g_project)<br \/>\nenabled = project_script.GetItemStateEnabled(item)<\/p>\n<p>if (enabled)<br \/>\nEnable(item)<br \/>\nelse<br \/>\nDisable(item)<br \/>\n}<\/p>\n<p>function Enable(item)<br \/>\n{<br \/>\nprint(&#8220;GameItem::Enable(&#8221; + ItemGetName(item) + &#8220;)&#8221;)<\/p>\n<p>ItemActivateHierarchy(item, true)<br \/>\nenabled = true<br \/>\nproject_script.SetItemStateEnabled(item, true)<br \/>\n}<\/p>\n<p>function Disable(item)<br \/>\n{<br \/>\nprint(&#8220;GameItem::Disable(&#8221; + ItemGetName(item) + &#8220;)&#8221;)<\/p>\n<p>ItemActivateHierarchy(item, false)<br \/>\nenabled = false<br \/>\nproject_script.SetItemStateEnabled(item, false)<br \/>\n}<br \/>\n}<\/p>\n<p>Basically, <strong>when setup<\/strong>, the class will <strong>look for a trigger<\/strong> parented to the main item. Then, during the update loop, the class will <strong>test the player against the trigger<\/strong>. If the item is triggered by the player, a stub method <em>ItemTaken()<\/em> is called.<\/p>\n<div class=\"screenshot\"><img decoding=\"async\" src=\"http:\/\/gamestart3d.com\/sites\/default\/files\/mgt_devlog_4_shot2.jpg\" alt=\"\" \/><\/div>\n<p>Based on this generic class, I can derive (or <strong>extend<\/strong>) any kind of specific class, and <strong>overload<\/strong> the <em>ItemTaken()<\/em> method.<\/p>\n<p>The class also provide two methods to <strong>enable<\/strong> and <strong>disable<\/strong> the item and its children. This is very handy when it comes to hide several items and lights. When disabled, the state of the item will be <strong>stored by the project<\/strong>, so that the item will know if it is enabled or not in case the player exits then enters the room again. Here, all the state logic is handled by two accessors methods I wrote directly in the project script : <em>SetState()<\/em> and <em>GetState()<\/em><\/p>\n<p>Here&#8217;s an example of a typical &#8216;power up&#8217; class inherited from the base <em>GameItem<\/em> class. You will note how the <em>ItemTaken()<\/em> class is overloaded in order to perform the proper action : here it increases the shield level of the player.<\/p>\n<p><code><br \/>\nclass ShieldCellItem extends GameItem<br \/>\n{<\/code><\/p>\n<p>function OnUpdate(item)<br \/>\n{<br \/>\nbase.OnUpdate(item)<br \/>\n}<\/p>\n<p>function ItemTaken(item)<br \/>\n{<br \/>\nprint(&#8220;ShieldCellItem::ItemTaken()&#8221;)<br \/>\ntank_script.ShieldUp()<br \/>\nDisable(item)<br \/>\n}<\/p>\n<p>function OnSetup(item)<br \/>\n{<br \/>\nbase.OnSetup(item)<br \/>\n}<\/p>\n<p>}<\/p>\n<p>&nbsp;<\/p>\n<h3>The Inventory<\/h3>\n<p>Some items can be picked and <strong>must be kept<\/strong> by the player. In this purpose, they will invoke another class called <em>Inventory<\/em>. At the moment the implementation of this class is really basic. It is more or less a few accessors to handle an array that contains the game items picked by the player.<\/p>\n<p><code><br \/>\nclass Inventory<br \/>\n{<br \/>\ninventory = 0<\/code><\/p>\n<p>constructor()<br \/>\n{<br \/>\ninventory = []<br \/>\n}<\/p>\n<p>function AddItem(item_name)<br \/>\n{<br \/>\ninventory.append(item_name)<br \/>\n}<\/p>\n<p>function RemoveItem(item_name)<br \/>\n{<br \/>\nprint(&#8220;Inventory::RemoveItem(&#8221; + item_name + &#8220;)&#8221;)<\/p>\n<p>local idx, val<br \/>\nforeach(idx,val in inventory)<br \/>\nif (val == item_name)<br \/>\n{<br \/>\ninventory.remove(idx)<br \/>\nreturn true<br \/>\n}<\/p>\n<p>return false<br \/>\n}<\/p>\n<p>function FindItem(item_name)<br \/>\n{<br \/>\nlocal i<br \/>\nforeach(i in inventory)<br \/>\nif (i == item_name)<br \/>\nreturn true<\/p>\n<p>return false<br \/>\n}<br \/>\n}<\/p>\n<p>&nbsp;<\/p>\n<h3>Video Capture<\/h3>\n<p>The following video shows the player that grabs several items (a powerup and a key), opens a first door, unlock a second door with the key he just grabbed. The key is marked as a X in the inventory, you can see it appear, the disappear when used.<\/p>\n<p><iframe loading=\"lazy\" title=\"YouTube video player\" src=\"http:\/\/www.youtube.com\/embed\/SD4X6IKj59A?rel=0\" frameborder=\"0\" width=\"853\" height=\"510\"><\/iframe><\/p>\n","protected":false},"excerpt":{"rendered":"<p>Game Items There&#8217;s no adventure game without powerups, keys and doors. For this prupose, I needed a generic class that handles the basic operations on items : &#8211; the item knows when it interacts with the player and calls the proper method\/function. &#8211; the item can be picked, destroyed, unlocked, and this state should remain &hellip; <a href=\"https:\/\/astrofra.com\/wordpress\/index.php\/2010\/12\/18\/mgt-project-devlog-4\/\" class=\"more-link\">Continue reading <span class=\"screen-reader-text\">MGT Project DevLog #4<\/span> <span class=\"meta-nav\">&rarr;<\/span><\/a><\/p>\n","protected":false},"author":1,"featured_media":0,"comment_status":"open","ping_status":"open","sticky":false,"template":"","format":"standard","meta":{"footnotes":""},"categories":[2,5],"tags":[],"class_list":["post-576","post","type-post","status-publish","format-standard","hentry","category-3d-techniques","category-prog"],"_links":{"self":[{"href":"https:\/\/astrofra.com\/wordpress\/index.php\/wp-json\/wp\/v2\/posts\/576"}],"collection":[{"href":"https:\/\/astrofra.com\/wordpress\/index.php\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/astrofra.com\/wordpress\/index.php\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/astrofra.com\/wordpress\/index.php\/wp-json\/wp\/v2\/users\/1"}],"replies":[{"embeddable":true,"href":"https:\/\/astrofra.com\/wordpress\/index.php\/wp-json\/wp\/v2\/comments?post=576"}],"version-history":[{"count":0,"href":"https:\/\/astrofra.com\/wordpress\/index.php\/wp-json\/wp\/v2\/posts\/576\/revisions"}],"wp:attachment":[{"href":"https:\/\/astrofra.com\/wordpress\/index.php\/wp-json\/wp\/v2\/media?parent=576"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/astrofra.com\/wordpress\/index.php\/wp-json\/wp\/v2\/categories?post=576"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/astrofra.com\/wordpress\/index.php\/wp-json\/wp\/v2\/tags?post=576"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}