Author Topic: Шаблон игры для новичка  (Read 2218 times)

0 Members and 1 Guest are viewing this topic.

Offline Alec - WS3D Developer

  • Producer
  • Administrator
  • Marquess
  • *
  • Posts: 910
  • Reputation 36
  • Game making is my hobby for life!
Шаблон игры для новичка
« on: December 21, 2014, 03:15:41 PM »
Идёт работа над шаблоном игры для начинающих. Шаблон будет основой для игр, от которого можно будет так сказать "плясать".

Шаблон будет состоять из основных элементов игры (кроме меню): загрузка объектов, звуков и др. контента любого проекта и управление ими. По сути, это обычный файл проекта .bas с подробными комментариями.

Становится видно, что можно сделать не только казуалку, но и 3D платформер, квест, РПГ, приключения и другое.

Версия 0.40
Есть игровая карта с основными элементами игры. Можно перемещаться по карте. Есть фоновая музыка.
Пока не всё прокомментировано.

Версия 0.45
- добавил аптечки;
- сделал разные исправления и дополнения:
- папку Media в коде переименовал, чтобы начиналась с большой буквы (критично для Линукс);
- немного поднял камеру, а то низко к полу была;
- добавил тени, кроме препятствия (тень препятствия сильно ест ресурсы процессора, но можно осделать тень попроще);
- пауэрапам сделал текстуры;
- добавил направленный свет (рассеянный уже был);
- некоторые ресурсы заменил или изменил, поэтому лучше прежние русурсы удалить или переименовать.

Версия 0.46
- исправил пару неточностей:
-- комментарий об освещении перенёс туда, где он должен быть;
-- исправил сообщение об управлении (было WASD, на самом деле стрелки).

Версия 0.53
- добавил индикатор здоровья (пока числовой, позже буде и графический);
- при сближении с аптечками (их 3 шт. в лабиринте) прибавляется здоровье, а сама аптечка (точнее её Нод) исчезает;
- код этих фич снабжён подробными комментариями.

Версия 0.60
- проверка расстояния до препятствий; если расстояние меньше 1 метра, сильно падает здоровье (сильно, потому что это не просто препятствия, а "мясорубка")
- здоровье падает на 30 пунктов в секунду, если препятствие не перепрыгивать;
- отрегулирован баланс:
------- если перепрыгнуть препятствие не рассчитав прыжок, то здоровье немного убавится, в связи с этим, отрегулирована высота препятствия и максимальная высота прыжка;
------- постоянное уменьшение здоровья от радиоактивности сделал меньше - 0.03 (или 1,8 пункта в сек.);
- если вдруг после получения аптечки здоровье стало больше 100, всё равно будет 100 (максимум и не больше);

Версия 0.62
- здоровье не уменьшается сразу после загрузки игры (или если будет меню, сразу после того, как игрок кликнул "Старт"). Вместо этого здоровье начинает уменьшаться, когда игрок подходит близко к вращающемуся сообщению "Старт", т.е. ко входу в лабиринт.
- возможность переопределить клавиши для управления. По умолчанию - стрелки + J (для прыжка). В проекте я сделал стандартный набор клавиш управления камерой: WASD + SPACE. Чтобы узнать обозначение клавиш, смотрите справку: Miscellaneous - Key codes или файл WS3DKeyEnum.bi в папке "Examples".

Версия 0.64
-добавлено озвучивание:
-- когда игрок берёт аптечку и повышается здоровье;
-- когда игрок не перепрыгивает препятствие и наносится вред здоровью.
Ссылку на звуки смотрите ниже. Вставьте их в папку /Media/Template. Или вставьте свои звуки, уверен вы увидите, где в коде их нужно вставить.

Версия 0.65
- добавлен простой графический индикатор здоровья (красный уровень на чёрном фоне)
(киньте 2 текстурки в папку /Media/Template )

Версия 0.67 (текущая)
- добавлен спрайт прицела;
- файл шрифта заменён на другой, с поддержкой кириллицы, поэтому теперь можно сообщения на экране писать на русском языке;
- ссылку на архив с этими ресурсами смотрите ниже.

Управление: W,A,S,D + SPACE (прыжок)

Что предстоит сделать:
- когда подходишь к пауэрапу ... (позже решу);
- звуки после взятия пауэрапа, успешного прохождения и др.;
- переход на другой уровень;
- если здоровье ноль и уровень не прошёл - что-то типа "Game over";
- что ещё? предлагайте или помогайте улучшить шаблон.

Ресурсы для шаблона -> скачать (1,44 мб)
Ресурсы необходимо распаковать в папку / Media

Следующие ресурсы кидаем в уже существующую у вас папку /Media/Template
Для версий, начиная с 0.64 также нужны 2 звука: скачать (101 кб)
Для версий, начиная с 0.65 также нужны 2 текстуры: скачать
Для версий, начиная с 0.67 также нужны 3 файла: спрайт прицела и 2 файла для шрифта с поддержкой кириллицы: скачать

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

Code: [Select]
'' ----------------------------------------------------------------------------
'' Автор(ы) проекта: ( )
'' Дата начала создания проекта: ( )
'' Дата окончания проекта: ( )
'' ----------------------------------------------------------------------------
'' <ШАБЛОН ИГРЫ v0.67> (эту и следующую строчку можно убрать, когда будете делать свою игру)
'' <Автор: Alec - WS3D Developer>
'' Краткое описание.
'' Казуальная игра, в которой игроку нужно выбраться из лабиринта. Через препятствия
'' нужно перепрыгивать, иначе они забирают здоровье. Чем меньше здоровье, тем
'' меньше шансов выйти из лабиринта. Если здоровье стало ноль, игра проиграна.
'' Лабиринт радиоактивен, поэтому здоровье игрока постоянно уменьшается, но на пути к
'' финишу он найдёт несколько аптечек, чтобы повысить уровень здоровья (энергии).
'' ----------------------------------------------------------------------------

'' Подключаем библиотеки и другие файлы заголовков:
#include "WorldSim3D.bi"                   'главная библиотека WorldSim3D
#Include "../Libs/FBSound/inc/fbsound.bi"  'библиотека управления звуками

'' Глобальные переменные
' объявляем переменные для работы со звуком
dim as Integer hWave,hSound     'для фоновой музыки
Dim As Integer hWave_2,hSound_2 'для взятия аптечек
Dim As Integer hWave_3,hSound_3 'для вреда от препятствий
Dim PlayTime As Integer = 0 'переменная для начала времени проигрывания звука

' Объекты WorldSim3D
DIM MazeMesh as wMesh
DIM MazeNode as wNode
Dim MazeTexture As wTexture
DIM Camera as wCamera
DIM CameraNode as wNode
DIM MapCollision as wSelector
Dim FloorCollision As wSelector
DIM BitmapFont as wFont
DIM Collision_anim as wSelector
DIM Collision_floor_anim as wSelector
DIM KeyEvent as wKEY_EVENT PTR
DIM MouseEvent as wMOUSE_EVENT Ptr
DIM Light as wNode
DIM SkyBox as wNode
DIM Anim_Powerup as wAnimator
DIM Anim_Obstacle as wAnimator
Dim Anim_FirstAid (1 To 3) As wAnimator
DIM Anim_Start as wAnimator
DIM Anim_Finish as wAnimator

Dim FloorMesh As wMesh
Dim FloorNode As wNode
Dim FloorTexture As wTexture

DIM PowerupMesh as wMesh
DIM PowerupNode (1 To 3) as wNode
Dim PowerupTexture As wTexture
Dim i As Integer

DIM ObstacleMesh as wMesh
DIM ObstacleNode (1 To 3) as wNode
Dim j As Integer

DIM FirstAidMesh as wMesh
DIM FirstAidNode (1 To 3) as wNode
Dim FirstAidTexture As wTexture
Dim k As Integer
Dim DeleteAnimatorAid As wAnimator
Dim a As Integer = 1 ' флаг для определения того, до какой аптечки нужно просчитывать
' расстояние. 1,2 или 3 - соответственно для 1-й, 2-й или 3-й; 0 - ни до какой. Вначале
' флаг установлен на 1, т.е. 1-я аптечка от старта.


Dim StartMesh As wMesh
Dim StartNode As wNode
Dim FinishMesh As wMesh
Dim FinishNode As wNode

' Текстуры для индикатора здоровья
Dim Health_bar as wTexture   ' для чёрного фона индикатора
Dim Health_point as wTexture ' для уровня (красный цвет)

' Текстура для прицела
Dim CrossHair As wTexture

Dim As Single XPosition, YPosition, ZPosition 'положение камеры
DIM XPOS as single
DIM YPOS as single
DIM ZPOS as Single

Dim health As single = 100 ' уровень здоровья игрока, в начале 100
Dim distance_aid_1 As Single ' расстояние между камерой и аптечкой 1 (ближайшая к старту)
Dim distance_aid_2 As Single ' расстояние между камерой и аптечкой 2
Dim distance_aid_3 As Single ' расстояние между камерой и аптечкой 3

Dim distance_obs (1 To 3) As Single ' расстояние между камерой и 3-мя препятствиями
Dim b As Integer ' счётчик для цикла проверки расстояния до препятствий

Dim distance_start As Single ' расстояние до входа в лабиринт (Старт)
Dim start As Integer = 0' флаг для проверки, подошёл ли игрок к входу в лабиринт (Старту)

DIM keyMapArray(0 To 4) as SKeyMap ' массив для переопределения клавиш упрвления ФПС-камерой

' =============================================================================================
' Запускаем интерфейс WorldSim3D
' Сцена будет отображаться через рендер OPENGL.
' Установим окно шириной и высотой 800 х 600 пикселей.
' Число битов цвета, установленное для каждого пикселя ставим 32.
' Режим отображения окна - оконный (в противоположность полноэкранному).
' Включим отображение теней.
' Приложение будет реагировать на события от мыши и клавиатуры.
' Синхронизация по вертикали (для сглаживания отображения) в режиме "включено" (по умолчанию отключено)
wStart( wDT_OPENGL, 800, 600, wBITS_PER_PIXEL_32,_
          wWINDOWED, wSHADOWS, wCAPTURE_EVENTS, wVERTICAL_SYNC_ON )

' ++++++++++++++++++  ПЕРВОНАЧАЛЬНЫЕ НАСТРОЙКИ ПРОЕКТА  ++++++++++++++++++++++++++++++++++

' Устанавливаем текст заголовка окна приложения
wSetWindowCaption( "Template: simple game" )

' ------------------  ИНИЦИАЛИЗАЦИЯ РАБОТЫ ЗВУКОВ  ---------------------------------------
'
Dim Sounds As FBSBOOLEAN
Sounds = fbs_Init(48000) ' инициализируем работу библиотеки FBSound
if Sounds = false then
  ? "error: fbs_Init() !"
  ? FBS_Get_PlugError()
  beep:sleep:end 1
end if

' загружаем файл звука для фоновой музыки
Sounds = fbs_Load_WAVFile ("../Media/Template/Island_Fever.wav",@hWave)
if Sounds = false then
  ? "error: fbs_Load_OGGFile() !"
  beep:sleep:end 1
end If
' создаём звук для фоновой музыки для работы со всеми возможностями библиотеки FBSound
fbs_Create_Sound (hWave,@hSound)

' загружаем файл звука для звука, когда игрок получает здоровье,т.е. берёт аптечку
Sounds = fbs_Load_MP3File ("../Media/Template/health_up.mp3",@hWave_2)
if Sounds = false then
  ? "error: fbs_Load_OGGFile() !"
  beep:sleep:end 1
end If
' создаём звук для фоновой музыки для работы со всеми возможностями библиотеки FBSound
fbs_Create_Sound (hWave_2,@hSound_2)

' загружаем файл звука для звука, когда игрок получает здоровье,т.е. берёт аптечку
Sounds = fbs_Load_MP3File ("../Media/Template/Damage.mp3",@hWave_3)
if Sounds = false then
  ? "error: fbs_Load_OGGFile() !"
  beep:sleep:end 1
end If
' создаём звук для фоновой музыки для работы со всеми возможностями библиотеки FBSound
fbs_Create_Sound (hWave_3,@hSound_3)


' загружаем нужный шрифт из папки ресурсов через функцию wGetFont
' Шрифты можно загружать напрямую, например, так: BitmapFont = wGetFont ( "../Media/Fonts/1.png" ),
' а можно через xml, как здесь я сделал. Преимущество загрузки через xml в том, что можно
' сделать шрифт с поддержкой кириллицы через инструмент WS3D Font Tool.
BitmapFont = wGetFont ( "../Media/Template/1.xml" )

' ------- ЗАГРУЗКА ИГРОВЫХ ОБЪЕКТОВ НА СЦЕНУ ----------------------------
' Загрузку игровых объектов (3d моделей, частиц, скайбоксов и др.) на сцену можно сделать
' 2-мя способами: 1) программно, т.е. пользуясь функциями WorldSim3D; 2) предварительно
' сделав сцену (т.е. уровень или карту) в редакторе сцены и сохранив её в файл, а затем
' воспользоваться функцией wLoadScene, загрузив сцену через сохранённый файл сцены. Первым
' способом можно пользоваться, когда объектов на сцене немного и соответственно 2-й способ
' подходит тогда, когда объектов на сцене много и их удобно сначала расставить на сцене с
' с помощью редактора сцены.
' --------------------------
' Давайте здесь воспользуемся 1-м способом, чтобы начинающий мог понять, как вообще объекты
' загружаются на сцену, чтобы знать, как потом ими управлять.

MazeMesh = wGetMesh( "../Media/Template/maze/Maze.x" )
MazeNode = wAddMeshToScene( MazeMesh )
wSetNodeScale ( MazeNode, 40.0,25.0,40.0 )


MazeTexture = wGetTexture( "../Media/Template/maze/10788.jpg" )
' apply a material to the node to give its surface color
wSetNodeMaterialTexture( MazeNode, MazeTexture, 0 )
wSetNodeMaterialFlag( MazeNode, wMF_LIGHTING, wON )

' Floor
FloorMesh = wGetMesh( "../Media/Models/Sci-fi_floor2.obj" )
FloorNode = wAddMeshToScene( FloorMesh )
wSetNodeScale ( FloorNode, 8.0,1.0,12.0 )
wSetNodePosition( FloorNode, 0, 0, 0 )

FloorTexture = wGetTexture( "../Media/Template/maze/4351.jpg" )
' apply a material to the node to give its surface color
wSetNodeMaterialTexture( FloorNode, FloorTexture, 0 )
wSetNodeMaterialFlag( FloorNode, wMF_LIGHTING, wON )

' Power-ups
' Разместим по лабиринту 3 пауэрапа, т.е. такие штучки, которые... (решим позже, что они делают)
' Если вам нужна тень для пауэрапа, раскомментируйте следующие 2 строки, а
' также строку ниже несколькими строчками: wAddNodeShadow( PowerupNode(i), SphereMesh)
' Тень не будет полностью соответствовать модели (она будет просто сферической),
' так как, если попытаться сделать тень точно отражающую данную модель, это
' скорее всего сильно загрузит процессор.
''' Dim SphereMesh As wMesh
''' SphereMesh = wAddSphereSceneMesh ( "Sphere", 150, 16 )
PowerupMesh = wGetMesh( "../Media/Template/Powerup.obj" )
For i = 1 To 3
PowerupNode (i) = wAddMeshToScene( PowerupMesh )
wSetNodeScale ( PowerupNode (i), 0.05,0.05,0.05 )
wSetNodeEmissiveColor ( PowerupNode (i), RGBA ( 0,125,125,0 ))
PowerupTexture = wGetTexture( "../Media/Template/Glass.jpg" )
' apply a material to the node to give its surface color
wSetNodeMaterialTexture( PowerupNode(i), PowerupTexture, 0 )
wSetNodeMaterialFlag( PowerupNode (i), wMF_LIGHTING, wON )
Anim_Powerup = wAddRotationAnimator( PowerupNode (i), 0.0, 0.2, 0.0 )
''' wAddNodeShadow( PowerupNode(i), SphereMesh)
Next i
wSetNodePosition( PowerupNode (1), -335, 15, -212 )
wSetNodePosition( PowerupNode (2), -332, 15, 340 )
wSetNodePosition( PowerupNode (3), 335, 15, -43 )


' Obstacles
' Разместим по лабиринту 3 препятствия, забирающие здоровье у игрока.
' Через них игроку нужно перепрыгивать, чтобы не потерять здоровье
ObstacleMesh = wGetMesh( "../Media/Template/Fan.obj" )
For j = 1 To 3
ObstacleNode (j) = wAddMeshToScene( ObstacleMesh )
wSetNodeScale ( ObstacleNode (j), 0.008,0.008,0.008 )
wSetNodeEmissiveColor ( ObstacleNode (j), RGBA ( 255,0,0,0 ))
wSetNodeMaterialFlag( ObstacleNode (j), wMF_LIGHTING, wON )
Anim_Obstacle = wAddRotationAnimator( ObstacleNode (j), 0.0, 0.5, 0.0 )
Next j
wSetNodePosition( ObstacleNode (1), -223, 15, 160 ) ' 15 - высота препятствия над землёй
wSetNodePosition( ObstacleNode (2), 220, 15, 107 )
wSetNodePosition( ObstacleNode (3), 102, 15, 325 )

' First-aid kits
' Разместим по лабиринту 3 аптечки, добавляющие здоровье игроку.
FirstAidMesh = wGetMesh( "../Media/Template/health.x" )
For k = 1 To 3
FirstAidNode (k) = wAddMeshToScene( FirstAidMesh )
wSetNodeScale ( FirstAidNode (k), 0.5,0.5,0.5 )
wSetNodeAmbientColor ( FirstAidNode (k), RGBA ( 255,0,0,0 ))
FirstAidTexture = wGetTexture( "../Media/Template/health.png" )
' apply a material to the node to give its surface color
wSetNodeMaterialTexture( FirstAidNode(k), FirstAidTexture, 0 )
wSetNodeMaterialFlag( FirstAidNode (k), wMF_LIGHTING, wON )
wSetNodeRotation( FirstAidNode (k), -45, 0, 0 )
Anim_FirstAid(k) = wAddRotationAnimator( FirstAidNode (k), 0.0, -0.5, 0.0 )
wAddNodeShadow( FirstAidNode (k) )
Next k
wSetNodePosition( FirstAidNode (1), 338, 12, -340 )
wSetNodePosition( FirstAidNode (2), -128, 12, 329 )
wSetNodePosition( FirstAidNode (3), 335, 12, 152 )


' Start message
StartMesh = wGetMesh( "../Media/Template/start.obj" )
StartNode = wAddMeshToScene( StartMesh )
wSetNodeScale ( StartNode, 3.0,1.0,3.0 )
wSetNodeEmissiveColor ( StartNode, RGBA ( 200,255,0,0 ))
wSetNodePosition( StartNode, -311, 20, -401 )
wSetNodeRotation( StartNode, -90, 180, 0 )
wSetNodeMaterialFlag( StartNode, wMF_LIGHTING, wON )
Anim_Start = wAddRotationAnimator( StartNode, 0.0, 0.5, 0.0 )
wAddNodeShadow( StartNode )


' Finish message
FinishMesh = wGetMesh( "../Media/Template/finish.obj" )
FinishNode = wAddMeshToScene( FinishMesh )
wSetNodeScale ( FinishNode, 0.8,0.8,0.8 )
wSetNodeAmbientColor ( FinishNode, RGBA ( 0,200,0,0 ))
wSetNodePosition( FinishNode, 15, 20, 389 )
wSetNodeMaterialFlag( FinishNode, wMF_LIGHTING, wON )
Anim_Finish = wAddRotationAnimator( FinishNode, 0.0, 0.5, 0.0 )
wAddNodeShadow( FinishNode )

' Индикатор здоровья
Health_bar = wGetTexture( "../Media/Template/Progress_backgr.png" )
Health_point = wGetTexture( "../Media/Template/Progress_indicat.png" )

' Загружаем спрайт прицела
CrossHair = wGetTexture ( "../Media/Template/crosshair.png" )

' ------------------------------ ДОБАВЛЯЕМ КАМЕРУ -----------------------------
''' ---- Изменение клавиш управления ФПС-камерой ------------------------------
' Добавим в проект камеру от 1-го лица, которой игрок будет управлять с помощью мыши и
' определённых клавиш. Вы можете определить, какими клавишами будет управляться камера.
' Здесь я поставил стандартный набор: WASD + Space (пробел). Смотрите справку, чтобы узнать,
' как в коде обозначать клавиши, например, KEY_KEY_W - это клавиша W.
keyMapArray(0).Action = KA_MOVE_FORWARD
keyMapArray(0).KeyCode = KEY_KEY_W      ' клавиша W
keyMapArray(1).Action = KA_MOVE_BACKWARD
keyMapArray(1).KeyCode = KEY_KEY_S      ' клавиша S
keyMapArray(2).Action = KA_STRAFE_LEFT
keyMapArray(2).KeyCode = KEY_KEY_A      ' клавиша A
keyMapArray(3).Action = KA_STRAFE_RIGHT
keyMapArray(3).KeyCode = KEY_KEY_D      ' клавиша W
keyMapArray(4).Action = KA_JUMP_UP
keyMapArray(4).KeyCode = KEY_SPACE      ' клавиша SPACE (пробел)

Camera = wAddFPSCamera ( _
    wNO_OBJECT, _      ' нет родительского Нода ("камера ни к чему не прицеплена")
    100.0, _           ' скорость вращения
    0.07, _            ' скорость перемещения
    -1, _              ' ID камеры
    @keyMapArray(0), _ ' адрес массива определённых для камеры клавиш (keyMap)
    5, _               ' количество клавиш в массиве определённых для камеры клавиш
    0, _               ' может ли камера перемещаться вертикально (0 - нет, 1 - да)
    1.0 )              ' скорость прыжка
'' --------------------------------------------------------------------------------------
'/
' Если вы хотите, чтобы  у вас была просто камера по умолчанию,то раскомментируйте
' следующую строку, а предыдущие, начиная с раздела "Добавляем камеру", наоборот закомментируйте.
''Camera = wAddFPSCamera( 0, 100.0, 0.07, -1,0,0, 0, 1.0 )
CameraNode = Camera
wSetNodePosition( CameraNode, -322, 25, -542 )
wSetNodeRotation( CameraNode, 357, 9, 0 )
wSetCameraClipDistance ( CameraNode, 10000 )

' ------------------ Установка физики: проверка столкновений и др. ------------
' В данном шаблоне мы будем пользоваться только встроенной в WorldSim3D (базовой) физикой
' the first thing we need to do with collision is to create an object called a
' selector that contains a selection of triangle to be used in the collision
' calculations there are a number of different ways of doing this depending on
' the type of mesh you are working with. in this example we are using the
' complex BSP map and therefore should use the following command

MapCollision = wGetCollisionGroupFromMesh( MazeMesh, MazeNode )' делаем лабиринт физическим, т.е.
' способным на проверку столкновения сдругими объектами

FloorCollision = wGetCollisionGroupFromBox ( FloorNode ) 'делаем пол физическим

' now we can add the sixth and final animator to our camera object the collision
' animator. This takes a long list of parameters that define the following:
' 1) the collision object created from the map
' 2) the node that is going to be collided against the map
' 3) 3 vaues defining the radius of the node (the camera in this case). if you
'    make this value too small you wont be able to climb steps, if its too big
'    you might get stuck in a doorway or be able to jump over a wall. the best
'    thing to do is to have some fun experimenting
' 4) 3 values defining the pull of gravity, in this case a weak downward force
' 5) finally 3 values defining the offset of the node from the collision point
'    this will enable you to bring an object to the surface

' Устанавливаем какие объекты (Ноды) должны сталкиваться между собой:
Collision_anim = wAddCollisionAnimator(_       ' проверка столкновения камеры с лабиринтом
                                MapCollision,_
                                CameraNode,_
                                10.0,10.0,10.0,_
                                0.0,0.0,0.0,_
                                0.0,0.0,0.0 )

Collision_floor_anim = wAddCollisionAnimator(_ ' проверка столкновения камеры с полом
                                FloorCollision,_
                                CameraNode,_
                                10.0,10.0,10.0,_
                                0.0,-2.0,0.0,_
                                0.0,10.0,0.0 )
' ---------------------------------------------------------------------------------

' hide the mouse pointer
wHideMouse

' Загрузим небесный купол (скайбокс)
' the skybox is a simple hollow cube that surrounds the whole scene. textures
' are applied to all of the six sides of the cube creating an image around the
' entire scene instead of simply the color of the blank canvas
' here we load the textures as parameters of the skybox command (they could
' of course be loaded seperatly and assigned to wTexture variables
SkyBox = wAddSkyBoxToScene( _
        wGetTexture("../media/SkyBoxes/Trivial/Skybox_up.jpg"),_
        wGetTexture("../media/SkyBoxes/Trivial/Skybox_dn.jpg"),_
        wGetTexture("../media/SkyBoxes/Trivial/Skybox_rt.jpg"),_
        wGetTexture("../media/SkyBoxes/Trivial/Skybox_lf.jpg"),_
        wGetTexture("../media/SkyBoxes/Trivial/Skybox_ft.jpg"),_
        wGetTexture("../media/SkyBoxes/Trivial/Skybox_bk.jpg"))
       
' добавим в проект яркий рассеянный свет, освещающий всё вокруг
' 3 значения - это красный, зелёный, синий. Они менются от 0.0 до 1.0
wSetAmbientLight ( 1, 1, 1 )
' также добавим напрвленный свет, чтобы были тени
Light = wAddLight( wNO_PARENT, 200, 400, -400, 0.9,0.9,0.9, 1000.0 )

' -----------------------------------------------------------------------------
'******************************************************************************
'----------------------- ГЛАВНЫЙ ЦИКЛ ВАШЕГО ПРОЕКТА --------------------------
' здесь главный цикл приложения, поэтому
' мы устанавливаем цикл с условием: пока движок работает (функция wRunning)
' внутри цикла постоянно выполняются определённые команды, в основном для отображения сцены
While wRunning
        ' начинаем отрисовку сцены с цветом фона, например зелёный (который устанавливаем числами 0,125,0)
        wBeginScene( 0, 125, 0 )
        wGetNodeRotation( CameraNode, XPOS, YPOS, ZPOS )
     
      ' сделаем так, чтобы игра начиналась, когда игрок подойдёт ко входу в лабиринт, т.е.
      ' станет близко к вращающемуся "Старту"; тогда и начнёт его здоровье уменьшаться.
      If start = 0 Then
      distance_start = wGetDistanceBetweenNodes ( StartNode, CameraNode ) - 20
      If distance_start > 0 And distance_start < 25 Then start = 1
      End If
     
' СДЕЛАЕМ УМЕНЬШЕНИЕ ЗДОРОВЬЯ
' Пока уровень здоровья больше нуля, оно уменьшается
If start = 1 Then
      If health > 0 And health < 101 Then
      ' здоровье уменьшается на 0.03 каждую 1/60 секунду (т.е. уменьшается на 1,8 пункта каждую секунду)
      health = health - 0.03
      ElseIf health > 100 Then ' если вдруг здоровье станет больше 100, пусть будет равно 100
      health = 100
      Else health = 0 ' если здоровье равно нулю, т.е. меньше одного, то установим значение здоровья на ноль
      ' здесь нужно написать код, показывающий, что игрок проиграл (сделаем позже)
      EndIf
End If
      ' ПРОВЕРКА РАССТОЯНИЯ ДО АПТЕЧЕК. Если игрок приблизился к одной из аптечек
      ' меньше чем на 1 метр, то здоровье прибавляем на определённое количество единиц,
      ' а эту аптечку убираем со сцены.
      ' Для определения расстояний воспользуемся функцией wGetDistanceBetweenNodes.
      ' Эта функция определяет расстояние от центра одного нода до центра другого.
      ' Это нужно учитывать. Например, радиус одного Нода может быть 8 метров, а другого -
      ' 2 метра, тогда сумму их радиусов (8+2=10) нужно вычесть из значения расстояния,
      ' полученного через функцию wGetDistanceBetweenNodes.
      ' Я протестировал и, в данном случае получилось 10 метров. Поэтому мы просто учтём
      ' эту разницу, отнимая от расстояния 10 метров и всё будет хорошо.
      ' Чтобы не усложнять, в данном шаблоне сделаем так, что игрок должен брать аптечки
      ' по порядку - от ближайшей к старту до самой дальней от старта, т.е. по мере того,
      ' как он приближается к финишу. Уровень здоровья и его уменьшение установим так, что
      ' если он не лечится очередной по порядку аптечкой, то ему не хватит здоровья добежать
      ' до финиша. Использованную аптечку будем убирать со сцены с помощью функции wAddDeleteAnimator.
      '
      ' Так как у нас 3 аптечки, сделаем для каждой из них проверку расстояния с камерой,
      ' т.е. с игроком.
     
      ' расстояние между камерой и 1-й аптечкой на пути от Старта к Финишу:
      ' a - это флаг, соответствующий номеру аптечки
      If a = 1 Then
      distance_aid_1 = wGetDistanceBetweenNodes ( FirstAidNode (1), CameraNode ) - 10
      ' если расстояние больше нуля, но меньше 2, то:
      If distance_aid_1 > 0 And distance_aid_1 < 1 Then
      ' убираем эту аптечку (её Нод) со сцены; 5 означает 5 миллисекунд, через которые
      ' аптечка исчезнет (1 миллисекунда - 1/1000 секунды)
      DeleteAnimatorAid = wAddDeleteAnimator ( FirstAidNode (1), 5 )
      a = 2 ' переключаем флаг на 2, чтобы просчитывалось расстояние до следующей (2-й) аптечки
      health = health + 20 ' прибавим к здоровью 20 пунктов (или сколько? ... должно быть в вашей игре)
      fbs_Play_Sound (hSound_2, 1) ' Воспроизводим загруженный и созданный звук увеличения здоровья
      ' 1 означает проиграть его 1 раз
      EndIf
      EndIf
     
      ' расстояние между камерой и 2-й аптечкой на пути от Старта к Финишу:
      If a = 2 Then
      distance_aid_2 = wGetDistanceBetweenNodes ( FirstAidNode (2), CameraNode ) - 10
      If distance_aid_2 > 0 And distance_aid_2 < 1 Then
      DeleteAnimatorAid = wAddDeleteAnimator ( FirstAidNode (2), 5 )
      a = 3 ' переключаем флаг на 3, чтобы просчитывалось расстояние до следующей (3-й) аптечки
      health = health + 20
      fbs_Play_Sound (hSound_2, 1) ' Воспроизводим загруженный и созданный звук увеличения здоровья
      ' 1 означает проиграть его 1 раз
      EndIf
      EndIf
     
      ' расстояние между камерой и 3-й аптечкой на пути от Старта к Финишу:
      If a = 3 Then
      distance_aid_3 = wGetDistanceBetweenNodes ( FirstAidNode (3), CameraNode ) - 10
      If distance_aid_3 > 0 And distance_aid_3 < 1 Then
      DeleteAnimatorAid = wAddDeleteAnimator ( FirstAidNode (3), 5 )
      a = 0 ' переключаем флаг на 0, чтобы расстояние больше не просчитывалось, т.к. аптечки закончились
      health = health + 20
      fbs_Play_Sound (hSound_2, 1) ' Воспроизводим загруженный и созданный звук увеличения здоровья
      ' 1 означает проиграть его 1 раз
      EndIf
      EndIf
     
      ' ПРОВЕРКА РАССТОЯНИЯ ДО ПРЕПЯТСТВИЙ. Если игрок неперепрыгнет препятствие, то
      ' потеряет часть здоровья. Для этого нужноснова сделать проверку расстояния от
      ' камеры до препятствия. Для определения расстояний снова воспользуемся функцией
      ' wGetDistanceBetweenNodes. Здесь учтём сумму радиусов нодов - 20.
      '
      ' Сделаем цикл из 3-х расстояний для 3-х препятствий
      '
      For b = 1 To 3
      distance_obs (b) = wGetDistanceBetweenNodes ( ObstacleNode (b), CameraNode ) - 20
      Next
      ' при инициализации переменной distance_obs она равна нулю, поэтому в начале игры будет
      ' срабатывать звук вреда от препятствия, но мы этого не хотим, поэтому предотвратим след. строкой
      ' Если расстояние до одного из препятствий больше 0, то
      If distance_obs (1) > 0 Or distance_obs (2) > 0 Or distance_obs (3) > 0 Then
      'и если расстояние до одного из препятствий станет меньше 1, то
      If distance_obs (1) < 1 Or distance_obs (2) < 1 Or distance_obs (3) < 1 Then
      ' отнимаем много здоровья - 0.5 за 1/60 сек., т.е. 30 пунктов за 1 секунду,
      ' так что игроку, хочешь не хочешь, придётся перепрыгивать через препятствие,
      ' и при этом рассчитывать прыжок, чтобы сохранить здоровье.
      health = health - 0.5
      fbs_Play_Sound (hSound_3, 1) ' Воспроизводим загруженный и созданный звук уменьшения здоровья
      ' 1 означает проиграть его 1 раз
      EndIf
      End if
     
   ' задаём момент времени, когда начать проигрывать звук
   If PlayTime = 1 Then ' начинаем проигрывать на 1-й миллисекунде работы цикла
    fbs_Play_Sound (hSound,10) ' Воспроизводим загруженный и созданный звук
    ' 10 означает сколько раз проиграть звук
   EndIf
    PlayTime +=1 'запускаем работу цикла
   
   
        ' если события клавиатуры могут быть обработаны, то:
        while wKeyEventAvailable
   
            ' читаем события клавиатуры. the key event has three parameters the key
            ' scan code, the direction of the key and flags that indicate whether
            ' the control key or the shift keys were also pressed
            KeyEvent = wReadKeyEvent
   
            ' если нажата какая-либо клавиша, связываем с ней событие, оторое мы хотим
            ' чтобы оно произошло. Это может быть что угодно:
            select case as const KeyEvent->key
            case KEY_KEY_D     ' Left Arrow
                ' if the key is going down
                if KeyEvent->direction = wKEY_DOWN then
                   
                else
                   
                endif
   
            case KEY_KEY_W     ' Up Arrow
                ' if the key is going down
                if KeyEvent->direction = wKEY_DOWN then
                   
                else
                   
                endif
                   
            case KEY_KEY_A     ' Right Arrow
                ' if the key is going down
                if KeyEvent->direction = wKEY_DOWN then
                   
                else
                   
                endif
                   
            case KEY_KEY_S     ' Down Arrow
                ' if the key is going down
                if KeyEvent->direction = wKEY_DOWN then
                   
                else
                   
                endif
            ' Добавим функцию для закрытия окна через клавишу ESCAPE.
    ' Если клавиатура не исчпользуется, то для этой цели нужно использовать
    ' другую функцию - wCloseESC(), которую можно поместить в конце главного цикла.
    wCloseKEY_ESC()
            end Select
        Wend

        ' while there are mouse events waiting
        while wMouseEventAvailable
            ' read the mouse event out
            MouseEvent = wReadMouseEvent
   
            ' if this is a mouse move event
            if MouseEvent->action = wME_MOUSE_MOVED then
   
            endif
   
        wend
         
        ' отрисовка сцены
        wDrawScene
       
        ' Работа графического индикатора
        wDraw2DImageElement( Health_bar, 660, 80, 0,0,100,20, wUSE_ALPHA )  'отображаем фон индикатора
        wDrawSpriteAdvanced(Health_point, 661, 81, health, 1, wUSE_ALPHA, 1)'отображаем уровень здоровья на индикаторе
       
        ' Отображаем прицел. Чтобы он был ровно посередине экрана, нужно ширину и высоту
        ' окна разделить на 2 и вычесть ширину и высоту спрайта соответственно.
        ' Если прицел вам не нужен, просто закомментируйте эту строку.
        wDrawSpriteAdvanced(CrossHair, 368, 268, 1, 1, wUSE_ALPHA, 1)

  ' отображаем на экране загруженный ранее шрифт
  ' последние 4 числа - координаты текста: X,Y левого верхнего угла и X,Y правого нижнего угла
      w2DFontDraw ( BitmapFont, "Нажимайте W,A,S,D, чтобы передвигаться по лабиринту и SPACE чтобы прыгать", 60, 570, 500, 590 )
       
        ' отладочная информация: положение и ориентация камеры
        ''w2DFontDraw ( BitmapFont, Str(XPosition)+ "   "+ Str(YPosition) +"   "+ Str(ZPosition), 10, 10, 250, 15 )
        ''w2DFontDraw ( BitmapFont, Str(XPOS)+ "   "+ Str(YPOS) +"   "+ Str(ZPOS), 10, 30, 250, 45 )
  ' числовой индикатор здоровья (также сделаем графический позже)
        w2DFontDraw ( BitmapFont, "Здоровье: " + Str(CInt(health)), 655, 40, 800, 55 )

   
        ' заканчиваем отрисовку сцены и отображаем её
        wEndScene
        wGetNodePosition ( CameraNode, XPosition, YPosition, ZPosition )


        wSetFPS   'устанавливаем фреймрейт по умолчанию 60 кадров в секунду
Wend
' -----------------------КОНЕЦ ГЛАВНОГО ЦИКЛА ВАШЕГО ПРОЕКТА ------------------
'******************************************************************************

' -----------------------------------------------------------------------------
' Останавливаем работу движка и высвобождаем ресурсы памяти
wStop
« Last Edit: January 01, 2015, 01:36:59 PM by Alec - WS3D Developer »
WorldSim3D = 3D + FreeBasic. Программируй в удовольствие, а не "в тягость"! Make your project with pleasure, not with strain!

Offline Alec - WS3D Developer

  • Producer
  • Administrator
  • Marquess
  • *
  • Posts: 910
  • Reputation 36
  • Game making is my hobby for life!
Re: Анонс: шаблон игры для новичка
« Reply #1 on: December 21, 2014, 10:17:24 PM »
В общем-то, шаблон почти готов. Можно сказать версия 0.1.  :)

Я взял модель лабиринта (коих много на https://3dwarehouse.sketchup.com/), экспортировал её в x и загрузил в движок. Сделал базовую физику для перемещения ФПС-камеры по этому лабиринту. Ещё придумаю, что можно такого игрового сделать, чтобы это было похоже на игру. Не хочется пока привязывать к какому-либо жанру игры, поэтому думаю, просто сделаю что-то совсем простое - цель: выйти из лабиринта за минимально короткое время. Может быть на пути игрока расставлю препятствия и т.п.
« Last Edit: December 24, 2014, 12:05:36 AM by Alec - WS3D Developer »
WorldSim3D = 3D + FreeBasic. Программируй в удовольствие, а не "в тягость"! Make your project with pleasure, not with strain!

Offline yood19

  • Knight
  • *
  • Posts: 105
  • Reputation 6
  • Maxim Cheban
Re: Анонс: шаблон игры для новичка
« Reply #2 on: December 23, 2014, 08:28:51 PM »
Ждать осталось не долго...
Programming is great

Offline Alec - WS3D Developer

  • Producer
  • Administrator
  • Marquess
  • *
  • Posts: 910
  • Reputation 36
  • Game making is my hobby for life!
Re: Анонс: шаблон игры для новичка
« Reply #3 on: December 23, 2014, 08:50:13 PM »
Ты прав.  :)
Версия 0.5.
WorldSim3D = 3D + FreeBasic. Программируй в удовольствие, а не "в тягость"! Make your project with pleasure, not with strain!

Offline Nikolas - WS3D Developer

  • Programmer
  • Global Moderator
  • Marquess
  • *
  • Posts: 888
  • Reputation 63
Re: Анонс: шаблон игры для новичка
« Reply #4 on: December 23, 2014, 10:16:14 PM »
По-моему, это сверхзадача для сверхчеловеков. Сделать шаблон универсальным очень трудно, да и нужен ли?
В свое время был такой движок-конструктор, который предлагал подобное:
Code: [Select]
http://gcup.ru/load/konstruktory_igr/3d_game_maker/2-1-0-2Правда, не юзал.  Ну что-ж, интересно, что будет далее.  ;D :D ::)
Под лежачий камень мы всегда успеем...

Offline Alec - WS3D Developer

  • Producer
  • Administrator
  • Marquess
  • *
  • Posts: 910
  • Reputation 36
  • Game making is my hobby for life!
Re: Анонс: шаблон игры для новичка
« Reply #5 on: December 23, 2014, 11:14:04 PM »
Quote
По-моему, это сверхзадача для сверхчеловеков. Сделать шаблон универсальным очень трудно
Трудно, конечно. Поэтому есть планы сделать несколько шаблонов по разным жанрам и типам игр.

Но кое-что всё же можно сделать. Шаблон, который сейчас делаю, по жанру просто казуалка. На даный момент сделал карту - загрузил модели: небольшой лабиринт, пол, пауэрапы, препятствия и сообщения Start и Finish.
Сейчас выложу, что сделал (не 0.5 конечно, но основа уже есть).  :)
WorldSim3D = 3D + FreeBasic. Программируй в удовольствие, а не "в тягость"! Make your project with pleasure, not with strain!

Offline Alec - WS3D Developer

  • Producer
  • Administrator
  • Marquess
  • *
  • Posts: 910
  • Reputation 36
  • Game making is my hobby for life!
Re: Анонс: шаблон игры для новичка
« Reply #6 on: December 23, 2014, 11:48:01 PM »
Папку с дополнительными ресурсами сейчас залью.
WorldSim3D = 3D + FreeBasic. Программируй в удовольствие, а не "в тягость"! Make your project with pleasure, not with strain!

Offline Nikolas - WS3D Developer

  • Programmer
  • Global Moderator
  • Marquess
  • *
  • Posts: 888
  • Reputation 63
Re: Анонс: шаблон игры для новичка
« Reply #7 on: December 24, 2014, 12:24:02 AM »
Ну что-ж, очень даже gut. Понравилось.
Подправь всюду media на Media в путях текстур (линукс не прощает, выдает segmentation fault).
Я бы, наверное, добавил бы еще что-то вроде прицела в центре экрана.
Еще: для вывода числовых данных хватило бы и integer.
Прыжок с  J  все таки на ПРОБЕЛ, но это дело привычки....
Ну, и моя трабла: звук FBSOUND все таки не робит, пришлось закомментировать.
Можно сделать шрифт с кириллицей, будет привлекательней для новичков.
При достижении Finish можно сделать выход с уровня или загрузку нового.
С аптечками, наверное, потом сделаешь? Добавление здоровья или наоборот  :D

Удачи в продолжении работ!
« Last Edit: December 24, 2014, 12:31:51 AM by nikolas »
Под лежачий камень мы всегда успеем...

Offline Alec - WS3D Developer

  • Producer
  • Administrator
  • Marquess
  • *
  • Posts: 910
  • Reputation 36
  • Game making is my hobby for life!
Re: Анонс: шаблон игры для новичка
« Reply #8 on: December 24, 2014, 06:07:20 PM »
Quote
Подправь всюду media на Media в путях текстур
Хорошо. Забыл про это.

Quote
еще что-то вроде прицела в центре экрана
Добавлю как вариант, и возможно закомментирую. А то прицел сразу вызывает ассоциацию со стрелялкой. А для шутеров я хочу отдельный шаблон сделать. Может кто раньше меня возьмётся и сделает?  :)

Quote
для вывода числовых данных хватило бы и integer.
В общем-то, да. Single объявляю просто как в объявлениях функций. Но для оптимизации можно и integer.

Quote
звук FBSOUND все таки не робит, пришлось закомментировать.
А какая у тебя звуковая карта?

Quote
Можно сделать шрифт с кириллицей, будет привлекательней для новичков.
Хорошая мысль.

Quote
При достижении Finish можно сделать выход с уровня или загрузку нового.
Воплощу.  :)

Quote
С аптечками, наверное, потом сделаешь? Добавление здоровья или наоборот
Добавил аптечки. И исправил: пауэрапы будут добавлять скорости, а аптечки здоровья.
WorldSim3D = 3D + FreeBasic. Программируй в удовольствие, а не "в тягость"! Make your project with pleasure, not with strain!

Offline Alec - WS3D Developer

  • Producer
  • Administrator
  • Marquess
  • *
  • Posts: 910
  • Reputation 36
  • Game making is my hobby for life!
Re: Шаблон игры для новичка
« Reply #9 on: December 24, 2014, 09:21:12 PM »
Новая версия - 0.45, смотрите шапку.
« Last Edit: December 24, 2014, 10:46:57 PM by Alec - WS3D Developer »
WorldSim3D = 3D + FreeBasic. Программируй в удовольствие, а не "в тягость"! Make your project with pleasure, not with strain!

Offline Alec - WS3D Developer

  • Producer
  • Administrator
  • Marquess
  • *
  • Posts: 910
  • Reputation 36
  • Game making is my hobby for life!
Re: Шаблон игры для новичка
« Reply #10 on: December 25, 2014, 08:45:56 AM »
Приступил к написанию, собственно, взаимодействия игровых элементов.
В планахбыло сделатьувеличение скорости, когда берёшь пауэрап, но с простой ФПС-камерой это неполучится, по крайней мере простым способом, понятным новичку. Поэтому от этой фичи придётся отказаться. Но, можно что-то придумать вместо этого.

В 1-ю очередь сделаю уменьшение/увеличение здоровья.

Попробовал поменять single на integer, естественно, как я  предполагал выдаёт ошибку несоответствия типов. Это можно исправить, если перед значением поставить функцию ФБ для конвертации типов, но тогда зачем вообще конвертировать. Решил оставить single, тем более это отладочная инфа в казуальной игре. А вот в космосимах положение и ориентация в пространстве обычно нужна, но там просто можно "обрезать" ненужное число знаков после запятой (точки) с помощью функций ФБ.

Кстати, если кто-то хочет посмотреть как выглядит игровая сцена сверху и попарить над ней, просто закомментируйте часть кода, где физика (если кто-то не знает как закомментировать большую часть кода, напомню: /' ваш код  '/  ).
« Last Edit: December 25, 2014, 08:47:54 AM by Alec - WS3D Developer »
WorldSim3D = 3D + FreeBasic. Программируй в удовольствие, а не "в тягость"! Make your project with pleasure, not with strain!

Offline Alec - WS3D Developer

  • Producer
  • Administrator
  • Marquess
  • *
  • Posts: 910
  • Reputation 36
  • Game making is my hobby for life!
Re: Шаблон игры для новичка
« Reply #11 on: December 26, 2014, 03:36:26 PM »
Добавлена версия 0.53. Смотрите шапку. Код, естественно, обновлён.
WorldSim3D = 3D + FreeBasic. Программируй в удовольствие, а не "в тягость"! Make your project with pleasure, not with strain!

Offline Alec - WS3D Developer

  • Producer
  • Administrator
  • Marquess
  • *
  • Posts: 910
  • Reputation 36
  • Game making is my hobby for life!
Re: Шаблон игры для новичка
« Reply #12 on: December 27, 2014, 09:37:38 AM »
Версия 0.60. Главная фича - проверка расстояния до препятствий и значительная потеря здоровья, если их не перепрыгивать.

Идёт работа уже и над другими фичами!
WorldSim3D = 3D + FreeBasic. Программируй в удовольствие, а не "в тягость"! Make your project with pleasure, not with strain!

Offline Alec - WS3D Developer

  • Producer
  • Administrator
  • Marquess
  • *
  • Posts: 910
  • Reputation 36
  • Game making is my hobby for life!
Re: Шаблон игры для новичка
« Reply #13 on: December 28, 2014, 03:04:57 PM »
Версия 0.62. Две фичи, в т.ч. переопределение клавиш для ФПС-камеры. Смотрите шапку.
Управление камерой изменилось (но вы можете вернуть прежнее, смотрите комментарии в коде) - W,A,S,D + SPACE (прыжок).

Сделайте свою игру и порадуйте народ!
WorldSim3D = 3D + FreeBasic. Программируй в удовольствие, а не "в тягость"! Make your project with pleasure, not with strain!

Offline Nikolas - WS3D Developer

  • Programmer
  • Global Moderator
  • Marquess
  • *
  • Posts: 888
  • Reputation 63
Re: Шаблон игры для новичка
« Reply #14 on: December 28, 2014, 04:29:13 PM »
Code: [Select]
Управление камерой изменилось (но вы можете вернуть прежнее, смотрите комментарии в коде) - W,A,S,D + SPACE (прыжок).Воооот, это уже интересней. Так привичней для большинства будет.
Под лежачий камень мы всегда успеем...