Русский
Русский
English
Статистика
Реклама

Action

Свой ремейк ZX игры Reskue в Steam

12.06.2021 16:15:59 | Автор: admin

Да, понимаю, что это игра про учёных, но это не игра про немого учёного с монтировкой с цифрой 3, которую все ждут. Что вышло за 4 года разработки.

Официальное описание: Научная станция в глубоком космосе перестала отвечать на запросы. Что там произошло? Вы агент, прибывший выяснить, что случилось и Ваша задача спасти важное открытие, сделанное на станции.

Ученые находятся в комнатах с колбами. Система по очереди открывает криокамеры, и они постепенно отходят от заморозки и плохо соображают. Вам необходимо спасти не менее шести представителей науки: каждый из них обладает важным фрагментом информации. Вражеская техника управляется извне и занимается уничтожением имущества и людей. К счастью в складских помещениях достаточно снаряжения и техники которые могут помочь в вашем деле.

Заправьте свой корабль радиоактивным топливом и спасите ученых. Берегите себя, науку и удачи!

Это ретро экшен, требующий достаточной быстроты, либо ловкости, либо хитрости от игрока. Есть несколько тактик прохождения игры. Кроме арсенала в 10 видов оружия, каждое из которых накладывает особый эффект на врага и имеет несколько режимов стрельбы, есть ещё и хитрость в виде ловушек или предметов сильно отвлекающих противника. некоторых настолько что игрок будет почти невидим для врагов. Даже на нормальной сложности игра не будет лёгкой прогулкой по которой игрока будут водить за ручку и обьяснять Press F to Win. Однако если вам игра покажется слишком лёгкой уровень сложности можно повысить.

В самой игре заложена и пара "пасхалок" напоминающих о спектруме. Я не скажу где они однако одна из них содержит пару обьектов из Boulder dash, а другая ещё что-то.

Ключевые обновления:

  • Добавлен режим хотсита - кооп (. затем kp9) и версус (. затем kp7). (Игра на 2 клавиатурах и/или джойстиках). Cетевая игра увы возможна только через Steam remote play.

  • Все почти враги теперь анимированы (новое видео пока не готово)

  • Внешний интерфейс (USER GUI) доработан. (Инвентарь, выбранное оружие, датчик жизни, кулдаун, селектор оружия.)

  • Встроенная игровая справка по F2 с описанием тактики поведения и арсенала.

Ключевые особенности

  • Редактор карт поддерживает импорт карт M2K (mission 2000), Rescue+ с реального ZX-Spectrum. Карты будут работать если их копировать программой HOBETA.

  • Мультиязычность и кроссплатформенность.

  • Высокая скорость работы даже на устаревших компьютерах.

Подсказка: Максимально просто игру можно пройти вдвоем - Один из игроков должен выбрать ученого при начале совместной игры.

Игра нетребовательная идёт почти на всём. Требования: 64бит и OpenGL 3.3 и хотя бы 30 мб места.

Steam Ранний доступ.

Все списки обновлений переводятся также на 3 языка как и сама игра. Прочесть можно на страничке игры

Я ранее писал статью на DTF и если кто хочет просто попробовать игру Reskue или M2K или Colony (очень ранняя версия) может скачать их ниже.

Видео новее пока нет. если только про кооператив и версус ссылка под видео. С тех пор игра была сильно переработана но я пока не осилил трейлер.

Хотсит на русском.

Новый трейлер на польском.

Я на вопросы иногда делаю выпуски видеоответов. Реже чем надо было бы, но делаю. https://www.youtube.com/watch?v=JJAe2b-kTgs - Руководство о портировании готовой игры на Love в Android APK (с подписью) для Linux. В блоге разработчика (devblog) бывают и арты и рисунки и другая всячина.

Игра написана с нуля и сохранившая в основном идею оригинала (Rescue od Mastertronic) и схожесть с Spectrum играми (тайлы, цветовая гамма, некоторая хардкорность геймплея и некоторые команды в Lua движке.). От оригинальной игры не используется ничего, перерисовано все что возможно. Изначально я делал ремейк собственной игры M2K (mission2000), затем понял что на основе движка могу сделать новую игру что и начал в 2019, вдохновили меня в коллективе confa-gd на конкурсе Джем победы на это. Канал по игре.

C чего всё начиналось:

Это оказался прекрасный фундамент для применения множества идей как Sci-fi так и просто современных удобств геймплея каждую из которых пришлось делать самому, т.к. движок мой авторский на Love framework. Я постарался бережно развить идею так как ранее с ограничениями платформы ее развить было бы значительно сложнее. Я с трудом нашел нескольких художников и аниматоров и за ещё 2 года и 16К получилась эта игра. Отдельная история и целая лекция получилась по работе со Steamworks чтобы игра попала в магазин, это заняло целых полгода в основном доработки тексту. Я даже не думаю что она вообще когда то отобьется и будет кормить меня и принесет мне хоть что то. мне просто хотелось возродить частичку классики так как я её вижу и сделать ее доступной всем.

Также я веду небольшой ютуб и телеграм каналы без мемасиков и приколов посвященный Linux для домашнего использования. Сборка в основном для тестирования Windows игр предназначена. Сам я выбрал Mint c Mate DE немного новостей немного взаимопомощи.

N.B. Людям, которые ждут, что один человек почти в одно лицо накодит им Ведьмака 3 в 3D за денек, прошу выйти из чата. Этим методом получатся только игры для Gry z kosza (польская передача об очень плохих играх).

Мне просто хочется, чтобы в эту игру можно было сыграть и через много лет спустя, я думаю Steam с нами всеми надолго и игра там точно проживёт много лет. Да название я написал в духе названия mortal kombat. А почему нет?

Также я время от времени обновляю код движка на github. У меня там несколько проектов.

Подробнее..

Навигация в многомодульном приложении на Jetpack без магии и DI

22.04.2021 20:09:52 | Автор: admin

Когда вы начинаете создавать приложение, в котором хотя бы несколько экранов, всегда встает вопрос - как лучше реализовать навигацию. Вопрос становится интереснее и сложнее, когда вы собираетесь делать многомодульное приложение. Примерно полтора года назад я рассказывал как можно реализовать навигацию c помощью Jetpack в многомодульном проекте. И вот спустя время, я наткнулся на свою реализацию и понял, что можно на том же Jetpack летать по модулям проще: без магии и DI.


Архитектура проекта

Чтобы покрыть основные кейсы я покажу как реализовать навигацию на многомодульном проекте такой структуры:

Типичная архитектура Android проекта: feature-модули c реализацией экранов зависят от shared-модулей с общей логикой. И app модуль, который зависит от feature и shared.

Сейчас довольно популярен подход Single Activity, поэтому в моем примере будет всего одна Activity с глобальным хостом, в котором будут переключаться фрагменты

Подготовка

От модуля shared:navigation зависят почти все модули проекта не просто так. В этом модуле реализована функция расширения фрагмента для реализации переходов.

fun Fragment.navigate(actionId: Int, hostId: Int? = null, data: Serializable? = null) {val navController = if (hostId == null) {findNavController()} else {Navigation.findNavController(requireActivity(), hostId)}val bundle = Bundle().apply { putSerializable("navigation data", data) }navController.navigate(actionId, bundle)}

У функции есть параметры:

  • actionId - id действия графа навигации

  • hostId - id хоста графа навигации. Если не будет передан, то будет использован текущий хост

  • data - объект с данными типа Serializable

В этом же модуле реализована функция расширения фрагмента для получения данных, которые были переданы при выполнении действия навигации.

val Fragment.navigationData: Serializable?get() = arguments?.getSerializable("navigation data")

Также в этом модуле надо описать id хостов навигации, чтобы к ним был доступ из feature модулей. Для этого в директории ресурсов надо создать файл res/value/ids.xml

<?xml version="1.0" encoding="utf-8"?><resources><item name="host_global" type="id"/><item name="host_main" type="id"/></resources>

Отлично! Подготовка завершена, можно приступать к самой реализации навигации.

Простые переходы в feature-модулях

Сэмулируем типичное поведение экрана splash. Обычно с этого экрана идет переход либо к онбордингу, либо к главному экрану приложения, либо к экрану авторизации. Реализуем нечто похожее: пусть фрагмент фичи splash будет уметь переходить на экран онбординга и на главный экран по нажатию кнопки.

Для начала создади id для этих действий: запишем их в res/value/ids.xml модуля splash

<?xml version="1.0" encoding="utf-8"?><resources><item name="action_splashFragment_to_mainFragment" type="id"/><item name="action_splashFragment_to_onboardingFragment" type="id"/></resources>

Id для действий переходов я рекомендую создавать именно в модулях фич, которые будут использовать эти действия, а не в модуле shared:navigation. Это позволяет модулю знать только о необходимых действиях.

Теперь можно использовать созданные id для выполнения переходов.

import com.example.smmn.shared.navigation.navigateclass SplashFragment : Fragment(R.layout.fragment_splash) {    override fun onViewCreated(view: View, savedInstanceState: Bundle?) {        super.onViewCreated(view, savedInstanceState)        buttonToOnboarding.setOnClickListener {            navigate(R.id.action_splashFragment_to_onboardingFragment)        }        buttonToMain.setOnClickListener {            navigate(R.id.action_splashFragment_to_mainFragment)        }    }}

Обратите внимание, что для выполнения перехода используется функция расширения из модуля shared:navigation.

Но чтобы этот переход заработал надо настроить глобальный хост и реализовать глобальную навигацию.

Глобальный хост

В нашей архитектуре всего одна Activity. Она будет содержать глобальный хост для фрагментов. Для этого нам ничего не потребуется реализовывать в самом коде Activity.

class MainActivity : AppCompatActivity(R.layout.activity_main)

Хост добавить надо в ее разметке activity_main.xml

<?xml version="1.0" encoding="utf-8"?><androidx.fragment.app.FragmentContainerView xmlns:android="http://personeltest.ru/away/schemas.android.com/apk/res/android"    xmlns:app="http://personeltest.ru/away/schemas.android.com/apk/res-auto"    xmlns:tools="http://personeltest.ru/away/schemas.android.com/tools"    android:id="@id/host_global"    android:name="androidx.navigation.fragment.NavHostFragment"    android:layout_width="match_parent"    android:layout_height="match_parent"    app:defaultNavHost="true"    app:navGraph="@navigation/navigation_global"    tools:ignore="FragmentTagUsage" />

Глобальная навигация

Это навигация, которая происходит в глобальном хосте. Для ее реализации надо реализовать в модуле app граф навигации res/navigation/navigation_global.xml

<?xml version="1.0" encoding="utf-8"?><navigation xmlns:android="http://personeltest.ru/away/schemas.android.com/apk/res/android"    xmlns:app="http://personeltest.ru/away/schemas.android.com/apk/res-auto"    android:id="@+id/navigation_global"    app:startDestination="@id/splashFragment">    <fragment        android:id="@+id/splashFragment"        android:name="com.example.smmn.feature.splash.SplashFragment"        android:label="SplashFragment">        <action            android:id="@id/action_splashFragment_to_mainFragment"            app:destination="@id/mainFragment"            app:popUpTo="@id/navigation_global" />        <action            android:id="@id/action_splashFragment_to_onboardingFragment"            app:destination="@id/onboardingFragment"            app:popUpTo="@id/navigation_global" />    </fragment>    <fragment        android:id="@+id/mainFragment"        android:name="com.example.smmn.feature.main.MainFragment"        android:label="MainFragment" >        <action            android:id="@id/action_mainFragment_to_splashFragment"            app:popUpTo="@id/navigation_global"            app:destination="@id/splashFragment" />    </fragment>    <fragment        android:id="@+id/onboardingFragment"        android:name="com.example.smmn.feature.onboarding.OnboardingFragment"        android:label="OnboardingFragment">        <action            android:id="@id/action_onboardingFragment_to_mainFragment"            app:destination="@id/mainFragment"            app:popUpTo="@id/navigation_global" />    </fragment></navigation>

Обратите внимание, что у каждого фрагмента есть набор action (действий) с помощью которых происходит переход между фрагментами. В действии указывается на какой фрагмент будет выполнен переход и как обрабатывать переход назад, например, при нажатии кнопки "Back".

И очень важно отметить, что id действий прописаны без знака +, то есть мы не создаем id в этом графе, а используем id, прописанные в feature модуле.

Прописанные id в модуле splash

<item name="action_splashFragment_to_mainFragment" type="id"/><item name="action_splashFragment_to_onboardingFragment" type="id"/>

Использование их в действиях глобального графа

        <action            android:id="@id/action_splashFragment_to_mainFragment"            app:destination="@id/mainFragment"            app:popUpTo="@id/navigation_global" />        <action            android:id="@id/action_splashFragment_to_onboardingFragment"            app:destination="@id/onboardingFragment"            app:popUpTo="@id/navigation_global" />

Вложенный хост

В Jetpack навигации есть возможность использовать вложенный хост. Это очень полезно, когда мы хотим сделать меню типа BottomNavigation и использовать для этого меню отдельный граф навигации.

В нашем примере во вложенном хосте будут фичи профиля и настроек.

Благодаря библиотеке navigation-ui, реализовать вложенную навигацию довольно просто.

В модуле main создадим меню для BottomNavigation в res/menu/menu_main.xml

<?xml version="1.0" encoding="utf-8"?><menu xmlns:android="http://personeltest.ru/away/schemas.android.com/apk/res/android">    <item        android:id="@+id/profileFragment"        android:icon="@drawable/ic_baseline_account_circle_24"        android:title="@string/main_menu_title_profile" />    <item        android:id="@+id/settingsFragment"        android:icon="@drawable/ic_baseline_settings_24"        android:title="@string/main_menu_title_settings" /></menu>

Создадим граф навигации в res/navigation/navigation_main.xml

<?xml version="1.0" encoding="utf-8"?><navigation xmlns:android="http://personeltest.ru/away/schemas.android.com/apk/res/android"    xmlns:app="http://personeltest.ru/away/schemas.android.com/apk/res-auto"    android:id="@+id/navigation_main"    app:startDestination="@id/profileFragment">    <fragment        android:id="@+id/profileFragment"        android:name="com.example.smmn.feature.profile.ProfileFragment"        android:label="ProfileFragment">        <action            android:id="@id/action_profileFragment_to_infoFragment"            app:destination="@id/infoFragment" />    </fragment>    <fragment        android:id="@+id/settingsFragment"        android:name="com.example.smmn.feature.settings.SettingsFragment"        android:label="SettingsFragment" />    <fragment        android:id="@+id/infoFragment"        android:name="com.example.smmn.feature.info.InfoFragment"        android:label="InfoFragment" /></navigation>

Здесь важно указать у фрагментов те же id что указаны в файле меню res/menu/menu_main.xml. И не забывать, что id действий брать из модулей фич.

Осталось добавить хост и меню в разметку фрагмента res/layout/fragment_main.xml

<?xml version="1.0" encoding="utf-8"?><androidx.constraintlayout.widget.ConstraintLayout xmlns:android="http://personeltest.ru/away/schemas.android.com/apk/res/android"    xmlns:app="http://personeltest.ru/away/schemas.android.com/apk/res-auto"    android:layout_width="match_parent"    android:layout_height="match_parent">    <fragment        android:id="@id/host_main"        android:name="androidx.navigation.fragment.NavHostFragment"        android:layout_width="match_parent"        android:layout_height="0dp"        app:defaultNavHost="true"        app:layout_constraintBottom_toTopOf="@+id/bottomNavigationView"        app:layout_constraintEnd_toEndOf="parent"        app:layout_constraintStart_toStartOf="parent"        app:layout_constraintTop_toTopOf="parent"        app:navGraph="@navigation/navigation_main" />    <com.google.android.material.bottomnavigation.BottomNavigationView        android:id="@+id/bottomNavigationView"        android:layout_width="match_parent"        android:layout_height="wrap_content"        android:background="@android:color/white"        app:elevation="8dp"        app:layout_constraintBottom_toBottomOf="parent"        app:layout_constraintEnd_toEndOf="parent"        app:layout_constraintStart_toStartOf="parent"        app:menu="@menu/menu_main" /></androidx.constraintlayout.widget.ConstraintLayout>

И в самом фрагменте настроить bottomNavigationView

class MainFragment : Fragment(R.layout.fragment_main) {    override fun onViewCreated(view: View, savedInstanceState: Bundle?) {        super.onViewCreated(view, savedInstanceState)        NavigationUI.setupWithNavController(            bottomNavigationView,            Navigation.findNavController(requireActivity(), R.id.host_main)        )    }}

Переходы между фрагментами из разных хостов

Довольно частый случай, когда надо перейти с экрана, который находится внутри вложенного хоста, на экран глобального хоста. Например, у нас есть главный экран c хостом для экранов главных фич: настроек и профиля.

И на экране настроек, который находится внутри хоста главного экрана (не глобальный хост, а глубже) надо выполнить переход на экран сплэша, который находится в глобальном хосте. Например это может понадобиться, если надо разлогинить текущего пользователя.

В этом случае также воспользуемся функцией расширения фрагмента, но укажем id глобального хоста. Мы имеем к нему доступ из фичи, так как он прописан в модуле shared:navigation.

class SettingsFragment : Fragment(R.layout.fragment_settings) {    override fun onViewCreated(view: View, savedInstanceState: Bundle?) {        super.onViewCreated(view, savedInstanceState)        buttonToSplash.setOnClickListener {            navigate(R.id.action_mainFragment_to_splashFragment, R.id.host_global)        }    }}

Id действия по аналогии с предыдущим переходом прописан в самом модуле фичи res/values/ids.xml

<?xml version="1.0" encoding="utf-8"?><resources><item name="action_mainFragment_to_splashFragment" type="id"/></resources>

Переходы между фрагментами с передачей и получением данных

Чтобы выполнить переход с передачей данных необходимо, чтобы данные можно было положить в bundle. Это могуг быть какие-то примитивные типы или объекты Serializable классов.

Выше я уже реализовал функцию расширения фрагмента для выполнения перехода, в которую можно передать объект Serializable класса. Аналогично вы можете реализовать передачу примитивных типов.

Чтобы передать объект Serializable класса надо чтобы модуль фичи, с которой происходит переход, и модуль фичи, на которую происходит переход, имели доступ к модулю с таким классом. В нашем случае создадим модуль shared:model где будет лежать Serializable класс Info.

data class Info(    val name: String,    val surname: String) : Serializable

Переход будет происходить с экрана profile на экран info. Создадим объект Info и передадим его в функцию расширения фрагмента.

class ProfileFragment : Fragment(R.layout.fragment_profile) {    override fun onViewCreated(view: View, savedInstanceState: Bundle?) {        super.onViewCreated(view, savedInstanceState)        buttonToInfo.setOnClickListener {            navigate(R.id.action_profileFragment_to_infoFragment, data = Info("name", "surname"))        }    }}

И получим данные используя другую функцию расширения фрагмента, созданную ранее.

class InfoFragment : Fragment(R.layout.fragment_info) {    override fun onViewCreated(view: View, savedInstanceState: Bundle?) {        super.onViewCreated(view, savedInstanceState)        val info = navigationData as? Info ?: return        textView.text = info.toString()    }}

Так это будет выглядеть в приложении

Заметьте, что мы не указывали в каком хосте выполнить переход, и переход произошел в текущем хосте.

Заключение

Таким несложным способом можно организовать навигацию в вашем многомодульном проекте, используя Jetpack и пару функций расширения. Этот подход функционально не отличается от подхода, который я описывал ранее, но в использовании он намного проще и лаконичнее.

Оставляю ссылку на код примера приложения.

Буду рад обратной связи!

Подробнее..

Категории

Последние комментарии

  • Имя: Макс
    24.08.2022 | 11:28
    Я разраб в IT компании, работаю на арбитражную команду. Мы работаем с приламы и сайтами, при работе замечаются постоянные баны и лаги. Пацаны посоветовали сервис по анализу исходного кода,https://app Подробнее..
  • Имя: 9055410337
    20.08.2022 | 17:41
    поможем пишите в телеграм Подробнее..
  • Имя: sabbat
    17.08.2022 | 20:42
    Охренеть.. это просто шикарная статья, феноменально круто. Большое спасибо за разбор! Надеюсь как-нибудь с тобой связаться для обсуждений чего-либо) Подробнее..
  • Имя: Мария
    09.08.2022 | 14:44
    Добрый день. Если обладаете такой информацией, то подскажите, пожалуйста, где можно найти много-много материала по Yggdrasil и его уязвимостях для написания диплома? Благодарю. Подробнее..
© 2006-2024, personeltest.ru