Создание простой игры на андроид

Создание простой игры на андроид

Этот туториал предназначен в первую очередь для новичков в разработке под андроид, но может быть будет полезен и более опытным разработчикам. Тут рассказано как создать простейшую 2D игру на анроиде без использования каких-либо игровых движков. Для этого я использовал Android Studio, но можно использовать любую другую соответствующее настроенную среду разработки.

Шаг 1. Придумываем идею игры
Для примера возьмём довольно простую идею:

Внизу экрана — космический корабль. Он может двигаться влево и вправо по нажатию соответствующих кнопок. Сверху вертикально вниз движутся астероиды. Они появляются по всей ширине экрана и двигаются с разной скоростью. Корабль должен уворачиваться от метеоритов как можно дольше. Если метеорит попадает в него — игра окончена.

Шаг 2. Создаём проект
В Android Studio в верхнем меню выбираем File > New > New Project.

Тут вводим название приложения, домен и путь. Нажимаем Next.

Тут можно ввести версию андроид. Также можно выбрать андроид часы и телевизор. Но я не уверен что наше приложение на всём этом будет работать. Так что лучше введите всё как на скриншоте. Нажимаем Next.

Тут обязательно выбираем Empty Activity. И жмём Next.

Тут оставляем всё как есть и жмём Finish. Итак проект создан. Переходим ко третьему шагу.

Шаг 3. Добавляем картинки

Скачиваем архив с картинками и распаковываем его.

Находим папку drawable и копируем туда картинки.

Позже они нам понадобятся.

Шаг 4. Создаём layout

Находим activity_main.xml, открываем вкладку Text и вставляем туда это:

На вкладке Design видно как наш layout будет выглядеть.

Сверху поле в котором будет сама игра, а снизу кнопки управления Left и Right. Про layout можно написать отдельную статью, и не одну. Я не буду на этом подробно останавливаться. Про это можно почитать тут.

Шаг 5. Редактируем MainActivity класс

В первую очередь в определение класса добавляем implements View.OnTouchListener. Определение класса теперь будет таким:

Добавим в класс нужные нам статические переменные (переменные класса):

В процедуру protected void onCreate(Bundle savedInstanceState) <
добавляем строки:

Классы LinearLayout, Button и т.д. подсвечены красным потому что ещё не добавлены в Import.
Чтобы добавить в Import и убрать красную подсветку нужно для каждого нажать Alt+Enter.
GameView будет подсвечено красным потому-что этого класса ещё нет. Мы создадим его позже.

Теперь добавляем процедуру:

Если кто-то запутался ? вот так в результате должен выглядеть MainActivity класс:

Итак, класс MainActivity готов! В нём инициирован ещё не созданный класс GameView. И когда нажата левая кнопка — статическая переменная isLeftPressed = true, а когда правая — isRightPressed = true. Это в общем то и всё что он делает.

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

Шаг 6. Создаём класс GameView

Теперь наконец-то создадим тот самый недостающий класс GameView. Итак приступим. В определение класса добавим extends SurfaceView implements Runnable. Мобильные устройства имею разные разрешения экрана. Это может быть старенький маленький телефон с разрешением 480×800, или большой планшет 1800×2560. Для того чтобы игра выглядела на всех устройствах одинаково я поделил экран на 20 частей по горизонтали и 28 по вертикали. Полученную единицу измерения я назвал юнит. Можно выбрать и другие числа. Главное чтобы отношение между ними примерно сохранялось, иначе изображение будет вытянутым или сжатым.

unitW и unitW мы вычислим позже. Также нам понадобятся и другие переменные:

Конструктор будет таким:

Метод run() будет содержать бесконечный цикл. В начале цикла выполняется метод update()
который будет вычислять новые координаты корабля. Потом метод draw() рисует корабль на экране. И в конце метод control() сделает паузу на 17 миллисекунд. Через 17 миллисекунд run() запустится снова. И так до пока переменная gameRunning == true. Вот эти методы:

Обратите внимание на инициализацию при первом запуске. Там мы вычисляем количество пикселей в юните и добавляем корабль. Корабль мы ещё не создали. Но прежде мы создадим его родительский класс.

Шаг 7. Создаём класс SpaceBody

Он будет родительским для класса Ship (космический корабль) и Asteroid (астероид). В нём будут содержаться все переменные и методы общие для этих двух классов. Добавляем переменные:

Шаг 8. Создаём класс Ship

Теперь создадим класс Ship (космический корабль). Он наследует класс SpaceBody поэтому в определение класа добавим extends SpaceBody.

и переопределим метод update()

На этом космический корабль готов! Всё компилируем и запускаем. На экране должен появиться космический корабль. При нажатии на кнопки он должен двигаться вправо и влево. Теперь добавляем сыплющиеся сверху астероиды. При столкновении с кораблём игра заканчивается.

Шаг 9. Создаём класс Asteroid

Добавим класс Asteroid (астероид). Он тоже наследует класс SpaceBody поэтому в определение класса добавим extends SpaceBody.

Добавим нужные нам переменные:

Астероид должен появляться в случайной точке вверху экрана и лететь вниз с случайной скоростью. Для этого x и speed задаются при помощи генератора случайных чисел в его конструкторе.

Астероид должен двигаться с определённой скорость вертикально вниз. Поэтому в методе update() прибавляем к координате x скорость.

Так же нам нужен будет метод определяющий столкнулся ли астероид с кораблём.

Рассмотрим его поподробнее. Для простоты считаем корабль и астероид квадратами. Тут я пошёл от противного. То есть определяю когда квадраты НЕ пересекаются.

((x+size) (shipX+shipSize)) — корабль справа от астероида.
((y+size) (shipY+shipSize)) — корабль снизу астероида.

Между этими четырьмя выражениями стоит || (или). То есть если хоть одно выражение правдиво (а это значит что квадраты НЕ пересекаются) — результирующие тоже правдиво.

Всё это выражение я инвертирую знаком!. В результате метод возвращает true когда квадраты пересекаются. Что нам и надо.

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

Шаг 10. Добавляем астероиды в GameView

В GameView добавляем переменные:

также добавляем 2 метода:

И в методе run() добавляем вызовы этих методов перед вызовоом control().

Далее в методе update() добавляем цикл который перебирает все астероиды и вызывает у них метод update().

Читайте также:  Почему после скачивания фильма нет звука

Такой же цикл добавляем и в метод draw().

Вот и всё! Простейшая 2D игра готова. Компилируем, запускаем и смотрим что получилось!
Если кто-то запутался или что-то не работает можно скачать исходник.

Игра, конечно, примитивна. Но её можно усовершенствовать, добавив новые функции. В первую очередь следует реализовать удаление вылетевших за пределы экрана астероидов. Можно сделать чтобы корабль мог стрелять в астероиды, чтобы игра постепенно ускорялась, добавить таймер, таблицу рекордов и прочее. Если это будет вам интересно — напишу продолжение, где всё это опишу.

На этом всё. Пишите отзывы, вопросы, интересующие вас темы для продолжения.

Вы можете помочь и перевести немного средств на развитие сайта

Индустрия мобильных игр для смартфонов и планшетов на Android с каждым годом набирает обороты.

  • На 2017 год в России более 80 млн. пользователей смартфонов.
  • Самые популярные мобильные игры приносят доход от 3-х до 5-ти млн. долларов в квартал.
  • 69% – доля рынка Android, 27% – игры для iOS.

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

Какое направление игры выбрать?

Самыми популярными мобильными жанрами в России являются:

Хоть в этих нишах и высокая конкуренция, заработать тут можно. Это делается несколькими способами:

  1. С помощью монетизации через рекламные сети (AdColony, Chartboost, Admob, Vungle и др.) – в вашей игре показывается реклама, за которую вы получаете процент.
  2. С помощью внутренних покупок – в играх могут быть виртуальные валюты, товары, VIP-статусы, которые помогают игроку и которые можно приобрести за реальные деньги.
  3. С помощью системы достижений – они могут стимулировать игрока приобрести тот или иной товар за реальные деньги.
  4. Брендирование – в случае, если ваша игра приобретает популярность или же имеет обнадеживающие прогнозы, то вполне возможно, что вами заинтересуются крупные компании. Например, захотят поместить свой логотип на одну из ваших текстур!
  5. Платные версии игр с большим количеством контента, чем в бесплатных. Это наиболее популярная бизнес модель (наличие платной и бесплатной версии), и называется она Freemium.

С чего начать разработку мобильной игры?

Секрет большого количества установок и продаж игры — уникальный дизайн и геймплей. Поэтому важно ответить на следующие вопросы:

  • насколько свободна интересующая меня ниша? Вполне возможно, что игр в жанре, в который вы метите, и так хватает, а интерес пользователей только падает. Вам такое вряд ли нужно.
  • кто моя целевая аудитория? Составьте портрет пользователя, который будет играть в вашу игру. Подскажем: в среднем это мужчины и женщины 25-30 лет, с семьей.
  • кто мои конкуренты? Необходимо проанализировать их сильные и слабые стороны, обратить внимание на контент, монетизацию, систему покупок внутри игры, а также игровую механику.
    чем дизайн моей игры и ее гемплей будет интересней и увлекательней? Здесь важно не только придумать оригинальный интерфейс и историю — нужно сделать игру интуитивно понятной.
  • как она будет называться? Сделайте название коротким и интересным, от одного до трех слов. Посмотрите, как зовут себя конкуренты и старайтесь придумать что-то уникальное. Копировать слова можно, но не более одного.
  • Какой язык программирования будет использоваться? Чаще всего используется Unity, но, тем не менее, также обозначьте это на начальных этапах разработки.

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

Где найти разработчика игр для Android?

Поиск разработчика приведет вас или на рынок фрилансеров или на рынок IT-компаний. Кому отдать предпочтение? Коротко о каждом:

  • фрилансеры — самозанятые разработчики. Стоимость их услуг меньше, чем в веб-студии, но также присутствует риск срыва сроков, нестабильная коммуникация. Выбирая этот вариант, тщательно изучите портфолио фрилансера, запросите отзывы о нем от его предыдущих клиентов, проверьте, работает ли он на биржах фриланса – там тоже можно найти подобную информацию.
  • профессиональная веб-студия — команда специалистов с опытом в разработке мобильных игр и с налаженной методологией. Тем не менее, здесь так же важно проверить репутацию студии.

Если хотите, чтобы игра появилась в Google Play и хорошо продавалась, то рекомендуем отдать предпочтение веб-студии!

Как выбрать веб-студию для разработки игры?

Анализ рейтингов разработчиков мобильных игр

Посмотрев рейтинг, сразу проигнорируйте его верхнюю и нижнюю часть (услуги первых слишком дорогие, а последних — сомнительного качества). Из середины рейтинга сформируйте шорт-лист и напишите всем компаниям.

Оценка скорости обратной связи

Вычеркните из списка те компании, которые не связались с вами оперативно и не предложили консультацию.

Теперь самое время ознакомьтесь с портфолио оставшихся в списке веб-студий. Отберите тех, кто обладает наибольшим релевантным опытом. Оцените удобство и простоту интерфейса нескольких игр из портфолио, перейдя по ссылкам на Google Play.

Затем предоставьте им техническое задание (ТЗ) или описание функционала игры на оценку. Если компания просто прислала число в рублях или в часах – смело вычеркивайте ее из списка.

Общение с клиентами

Попросите контакты нескольких клиентов и в личной беседе уточните насколько довольны они сотрудничеством с этой компанией, насколько тщательно выполнялась оценка проекта, насколько оперативно решались проблемы по ходу реализации проекта и т.д.

Знакомство с командой

Когда в списке осталось 2-3 компании можно переходить к личному знакомству с командой.

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

Поинтересуйтесь, есть ли в компании собственный отдел QA (тестирование), иначе искать ошибки придется вам или вашим клиентам. Спросите про парк устройств QA-отдела. Если в нем только несколько смартфонов Xiaomi и Lenovo, то это уж точно не должно внушать доверия. Парк устройств обязательно должен включать как дешевые смартфоны на Android, так и актуальные флагманы известных брендов.

Читайте также:  Как проверить авто по интернету

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

Позвоните нам и узнайте, почему разработку игр для android стоит доверить компании «InfoShell»!

Вступительное слово

Этот урок начинает серию статей, посвященных написанию аркадных игр для Android. За основу был взят цикл, который написал и опубликовалв своем блогеTamas Jano. Материал ориентирован, прежде всего, на начинающих программистов, которые хотят попробовать свои силы в создании игр для Android. Я ставлю перед собой цель создать у нас на сайте максимально понятный и доступный учебник для молодой русскоязычной аудитории, поэтому очень надеюсь на вашу критику, вопросы и комментарии. Опубликованный в этом цикле материал будет постоянно перерабатываться с учетом ваших вопросов, пожеланий и замечаний. Надеюсь, что вместе мы сможем успешно осуществить этот небольшой эксперимент.

Идея и архитектура

Прежде чем переходить непосредственно к программированию, давайте определимся с нашими задачами и опишем в общих чертах нашу будущую игру. Идея проста: главный герой борется с ордами роботов, которые хотят его уничтожить. У него есть три жизни и лазерное ружье. Роботы не умеют стрелять. Все что они могут — поймать нашего героя и оторвать ему голову. ну или что-нибудь еще. Управление персонажем осуществляется с помощью двух "сенсорных джойстиков" Вы наверняка встречали их в подобных играх. В левом нижнем углу будет размещен джойстик, отвечающий за перемещение героя. В правом нижнем углу — за оружие.

Смоделируем игровую ситуацию. Наш персонаж находится в центре экрана. Роботы каждую 1/10 секунды приближаются к нему. каждую десятую секунду мы проверяем также не произошло ли касание экрана. Если произошло — двигаем наш персонаж в необходимом направлении или делаем выстрел. если выстрел сделан, каждый тик (1/10 секунды) мы проверяем столкновение пули с врагами. Если пуля попала в робота — то и робот и пуля взрываются, если нет — роботы и пуля перемещаются на новые позиции (робот перемещается на 5 пикселей за тик, а пуля — на 50 пикселей). Мы также проверяем не поймал ли робот нашего героя. Если поймал — игра заканчивается.

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

  1. Модуль управления. Здесь считываются координаты касания экрана.
  2. Игровой движок. Здесь мы должны обновить состояние игровых объектов, то есть вычислить их новые координаты, проверить здоровье, столкновения и тому подобное.
  3. Аудио модуль.
  4. Графический модуль. Здесь на основании текущего состояния формируется и выводится на экран новый кадр.

Давайте более детально рассмотрим наши модули.

Модуль управления

В нашей игре сообщения генерируются при касании пользователем двух областей на экране. Программа отслеживает события onTouch и записывает координаты каждого касания. Если координаты находятся внутри управляющей области, мы посылаем соответствующую команду игровому движку. Например, если произошло касание сбоку круга, мы должны двигать нашего персонажа в соответствующую сторону. Если произошло касание круга, управляющего оружием, мы посылаем команду движку обработать событие выстрела.

Игровой движок

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

Давайте рассмотрим взаимодействие модуля управления и игрового движка. На представленном выше рисунке показан круг-контроллер. Светлое зеленое пятно символизирует область касания. Модуль управления сообщает игровому движку координаты касания (dx и dy — расстояния в пикселях от центра круга). На основании этих координат игровой движок вычисляет направление и скорость движения нашего героя. Например, если dx>0, наш персонаж движется вправо, eсли dy>0 — в верх.

Аудио модуль

Этот модуль управляет проигрывание звука в зависимости от игровой ситуации. Звуки могут генерировать разные игровые объекты, но поскольку число звуковых каналов ограничено (число звуковых каналов соответствует числу звуковых файлов, которые могут быть проиграны одновременно), аудио модуль должен решать какие звуки проигрывать, а какие нет. Например, робот представляет огромную опасность для нашего героя, поэтому мы должны привлечь внимание игрока к его появлению, например включить звук сирены, и конечно, мы просто обязаны озвучивать все выстрелы нашего персонажа.

Графический модуль

Этот модуль отвечает за вывод игровой ситуации на экран телефона. В Android существует несколько способов формирования изображения на экране. Можно рисовать прямо на canvas, полученный от View или использовать отдельный графический буффер и вы, а затем передавать его View, а можно воспользоваться возможностями библиотеки OpenGL. Полезно при разработке игры постоянно измерять FPS — число кадров в секунду, которые выдает ваш графический движок. Величина в 30 FPS означает, что за одну секунду наша программа успевает 30 раз обновить экран. Забегая вперед скажу, что для мобильного устройства 30 FPS более чем достойный показатель.

Создаем проект-заготовку для будущей Android игры

Я не буду здесь подробно расписывать процесс установки Android SDK и Eclipse, за рамками повествования я оставлю и элементарные действия по созданию Android проекта. В интернете валяется огромное количество уроков и статей, посвященных этой теме.

Создайте новый проект. В поле Project Name введитеDroidz. В качестве целевой платформы выберите Android 2.2 или выше. В Package Name — "ru.mobilab.gamesample". Не забудьте поставить галочку около Create Activity. В качестве имени главной activity введитеDroidzActivity.

Откройте файл src/ru.mobilab.gamesample/DroidzActivity.java

Метод onCreate вызывается при создании activity во время запуска приложения. Этот метод можно рассматривать, как точу входа в программу. Класс R.java автоматически генерируется Eclipse и содержит в себе ссылки на ресурсы. Каждый раз, когда вы изменяете ресурсы в Eclipse класс R пересобирается.

Главный игровой цикл

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

Читайте также:  Гитарный ламповый усилитель на 6п3с

Как вы помните, в Android все происходит внутри Activity. Activity создает View — объект, где происходит все самое интересное. Именно через него мы можем получить информацию о касаниях экрана, здесь же можно вывести картинку на экран.

Давайте откроем файл DroidzActivity.java. В конструкторе класса вы увидите строчку

эта строка выбирает текущий объект View для Activity. Давайте создадим новый объект для View. Наиболее простым способом получения View — создать собственный класс на основании SurfaceView. В нашем классе мы реализуем интерфейс SurfaceHolder.Callback, чтобы ускорить доступ к изменениям поверхности, например когда она уничтожается при изменении ориентации устройства.

В приведенном выше листинге показан шаблон класса, которые нам предстоит реализовать. Давайте более внимательно посмотрим на содержание конструктора. Строка

Устанавливает текущий класс (MainGamePanel) как обработчик событий от поверхности.

Эта строка делает наш класс фокусируемым. Это означает, что он может получать фокус, а значит и события.

Давайте создадим поток, внутри которого собственно и будет реализован наш игровой цикл. Разделение игры на несколько параллельно выполняющихся потоков — общепринятая в современном геймдеве практика. Создадим для нашего потока класс MainThread.java

Как видите, этот класс существенно проще предыдущего. Внутри мы переопределили метод run(). Поток выполняется до тех пор, пока выполняется этот метод, поэтому мы организовали внутри него бесконечный цикл. Мы добавили логическую переменную running, которая служит индикатором выхода из цикла. Теперь чтобы завершить поток, нужно просто где-то изменить значение этой переменной на false.

После того, как мы создали класс потока, его нужно запустить. Давайте запускать его при загрузке экрана. Изменим класс MainGamePanel

Мы объявили объект thread

и создали его в конструкторе

в методе surfaceCreated мы установили флаг running в значение true и запустили поток. К этому времени объект thread уже благополучно создан и можем без опасений запускать его.

Метод surfaceDestroyed вызывается перед закрытием поверхности. Здесь недостаточно просто снять флаг running. Мы должны убедиться, что поток действительно закрылся. Мы просто блокируем поток и ждем, пока он не умрет.

Добавляем взаимодействие с экраном

Чтобы показать, как в Android обработать касания, напишем небольшой пример. Будем выходить из программы, когда пользователь коснется нижней части экрана. Если касание произошло где-то выше — будем просто выводить в лог соответствующие координаты. Добавим в класс MainThread следующие строки:

тем самым мы определили переменные gamePanel и surfaceHolder, взяв соответствующие значения из параметров конструктора. Нам нужно запомнить эти значения, чтобы потом иметь возможность блокировать поверхность на время рисования, а это можно сделать только через surfaceHolder.

Измените строку в классе MainGamePanel, добабвив в конструктор вновь объявленные параметры

Мы передаем текущий обработчик и панель в новый конструктор. Это позволит нам иметь к ней доступ из потока. В gamePanel мы создадим метод update и будем переключать его из потока, но пока оставим все как есть.

Логирование

Ниже мы напишем вспомогательный код, осуществляющий логирование — запись специальных отладочных строк с текстом, отражающих состояние нашей программы, в специальный файл, который потом можно просмотреть и попытаться понять, что происходило в программе. добавим константу TAG в класс MainThread. Каждый класс будет у нас иметь собственную константу с именем TAG, которая будет содержать название соответствующего класса. Бы будем использовать Android logging framework, чтобы вести логирование, в рамках этой библиотеки каждый лог должен иметь два параметра. Первый параметр определяет место, откуда записан лог. Именно для этих целей мы и создали константу TAG. Второй параметр — собственно сообщение, которое мы хотим записать в лог. Использование имен классов в качестве первого параметра — довольно распространенная в среде java программистов практика.

Чтобы посмотреть записанные в процессе выполнения программы логи нужно выбрать меню
Windows -> Show View -> Other…
а затем в открывшемся диалоге
Android -> LogCat
В открывшемся окне можно не только просматривать логи, но и осуществлять фильтрацию и поиск.

Вернемся к нашему коду. Внесем изменения в MainThread.java

Как видите, мы определили TAG и вызвали внутри метода run команду Log, которая делает соответствующую запись в лог файле. Мы выводим в лог значение переменной tickCount, которая фактически является счетчиком игрового цикла и показывает сколько раз успел выполниться игровой цикл за время работы программы

Перейдем к файлу MainGamePanel.java и найдем метод onTouchEvent, который является обработчиком касаний экрана.

Сначала мы проверяем произошло ли событие касания экрана (MotionEvent.ACTION_DOWN). Если произошло, проверяем координату y и если она находится в нижней части экрана (50 пикселей снизу), мы посылаем потоку команду на завершение (установив переменную running в false), а затем вызываем метод finish() для главной Activity, который закрывает всю нашу программу.

Замечание. Начало системы координат у экрана находится в левом верхнем углу. Ось y направлена вниз, ось x — вправо. Ширину и высоту экрана можно получить с помощью методов getWidth() и getHeight() соответственно.

Изменим DroidzActivity.java, добавив команды записи в лог

Мы добавили строки, переводящие приложение в полноэкранный режим и добавили команды записи в лог в методах onDestroy() и onStop().

Давайте запустим приложение. После запуска Вы должны увидеть черный экран. Пощелкайте несколько раз по верхней части экрана, а затем по нижней. программа закроется. Самое время проверить лог.

Просмотрев лог вы получите четкое представление о порядке запуска методов. Вы также можете увидеть сколько раз за время работы программы успел выполниться игровой цикл. Эта цифра ни о чем не говорит, в следующий раз мы выведем в лог более полезную информацию: FPS и UPS (обновлений в секунду).

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

В следующий раз мы перейдем к рисованию. Исходный код этого урока можно скачатьздесь.

Ссылка на основную публикацию
Сколько рублей получают ютуберы
Видеохостинг YouTube — не только развлекательная площадка, но и хороший источник дохода. Тысячи пользователей выкладывают ролики, пытаясь привлечь внимание аудитории....
Самый дорогой самсунг 2018
Samsung / Самсунг - южнокорейская компания, ведущий производитель смартфонов в мире. В первом квартале 2018 года доля Самсунг на мировом...
Самый лучший smart tv
Ежегодные обновления телевизионных технологий делают телевизоры уже больше, чем обычным экраном для демонстрации каналов. Растет популярность функции Smart TV, которая...
Сколько света мотает компьютер
Выбирая комплектующие для персонального компьютера (ПК) обычно обращают внимание на производительность и объем памяти, порой забывая о том, сколько же...
Adblock detector