منوی بازی Retro با Godot4

Summarize this content to 400 words in Persian Lang
گودو یکی از معروف ترین موتورهای بازی مانند Unreal Engine و Unit است. گودو مانند رقبای خود اجازه ساخت بازی های دو بعدی و سه بعدی را با ویرایشگر بصری می دهد. وجه تمایز اصلی آن منبع باز بودن آن است. علاوه بر این، این به برنامه نویس اجازه می دهد تا به زبانی به نام Godot Script بنویسد که بسیار شبیه پایتون است.
این مقاله کوتاه به سرعت نشان می دهد که چگونه می توان قسمت منوی یک بازی را با استفاده از این موتور در جدیدترین نسخه اصلی آن، نسخه 4 ایجاد کرد. منوی مورد نظر صفحه ای است که بازیکن با شخصیت خود وارد فروشگاه می شود تا آیتم هایی با طلا خریداری کند. در بازی جمع آوری شده است همه کسانی که تا به حال یک JRPG بازی کرده اند با این نوع صفحه نمایش آشنا هستند.
به دست آوردن دارایی
دارایی های مورد استفاده در صحنه بسیار ابتدایی هستند که توسط هوش مصنوعی ایجاد شده اند.
ایجاد درخت صحنه
پس از ایجاد یک پروژه جدید با استفاده از ویرایشگر موتور، اولین شی را در درخت صحنه ایجاد کردم که یک Node2D است که آن را InGameShop نامیدم. این موضوع اصلی صحنه است. گودو به شما امکان می دهد آن را به عنوان یک منبع قابل استفاده مجدد صادر کنید. این ابزار همچنین به شما این امکان را می دهد که به سادگی این گره را کپی کرده و آن را در یک صحنه پیچیده تر قرار دهید.
به عنوان فرزند گره ریشه، یک شی از نوع “Sprite” اضافه می کنیم که پس زمینه منو خواهد بود.
شی “Background” را انتخاب می کنیم و بافت آن را به تصویر پس زمینه از مجموعه دارایی تغییر می دهیم.
از آنجایی که تصویر مقیاس متفاوتی نسبت به صفحه دارد (میتوانیم طرح کلی صفحه کاربر نهایی را به رنگ آبی در ویرایشگر ببینیم)، بیایید اندازه را افزایش دهیم.از تصویر پس زمینه به طوری که فضای بیشتری نسبت به صفحه اشغال می کند. (این را می توان در ویژگی Transform >> Scale انجام داد).
هنوز در ویژگیهای تصویر، میتوانیم رنگهای تصویر را تعدیل کنیم تا کمتر جلب توجه کند، زیرا پسزمینه نمیتواند مانع مشاهده آیتمهای منو روی صفحه شود. اگر ترجیح می دهید، می توانید این کار را مستقیماً روی تصویر با ویرایشگری مانند Photoshop یا Gimp انجام دهید.
حال، بیایید دو شی دیگر در زیر “InGameShop” ایجاد کنیم. آنها از نوع “Node2D” هستند و ما آنها را “MenuLeft” و “MenuRight” می نامیم.
در داخل “MenuLeft” و “MenuRight”، برای هر یک از آنها، یک شی فرزند از نوع “Sprite” به نام “Background” ایجاد می کنیم.
برای هر یک از اسپرایت های ایجاد شده قبلی، تصویری که یک پنل آبی است را به عنوان بافت انتخاب می کنیم. پس از آن، اندازه آن، اندازه هر پنل را با تغییر اندازه اسپرایت تعریف می کنیم. این را می توان با استفاده از ویژگی transform انجام داد. سپس، با استفاده از ویژگی position یا با استفاده از ابزارهای بالای ویرایشگر، آنها را روی صفحه قرار می دهیم.
اگر پروژه را اجرا کنیم، با استفاده از نماد “play” در بالای صفحه، می توانیم نمای کاربر نهایی را ببینیم.
برای ایجاد پنل در وسط با مقدار سکه، این کار را به همان روشی که پانل های دیگر انجام دادیم انجام می دهیم. ما یک “Node2D” در زیر شی root ایجاد می کنیم، آن را نام گذاری می کنیم و یک شی “Sprite” را در داخل آن قرار می دهیم. من اسمش را گذاشتم “CoinPanel”
من یک شی از نوع “Label” را در داخل “CoinPanel” اضافه کردم، همانطور که از نام آن پیداست، این شی متن را درج می کند. در ویژگی “text” به عنوان متن اولیه، مقدار “0000” درج شد. برای کنترل اندازه و موقعیت آن، موقعیت و مقیاس را مانند اشیاء “Sprite” تغییر دهید.
یک اسپرایت دیگر در “CoinPanel” اضافه شده است، این اسپرایت به نماد سکه در سمت چپ، در شمارنده سکه کوچک اشاره دارد. اندازه و موقعیت با استفاده از همان خواص ذکر شده در بالا تنظیم شد.
دو شی “Labels” دیگر باید ایجاد شود، یکی در “MenuLeft” و دیگری در “MenuRight”. آنها یک مورد را در یک پانل نشان خواهند داد. اندازه این موارد تنظیم شده و در اولین خط موارد در هر پانل درج می شود. این برچسب ها قبل از شروع صحنه، دید خود را از دست خواهند داد. اسکریپت این موارد را شبیه سازی می کند تا لیست واقعی آیتم ها را در صحنه نمایش دهد.
حباب پیام فروشنده با درج یک “Node2D” دیگر در داخل شی ریشه ایجاد می شود. من این گره را “SalesmanDialog” نامیدم. این گره دارای یک Sprite و یک Label در داخل آن است. Sprite تصویر پس زمینه ای است که من برای تصویر حباب گفتار استفاده کردم. Label بر روی بالون متمرکز شده و رنگ آن با استفاده از ویژگی Material >> New Canvas item >> ویرایش مورد بوم و تغییر حالت Blend به “Subtract” به رنگ تیره تغییر می کند.
وقتی دوباره پروژه را اجرا می کنیم، می توانیم ببینیم که بالون چگونه روی صفحه قرار گرفته است.
در دارایی های انتخاب شده، یک png از یک پانل سفید با کدورت تصویر در نصف وجود دارد. این بدان معنی است که این پانل با سایر عناصر پشت خود همپوشانی نخواهد داشت. در عوض، مانند نور (برای رنگهای روشن) یا سایه (برای رنگهای تیره) رفتار میکند. یک شی Sprite با بافت این پانل در “MenuRight” درج شد که روی مورد اول همپوشانی دارد.
پس از تنظیم موقعیت، حباب گفتار فروشنده باید ویژگی “مرئی” آن به false تغییر کند. این کار را می توان با استفاده از نماد “چشم” در منوی سمت چپ یا با ویرایش ویژگی های خود شی انجام داد.
برچسبهایی که برای هر مورد در سمت چپ یا راست تکرار میشوند، دیدشان تغییر میکند تا نامرئی باشند. نماد “چشم” در پانل سمت چپ و همچنین ویژگی قابل مشاهده در پانل سمت راست قابل استفاده است.
یک گودو اسکریپت با کلیک راست روی آن به گره اصلی اضافه می شود. فیلمنامه ای که رفتار صحنه را برنامه ریزی می کند در زیر آمده است. کامنت گذاری شده و با نام های متغیر به خوبی توصیف شده است. اگر میخواهید از این اسکریپت یا چیزی مشابه در پروژهای استفاده کنید، توصیه میکنم فهرستها و پیامها را در اسکریپتهای جداگانه استخراج کنید.
extends Node2D
# Max amount of itens on panel, without scrolling
const max_amount_vertically = 8
# Store itens available enum
enum Adquirance {
MUSHROOM,
MUSHROOM_5x,
RING,
RING_10x,
GREEN_MUSHROOM,
GREEN_MUSHROOM_5x,
GREEN_MUSHROOM_10x,
GREEN_MUSHROOM_20x,
LEAF,
LEAF_5x,
LEAF_10x,
}
var adquirances = []
var menu_left_items = []
var menu_right_items = []
var menu_left_scroll_top = 0
var menu_right_scroll_top = 0
var selectedItemIndex = 0
var focusInitialPosition = 0
var game_state = null
var coin_available = 800
var coin_transfering = 0
var salesman_talking = 0
# Store itens available on this store
var salesman_store = [
Adquirance.MUSHROOM,
Adquirance.MUSHROOM_5x,
Adquirance.RING,
Adquirance.RING_10x,
Adquirance.GREEN_MUSHROOM,
Adquirance.GREEN_MUSHROOM_5x,
Adquirance.GREEN_MUSHROOM_10x,
Adquirance.GREEN_MUSHROOM_20x,
Adquirance.LEAF,
Adquirance.LEAF_5x,
Adquirance.LEAF_10x,
]
# Internationalization messages
var i18n_messages = {
‘MUSHROOM’: ‘Mushroom’,
‘MUSHROOM_5x’: ‘Mushroom 5x’,
‘RING’: ‘Ring’,
‘RING_10x’: ‘Ring 10x’,
‘GREEN_MUSHROOM’: ‘Green Mushroom’,
‘GREEN_MUSHROOM_5x’: ‘Green Mushroom 5x’,
‘GREEN_MUSHROOM_10x’: ‘Green Mushroom 10x’,
‘GREEN_MUSHROOM_20x’: ‘Green Mushroom 20x’,
‘LEAF’: ‘Leaf’,
‘LEAF_5x’: ‘Leaf 5x’,
‘LEAF_10x’: ‘Leaf 10x’,
‘THX’: ‘Thanks!’,
‘NOT_ENOUGHT_COINS’: ‘Not enough coins.’
}
# price mapping
var price_table = [
{
‘item’: Adquirance.MUSHROOM,
‘price’: 30
},
{
‘item’: Adquirance.MUSHROOM_5x,
‘price’: 70
},
{
‘item’: Adquirance.RING,
‘price’: 90
},
{
‘item’: Adquirance.RING_10x,
‘price’: 140
},
{
‘item’: Adquirance.GREEN_MUSHROOM,
‘price’: 60
},
{
‘item’: Adquirance.GREEN_MUSHROOM_5x,
‘price’: 90
},
{
‘item’: Adquirance.GREEN_MUSHROOM_10x,
‘price’: 120
},
{
‘item’: Adquirance.GREEN_MUSHROOM_20x,
‘price’: 120
},
{
‘item’: Adquirance.LEAF,
‘price’: 50
},
{
‘item’: Adquirance.LEAF_5x,
‘price’: 200
},
]
# Called when the node enters the scene tree for the first time.
func _ready():
rearrange_store()
focusInitialPosition = $MenuRight/Selection.position.y
pass
# Called every frame. ‘delta’ is the elapsed time since the previous frame.
func _physics_process(delta):
if coin_transfering > 0:
coin_available -= 1
coin_transfering -= 1
$CoinPanel/Label.text = str(coin_available)
else:
if Input.is_action_just_released(“ui_down”):
selectedItemIndex += 1
# $PopAudio.play()
if Input.is_action_just_released(“ui_up”):
selectedItemIndex -= 1
# $PopAudio.play()
if Input.is_action_just_released(“ui_accept”):
buy_item(salesman_store[selectedItemIndex + menu_right_scroll_top])
# $PopAudio.play()
if selectedItemIndex < 0:
selectedItemIndex = 0
if menu_right_scroll_top > 0:
menu_left_scroll_top -= 1
do_menu_right_scroll_up()
if selectedItemIndex > salesman_store.size():
selectedItemIndex = salesman_store.size()
if (selectedItemIndex + menu_right_scroll_top) > (salesman_store.size()-1):
selectedItemIndex -= 1
if selectedItemIndex > (max_amount_vertically-1):
do_menu_right_scroll_down()
selectedItemIndex = (max_amount_vertically-1)
$MenuRight/Selection.position.y = focusInitialPosition + (selectedItemIndex * 35)
if salesman_talking > 0:
salesman_talking -= 1
if salesman_talking == 0:
$SalesmanDialog.visible = false
pass
func do_menu_right_scroll_down():
menu_right_scroll_top += 1
rearrange_store()
func do_menu_right_scroll_up():
menu_right_scroll_top -= 1
rearrange_store()
func get_item_name(item):
match item:
‘mushroom’:
return i18n_messages[‘MUSHROOM’]
‘ring’:
return i18n_messages[‘RING’]
‘green_mushroom’:
return i18n_messages[‘GREEN_MUSHROOM’]
‘leaf’:
return i18n_messages[‘LEAF’]
Adquirance.MUSHROOM:
return i18n_messages[‘MUSHROOM’]
Adquirance.MUSHROOM_5x:
return i18n_messages[‘MUSHROOM_5x’]
Adquirance.RING:
return i18n_messages[‘RING’]
Adquirance.RING_10x:
return i18n_messages[‘RING_10x’]
Adquirance.GREEN_MUSHROOM:
return i18n_messages[‘GREEN_MUSHROOM’]
Adquirance.GREEN_MUSHROOM_5x:
return i18n_messages[‘GREEN_MUSHROOM_5x’]
Adquirance.GREEN_MUSHROOM_10x:
return i18n_messages[‘GREEN_MUSHROOM_10x’]
Adquirance.GREEN_MUSHROOM_20x:
return i18n_messages[‘GREEN_MUSHROOM_20x’]
Adquirance.LEAF:
return i18n_messages[‘LEAF’]
Adquirance.LEAF_5x:
return i18n_messages[‘LEAF_5x’]
Adquirance.LEAF_10x:
return i18n_messages[‘LEAF_10x’]
return “”
func get_product_price(item):
for price_table_item in price_table:
if price_table_item[‘item’] == item:
return price_table_item[‘price’]
return 0
func rearrange_store():
$CoinPanel/Label.text = str(coin_available)
var amount = 0
for item in menu_right_items:
$MenuRight.remove_child(item[‘node’])
for item in menu_left_items:
$MenuLeft.remove_child(item[‘node’])
menu_right_items = []
var scrolling = menu_right_scroll_top
for item in salesman_store:
if scrolling > 0:
scrolling -= 1
continue
var item_node = $MenuRight/Item.duplicate()
var in_list_item = {
‘kind’: item,
‘node’: item_node
}
menu_right_items.push_back(in_list_item)
if amount < max_amount_vertically:
$MenuRight.add_child(item_node)
item_node.position.y += 35 * amount
item_node.set_visible(true)
item_node.text = get_item_name(item) + ” $” + str(get_product_price(item))
amount += 1
if amount == max_amount_vertically:
var more_indicator = $MenuRight/Item.duplicate()
more_indicator.text = “…”
more_indicator.set_visible(true)
more_indicator.position.y += 35 * amount
$MenuRight.add_child(more_indicator)
amount = 0
for adquirance in adquirances:
var item_node = $MenuLeft/Item.duplicate()
item_node.visible = true
item_node.position.y += 35 * amount
item_node.text = get_item_name(adquirance.type) + ” x” + str(adquirance.amount)
var in_list_item = {
‘kind’: adquirance.type,
‘amount’: adquirance.amount,
‘node’: item_node
}
menu_left_items.push_back(in_list_item)
$MenuLeft.add_child(item_node)
amount += 1
func buy_item(item):
var price = get_product_price(item)
if coin_available < price:
salesman_talks(i18n_messages[‘NOT_ENOUGHT_COINS’])
return; # TODO more coins needed
coin_transfering = price
salesman_talks(i18n_messages[‘THX’])
match item:
Adquirance.MUSHROOM:
add_item_to_bag(‘mushroom’, 1)
return;
Adquirance.MUSHROOM_5x:
add_item_to_bag(‘mushroom’, 5)
return;
Adquirance.RING:
add_item_to_bag(‘ring’, 1)
return;
Adquirance.RING_10x:
add_item_to_bag(‘ring’, 10)
return;
Adquirance.GREEN_MUSHROOM:
add_item_to_bag(‘green_mushroom’, 1)
return;
Adquirance.GREEN_MUSHROOM_5x:
add_item_to_bag(‘green_mushroom’, 5)
return;
Adquirance.GREEN_MUSHROOM_10x:
add_item_to_bag(‘green_mushroom’, 10)
return;
Adquirance.GREEN_MUSHROOM_20x:
add_item_to_bag(‘green_mushroom’, 20)
return;
Adquirance.LEAF:
add_item_to_bag(‘leaf’, 1)
return;
Adquirance.LEAF_5x:
add_item_to_bag(‘leaf’, 5)
return;
Adquirance.LEAF_10x:
add_item_to_bag(‘leaf’, 10)
return;
func add_item_to_bag(type, amount):
for adquired in adquirances:
if adquired.type == type:
adquired.amount += amount
rearrange_store()
return;
adquirances.push_back({ ‘type’: type, ‘amount’: amount })
rearrange_store()
func salesman_talks(message):
$SalesmanDialog/Label.text = message
$SalesmanDialog.visible = true
salesman_talking = 200
وارد حالت تمام صفحه شوید
از حالت تمام صفحه خارج شوید
یک مخزن با این پروژه را می توان در آدرس زیر پیدا کرد: https://github.com/misabitencourt/in-game-shop
گودو یکی از معروف ترین موتورهای بازی مانند Unreal Engine و Unit است. گودو مانند رقبای خود اجازه ساخت بازی های دو بعدی و سه بعدی را با ویرایشگر بصری می دهد. وجه تمایز اصلی آن منبع باز بودن آن است. علاوه بر این، این به برنامه نویس اجازه می دهد تا به زبانی به نام Godot Script بنویسد که بسیار شبیه پایتون است.
این مقاله کوتاه به سرعت نشان می دهد که چگونه می توان قسمت منوی یک بازی را با استفاده از این موتور در جدیدترین نسخه اصلی آن، نسخه 4 ایجاد کرد. منوی مورد نظر صفحه ای است که بازیکن با شخصیت خود وارد فروشگاه می شود تا آیتم هایی با طلا خریداری کند. در بازی جمع آوری شده است همه کسانی که تا به حال یک JRPG بازی کرده اند با این نوع صفحه نمایش آشنا هستند.
به دست آوردن دارایی
دارایی های مورد استفاده در صحنه بسیار ابتدایی هستند که توسط هوش مصنوعی ایجاد شده اند.
ایجاد درخت صحنه
پس از ایجاد یک پروژه جدید با استفاده از ویرایشگر موتور، اولین شی را در درخت صحنه ایجاد کردم که یک Node2D است که آن را InGameShop نامیدم. این موضوع اصلی صحنه است. گودو به شما امکان می دهد آن را به عنوان یک منبع قابل استفاده مجدد صادر کنید. این ابزار همچنین به شما این امکان را می دهد که به سادگی این گره را کپی کرده و آن را در یک صحنه پیچیده تر قرار دهید.
به عنوان فرزند گره ریشه، یک شی از نوع “Sprite” اضافه می کنیم که پس زمینه منو خواهد بود.
شی “Background” را انتخاب می کنیم و بافت آن را به تصویر پس زمینه از مجموعه دارایی تغییر می دهیم.
از آنجایی که تصویر مقیاس متفاوتی نسبت به صفحه دارد (میتوانیم طرح کلی صفحه کاربر نهایی را به رنگ آبی در ویرایشگر ببینیم)، بیایید اندازه را افزایش دهیم.
از تصویر پس زمینه به طوری که فضای بیشتری نسبت به صفحه اشغال می کند. (این را می توان در ویژگی Transform >> Scale انجام داد).
هنوز در ویژگیهای تصویر، میتوانیم رنگهای تصویر را تعدیل کنیم تا کمتر جلب توجه کند، زیرا پسزمینه نمیتواند مانع مشاهده آیتمهای منو روی صفحه شود. اگر ترجیح می دهید، می توانید این کار را مستقیماً روی تصویر با ویرایشگری مانند Photoshop یا Gimp انجام دهید.
حال، بیایید دو شی دیگر در زیر “InGameShop” ایجاد کنیم. آنها از نوع “Node2D” هستند و ما آنها را “MenuLeft” و “MenuRight” می نامیم.
در داخل “MenuLeft” و “MenuRight”، برای هر یک از آنها، یک شی فرزند از نوع “Sprite” به نام “Background” ایجاد می کنیم.
برای هر یک از اسپرایت های ایجاد شده قبلی، تصویری که یک پنل آبی است را به عنوان بافت انتخاب می کنیم. پس از آن، اندازه آن، اندازه هر پنل را با تغییر اندازه اسپرایت تعریف می کنیم. این را می توان با استفاده از ویژگی transform انجام داد. سپس، با استفاده از ویژگی position یا با استفاده از ابزارهای بالای ویرایشگر، آنها را روی صفحه قرار می دهیم.
اگر پروژه را اجرا کنیم، با استفاده از نماد “play” در بالای صفحه، می توانیم نمای کاربر نهایی را ببینیم.
برای ایجاد پنل در وسط با مقدار سکه، این کار را به همان روشی که پانل های دیگر انجام دادیم انجام می دهیم. ما یک “Node2D” در زیر شی root ایجاد می کنیم، آن را نام گذاری می کنیم و یک شی “Sprite” را در داخل آن قرار می دهیم. من اسمش را گذاشتم “CoinPanel”
من یک شی از نوع “Label” را در داخل “CoinPanel” اضافه کردم، همانطور که از نام آن پیداست، این شی متن را درج می کند. در ویژگی “text” به عنوان متن اولیه، مقدار “0000” درج شد. برای کنترل اندازه و موقعیت آن، موقعیت و مقیاس را مانند اشیاء “Sprite” تغییر دهید.
یک اسپرایت دیگر در “CoinPanel” اضافه شده است، این اسپرایت به نماد سکه در سمت چپ، در شمارنده سکه کوچک اشاره دارد. اندازه و موقعیت با استفاده از همان خواص ذکر شده در بالا تنظیم شد.
دو شی “Labels” دیگر باید ایجاد شود، یکی در “MenuLeft” و دیگری در “MenuRight”. آنها یک مورد را در یک پانل نشان خواهند داد. اندازه این موارد تنظیم شده و در اولین خط موارد در هر پانل درج می شود. این برچسب ها قبل از شروع صحنه، دید خود را از دست خواهند داد. اسکریپت این موارد را شبیه سازی می کند تا لیست واقعی آیتم ها را در صحنه نمایش دهد.
حباب پیام فروشنده با درج یک “Node2D” دیگر در داخل شی ریشه ایجاد می شود. من این گره را “SalesmanDialog” نامیدم. این گره دارای یک Sprite و یک Label در داخل آن است. Sprite تصویر پس زمینه ای است که من برای تصویر حباب گفتار استفاده کردم. Label بر روی بالون متمرکز شده و رنگ آن با استفاده از ویژگی Material >> New Canvas item >> ویرایش مورد بوم و تغییر حالت Blend به “Subtract” به رنگ تیره تغییر می کند.
وقتی دوباره پروژه را اجرا می کنیم، می توانیم ببینیم که بالون چگونه روی صفحه قرار گرفته است.
در دارایی های انتخاب شده، یک png از یک پانل سفید با کدورت تصویر در نصف وجود دارد. این بدان معنی است که این پانل با سایر عناصر پشت خود همپوشانی نخواهد داشت. در عوض، مانند نور (برای رنگهای روشن) یا سایه (برای رنگهای تیره) رفتار میکند. یک شی Sprite با بافت این پانل در “MenuRight” درج شد که روی مورد اول همپوشانی دارد.
پس از تنظیم موقعیت، حباب گفتار فروشنده باید ویژگی “مرئی” آن به false تغییر کند. این کار را می توان با استفاده از نماد “چشم” در منوی سمت چپ یا با ویرایش ویژگی های خود شی انجام داد.
برچسبهایی که برای هر مورد در سمت چپ یا راست تکرار میشوند، دیدشان تغییر میکند تا نامرئی باشند. نماد “چشم” در پانل سمت چپ و همچنین ویژگی قابل مشاهده در پانل سمت راست قابل استفاده است.
یک گودو اسکریپت با کلیک راست روی آن به گره اصلی اضافه می شود. فیلمنامه ای که رفتار صحنه را برنامه ریزی می کند در زیر آمده است. کامنت گذاری شده و با نام های متغیر به خوبی توصیف شده است. اگر میخواهید از این اسکریپت یا چیزی مشابه در پروژهای استفاده کنید، توصیه میکنم فهرستها و پیامها را در اسکریپتهای جداگانه استخراج کنید.
extends Node2D
# Max amount of itens on panel, without scrolling
const max_amount_vertically = 8
# Store itens available enum
enum Adquirance {
MUSHROOM,
MUSHROOM_5x,
RING,
RING_10x,
GREEN_MUSHROOM,
GREEN_MUSHROOM_5x,
GREEN_MUSHROOM_10x,
GREEN_MUSHROOM_20x,
LEAF,
LEAF_5x,
LEAF_10x,
}
var adquirances = []
var menu_left_items = []
var menu_right_items = []
var menu_left_scroll_top = 0
var menu_right_scroll_top = 0
var selectedItemIndex = 0
var focusInitialPosition = 0
var game_state = null
var coin_available = 800
var coin_transfering = 0
var salesman_talking = 0
# Store itens available on this store
var salesman_store = [
Adquirance.MUSHROOM,
Adquirance.MUSHROOM_5x,
Adquirance.RING,
Adquirance.RING_10x,
Adquirance.GREEN_MUSHROOM,
Adquirance.GREEN_MUSHROOM_5x,
Adquirance.GREEN_MUSHROOM_10x,
Adquirance.GREEN_MUSHROOM_20x,
Adquirance.LEAF,
Adquirance.LEAF_5x,
Adquirance.LEAF_10x,
]
# Internationalization messages
var i18n_messages = {
'MUSHROOM': 'Mushroom',
'MUSHROOM_5x': 'Mushroom 5x',
'RING': 'Ring',
'RING_10x': 'Ring 10x',
'GREEN_MUSHROOM': 'Green Mushroom',
'GREEN_MUSHROOM_5x': 'Green Mushroom 5x',
'GREEN_MUSHROOM_10x': 'Green Mushroom 10x',
'GREEN_MUSHROOM_20x': 'Green Mushroom 20x',
'LEAF': 'Leaf',
'LEAF_5x': 'Leaf 5x',
'LEAF_10x': 'Leaf 10x',
'THX': 'Thanks!',
'NOT_ENOUGHT_COINS': 'Not enough coins.'
}
# price mapping
var price_table = [
{
'item': Adquirance.MUSHROOM,
'price': 30
},
{
'item': Adquirance.MUSHROOM_5x,
'price': 70
},
{
'item': Adquirance.RING,
'price': 90
},
{
'item': Adquirance.RING_10x,
'price': 140
},
{
'item': Adquirance.GREEN_MUSHROOM,
'price': 60
},
{
'item': Adquirance.GREEN_MUSHROOM_5x,
'price': 90
},
{
'item': Adquirance.GREEN_MUSHROOM_10x,
'price': 120
},
{
'item': Adquirance.GREEN_MUSHROOM_20x,
'price': 120
},
{
'item': Adquirance.LEAF,
'price': 50
},
{
'item': Adquirance.LEAF_5x,
'price': 200
},
]
# Called when the node enters the scene tree for the first time.
func _ready():
rearrange_store()
focusInitialPosition = $MenuRight/Selection.position.y
pass
# Called every frame. 'delta' is the elapsed time since the previous frame.
func _physics_process(delta):
if coin_transfering > 0:
coin_available -= 1
coin_transfering -= 1
$CoinPanel/Label.text = str(coin_available)
else:
if Input.is_action_just_released("ui_down"):
selectedItemIndex += 1
# $PopAudio.play()
if Input.is_action_just_released("ui_up"):
selectedItemIndex -= 1
# $PopAudio.play()
if Input.is_action_just_released("ui_accept"):
buy_item(salesman_store[selectedItemIndex + menu_right_scroll_top])
# $PopAudio.play()
if selectedItemIndex < 0:
selectedItemIndex = 0
if menu_right_scroll_top > 0:
menu_left_scroll_top -= 1
do_menu_right_scroll_up()
if selectedItemIndex > salesman_store.size():
selectedItemIndex = salesman_store.size()
if (selectedItemIndex + menu_right_scroll_top) > (salesman_store.size()-1):
selectedItemIndex -= 1
if selectedItemIndex > (max_amount_vertically-1):
do_menu_right_scroll_down()
selectedItemIndex = (max_amount_vertically-1)
$MenuRight/Selection.position.y = focusInitialPosition + (selectedItemIndex * 35)
if salesman_talking > 0:
salesman_talking -= 1
if salesman_talking == 0:
$SalesmanDialog.visible = false
pass
func do_menu_right_scroll_down():
menu_right_scroll_top += 1
rearrange_store()
func do_menu_right_scroll_up():
menu_right_scroll_top -= 1
rearrange_store()
func get_item_name(item):
match item:
'mushroom':
return i18n_messages['MUSHROOM']
'ring':
return i18n_messages['RING']
'green_mushroom':
return i18n_messages['GREEN_MUSHROOM']
'leaf':
return i18n_messages['LEAF']
Adquirance.MUSHROOM:
return i18n_messages['MUSHROOM']
Adquirance.MUSHROOM_5x:
return i18n_messages['MUSHROOM_5x']
Adquirance.RING:
return i18n_messages['RING']
Adquirance.RING_10x:
return i18n_messages['RING_10x']
Adquirance.GREEN_MUSHROOM:
return i18n_messages['GREEN_MUSHROOM']
Adquirance.GREEN_MUSHROOM_5x:
return i18n_messages['GREEN_MUSHROOM_5x']
Adquirance.GREEN_MUSHROOM_10x:
return i18n_messages['GREEN_MUSHROOM_10x']
Adquirance.GREEN_MUSHROOM_20x:
return i18n_messages['GREEN_MUSHROOM_20x']
Adquirance.LEAF:
return i18n_messages['LEAF']
Adquirance.LEAF_5x:
return i18n_messages['LEAF_5x']
Adquirance.LEAF_10x:
return i18n_messages['LEAF_10x']
return ""
func get_product_price(item):
for price_table_item in price_table:
if price_table_item['item'] == item:
return price_table_item['price']
return 0
func rearrange_store():
$CoinPanel/Label.text = str(coin_available)
var amount = 0
for item in menu_right_items:
$MenuRight.remove_child(item['node'])
for item in menu_left_items:
$MenuLeft.remove_child(item['node'])
menu_right_items = []
var scrolling = menu_right_scroll_top
for item in salesman_store:
if scrolling > 0:
scrolling -= 1
continue
var item_node = $MenuRight/Item.duplicate()
var in_list_item = {
'kind': item,
'node': item_node
}
menu_right_items.push_back(in_list_item)
if amount < max_amount_vertically:
$MenuRight.add_child(item_node)
item_node.position.y += 35 * amount
item_node.set_visible(true)
item_node.text = get_item_name(item) + " $" + str(get_product_price(item))
amount += 1
if amount == max_amount_vertically:
var more_indicator = $MenuRight/Item.duplicate()
more_indicator.text = "..."
more_indicator.set_visible(true)
more_indicator.position.y += 35 * amount
$MenuRight.add_child(more_indicator)
amount = 0
for adquirance in adquirances:
var item_node = $MenuLeft/Item.duplicate()
item_node.visible = true
item_node.position.y += 35 * amount
item_node.text = get_item_name(adquirance.type) + " x" + str(adquirance.amount)
var in_list_item = {
'kind': adquirance.type,
'amount': adquirance.amount,
'node': item_node
}
menu_left_items.push_back(in_list_item)
$MenuLeft.add_child(item_node)
amount += 1
func buy_item(item):
var price = get_product_price(item)
if coin_available < price:
salesman_talks(i18n_messages['NOT_ENOUGHT_COINS'])
return; # TODO more coins needed
coin_transfering = price
salesman_talks(i18n_messages['THX'])
match item:
Adquirance.MUSHROOM:
add_item_to_bag('mushroom', 1)
return;
Adquirance.MUSHROOM_5x:
add_item_to_bag('mushroom', 5)
return;
Adquirance.RING:
add_item_to_bag('ring', 1)
return;
Adquirance.RING_10x:
add_item_to_bag('ring', 10)
return;
Adquirance.GREEN_MUSHROOM:
add_item_to_bag('green_mushroom', 1)
return;
Adquirance.GREEN_MUSHROOM_5x:
add_item_to_bag('green_mushroom', 5)
return;
Adquirance.GREEN_MUSHROOM_10x:
add_item_to_bag('green_mushroom', 10)
return;
Adquirance.GREEN_MUSHROOM_20x:
add_item_to_bag('green_mushroom', 20)
return;
Adquirance.LEAF:
add_item_to_bag('leaf', 1)
return;
Adquirance.LEAF_5x:
add_item_to_bag('leaf', 5)
return;
Adquirance.LEAF_10x:
add_item_to_bag('leaf', 10)
return;
func add_item_to_bag(type, amount):
for adquired in adquirances:
if adquired.type == type:
adquired.amount += amount
rearrange_store()
return;
adquirances.push_back({ 'type': type, 'amount': amount })
rearrange_store()
func salesman_talks(message):
$SalesmanDialog/Label.text = message
$SalesmanDialog.visible = true
salesman_talking = 200
یک مخزن با این پروژه را می توان در آدرس زیر پیدا کرد: https://github.com/misabitencourt/in-game-shop