IPB

Здравствуйте, гость ( Вход | Регистрация )

2 страниц V   1 2 >  
Ответить в данную темуНачать новую тему
DarkBasicPro 2D Tutorial(урок), Простенький урок, "2d (спрайты)" игра The Bugs Killer
Vova
сообщение 16.9.2010, 14:54
Сообщение #1


Активный участник
***

Группа: Пользователи
Сообщений: 569
Регистрация: 27.8.2009
Из: Москва
Пользователь №: 65609



В посл время меня сильно огорчает ситуация которая сложилась вокруг инфы и тутов по ДБп, этим постом я надеюсь поделиться своими знаниями...
Я не говорю что я знаю все и что мой код идеален для меня он работает, если у Вас возникли проблемы с ним, можно смело задавать вопрос тут на форуме либо мне на почту(ПМ)
Я надеюсь моему примеру последуют и другие участники форума и несмотря на то, что у большинства уже есть семья, работа и другие проблемы смогут отыскать время и написание на основе небольшого примере \"не сложных игр\" урок на понятном всем нам языке!


К сожалению я не смогу выложить все разом по этому буду выкладывать частями, по этому следите за данным постом(если вы читаете это на форуме) или разделом моего сайта...

И так начинаем.

Название игры
The Bugs Killer


Краткое описание:
2д шутер от первого лица ( wink.gif )
Целимся мышкой в жука и click...жук мертв...
Цель игры:
Убить как можно больше жучков за определенный отрезок времени

Что нам понадобиться для создания игры(инструментарий):
DarkBasic professional версии 7.4 или выше
Всю необходимую медиа(картинки) я поместил чуть ниже в этом сообщение..
Если у кого то есть желание изменить графику в игре можно использовать paint.net очень удобная и не просит денег

Часть 1.

Создайте пустой проект в DBp Editor, назовите его TheBugsKillerTUT01 (или тем именем которое более всего нравиться Вам.)
В поле Editora Вы увидите следующее

Код
Rem Project: TheBugsKillerTUT01
Rem Created: Thursday, September 16, 2010

Rem ***** Main Source File *****


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

Следующим шагом нам необходимо задать параметры окна будущей игры.
set display mode 800,600,32
Где 800 - это ширина окна, 600 - высота , 32 - глубина цвета.
Теперь нам необходимо установить частоту обновления экрана.
Задается это командами
sync on
sync rate 60
Далее мы знаем, что курсор мыши нам не понадобиться т.к. мы его заменим нашим собственным значит убираем курсор командой
hide mouse
Теперь надо добавить основной цикл и посмотреть что у нас вышло
DO - начало цикла
sync - синхронизация
LOOP - конец цикла
И так получаем следующее
Код
set display mode 800,600,32
sync on
sync rate 60
hide mouse


DO
    sync
LOOP


Синие окно размеров 800 на 600

Конец первой части cool.gif

Если у Вас есть чем поделиться или что добавить(поправить меня) милости прошу!!!

Прикрепленное изображение

Прикрепленное изображение

Для тех кто хочет посмотреть, что из этого получилось финальный код игры (без дополнений) :
CODE

Rem Project: TheBugsKillerTUT01
Rem Created: Thursday, September 16, 2010

Rem ***** Main Source File *****

set display mode 800,600,32
Sync on
Sync rate 60
hide mouse
disable escapekey

Goto _startscreanloop

_gameLoad:

If initPass = 1 then Goto _gameLoop

create animated sprite 1,"Media\Bug.png",4,1,1
sprite 1,rndx(64,600),rndx(64,500),1
SET SPRITE FRAME 1 , 4
OffSetSprite_to_M(1)

load image "Media\curs.png",2
sprite 2,300,400,2
OffSetSprite_to_M(2)

initPass = 1

_gameLoop:

spriteMoveSpeed# = 0.3
Score = 0
BugsKilled = 0
Time = timer()
GameTime = 0
show sprite 1
show sprite 2
DO


If escapekey()=1 then Goto _scroteloop

If sprite collision(2,1)> 0
If mouseclick()=1
If click = 0
Score = Score + 100
BugsKilled = BugsKilled + 1
n = n + 3
clone sprite 1,n
SET SPRITE FRAME n , 4
sprite n,sprite x(1),sprite y(1),1
sprite 1,rndx(64,600),rndx(64,500),1
ROTATE SPRITE 1, rnd(360)
click = 1
EndIf
Else
click = 0
EndIf
EndIf

If sprite x(1) < 0 or sprite y(1) < 0 or sprite x(1) > 800 or sprite y(1) > 600
sprite 1,rndx(64,600),rndx(64,500),1
ROTATE SPRITE 1, rnd(360)
Score = Score - 50
EndIf

If GameTime > 30000
Goto _scroteloop
EndIf

If GameTime > 10000
spriteMoveSpeed# = 0.6
EndIf

play sprite 1,1,3,300
MOVE SPRITE 1, spriteMoveSpeed#

text 10,10, "Очки : " + str$(Score) + " $"
text 10,30, "Время игры :" + str$(GameTime/1000)

GameTime = abs( Time - timer() )

sprite 2,aimX,aimY,2
aimX = mouseX()
aimY = mouseY()

Sync
LOOP

Function OffSetSprite_to_M(spriteOffSet)
Offset Sprite spriteOffSet,sprite width(spriteOffSet)/2,sprite height(spriteOffSet)/2
EndFunction

function rndx(min,max)
value=rnd(max-min)+min
endfunction value

_scroteloop:
tupESC = 1
HIDE ALL SPRITES
DO

text 150,150, "Очки : " + str$(Score) + " $"
text 150,170, "Всего жуков убито :" + str$(BugsKilled)
text 150,190, "Для перезапуска игры жми пробел."

If spacekey()=1 then goto _gameLoop

If escapekey()=1
If tupESC = 0
goto _startscreanloop
tupESC = 1
EndIf
Else
tupESC = 0
EndIf

Sync
LOOP

_startscreanloop:

HIDE ALL SPRITES
newgameFlag = 1
DO
SET TEXT SIZE 50
INK RGB(255,rnd(255),rnd(255)),RGB(255,255,255)
text SCREEN WIDTH()/2,SCREEN HEIGHT()/2, "The Bugs Killer"

If newgameFlag = 1
SET TEXT SIZE 12
INK RGB(rnd(255),rnd(255),rnd(255)),RGB(255,255,255)
text 150,150, "Начать игру"
INK RGB(150,150,150),RGB(255,255,255)
text 150,170, "Выход"
If spacekey()=1 then goto _gameLoad
EndIf

If newgameFlag = 0
SET TEXT SIZE 12
INK RGB(150,150,150),RGB(255,255,255)
text 150,150, "Начать игру"
INK RGB(rnd(255),rnd(255),rnd(255)),RGB(255,255,255)
text 150,170, "Выход"
If spacekey()=1 then end
EndIf

If upkey()=1 then newgameFlag = 1
If downkey()=1 then newgameFlag = 0

Sync
LOOP



The Bugs Killer Часть 2.


tongue.gif И так в первой части нашего урока мы успешно создали основной цикл игры и немного настроили будущую игру задав параметры обновления экрана, убрав мышку и задали размер окна для игры..

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

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

load image "Media\curs.png",2 - Данная команда позволяет загрузить изображение в проект.
Параметры которые необходимо указать: load image "полный/относительный путь файла",номер присваиваемый изображению
Я знаю, что файлы для проекта у меня лежат в папке "Media" а необходимый файл называется "curs" и имеет расширение ".png" , при указание пути мы должны знать как осуществляется переходы между папками, у меня есть папка "Madia" которая находиться в папке с проектом в итоге мы получаем "Media\curs.png", если поместить папку "Media" рядом с папкой проекта то путь будет выглядеть следующим образом "..\Media\curs.png" в этом случае указатель "..\" говорить вернуться на папку назад.
Так же можно указать и полный путь до файла "F:\iBinaryWay\BugsKiller\Media\crus.png" - но это не всегда удобно так, что мы будем использовать относительные пути...

sprite 2,0,0,2 - это довольно таки универсальная команда для вывода спрайта на экран с возможностью позиционировать его на экране по осям X. Y.
Параметры которые необходимо указать:
sprite Номер спрайта,координата по оси X,координата по оси Y,номер изображения из которого мы хотим сделать спрайт
Номер спрайта - можно указать любое целочисленное число(теоретически) но лично я обычно страюсь обозначать их под тем же номером что и загруженная картинка.
Цитата
Мне больше нравиться когда вместо номеров срайтам (картинкам,моделям,музыке и т.д.) можно поставить относительное название(к примеру load image "Media\curs.png",cursor) но эта тема для другой беседы

Теперь немного о системе координат в ДБ/ДБпро.
Следующая картинка покажет как выглядит система координат в ДБ
Прикрепленное изображение

Теперь мы знаем, что левый верхний угол это координата x0 y0 правый нижний x800 y600
Попробуем переместить наш курсор в центр экрана
sprite 2,300,400,2 laugh.gif
Вот пример кода который должен у нас получиться.
Код
set display mode 800,600,32
sync on
sync rate 60
hide mouse

load image "Media\curs.png",2
sprite 2,300,400,2

DO
    sync
LOOP

Можно скомпилировать проект нажав кнопку F5 на клавиатуре и посмотреть, что у нас вышло..
Теперь давайте попробуем разобраться с еще одной картинкой где нарисовано 4 жучка... хотя если быть точным на этой картинке 1 жук но в 4х разных ракурсах. 1-3 жук в движение 4 раздавленный жук... ( относительно похоже) tongue.gif
Для загрузки спрайта с несколькими и более кадрами можно использовать следующую команду:

create animated sprite 1,"Media\Bug.png",4,1,1 - загрузка картинки, параметры анимации
Параметры которые необходимо указать:
create animated sprite Номер спрайта ,"Путь",кадры по горизонтали,кадры по вертикали,номер картинки
Я думаю с параметрами 1.2.4 все понятно.. давайте разберем параметры кадров...
Данные параметры задают кол во кадров по вертикали и горизонтали, в нашем случае у нас есть картинка с 4мя кадрами по горизонтали и одним кадром по вертикали... легче всего представить это на примере сетки или электронной таблицы тогда мы получим число столбцов и строк 4 столбца в 1 строку. считаться и читататься кадры из файла будут с лева на права и с верху вниз... я думаю тут нечего сложного нет...

Добавляем команду create animated sprite 1,"Media\Bug.png",4,1,1 перед основным циклом как и предыдущую.
Добавляем еще одну сточку в которой указываем где ее надо расположиться sprite 1,300,400,1
и пожалуй еще одну небольшую команду для кросоты картинки dry.gif SET SPRITE FRAME 1 , 4 - задает кадр спрайту.
SET SPRITE FRAME Номер спрайта , номер кадра

В итоге получаем следующее
Код
set display mode 800,600,32
sync on
sync rate 60
hide mouse

create animated sprite 1,"Media\Bug.png",4,1,1
sprite 1,300,400,1
SET SPRITE FRAME 1 , 4

load image "Media\curs.png",2
sprite 2,300,400,2


DO
    sync
LOOP


Теперь попробуем управлять нашим курсором.

Добавим в основной цикл следующие строки

sprite 2,aimX,aimY,2 - вместо указания на конкретную координату в 2х мерном пространстве мы ввели переменные aimX и aimY.
aimX = mouseX() - берем нашу переменную и говорим ей что отныне она будет ровна координате мышки по X
aimY = mouseY() - по Y

mouseX() - Эта команда получает текущую целое X положение указателя мыши
mouseY() - Эта команда получает текущую целое Y положение указателя мыши

Полный листинг данного урока.
CODE
set display mode 800,600,32
sync on
sync rate 60
hide mouse

create animated sprite 1,"Media\Bug.png",4,1,1
sprite 1,300,400,1
SET SPRITE FRAME 1 , 4

load image "Media\curs.png",2
sprite 2,300,400,2

DO

sprite 2,aimX,aimY,2
aimX = mouseX()
aimY = mouseY()
sync
LOOP


Конец 2й части...

Фууууухххх blink.gif

The Bugs Killer Часть 3.


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

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

Немного о пользовательских функциях. ( в дальнейшим я буду сокращать их либо func либо ПФ)
В общем любая ПФ это микро программа исполняемая в перед циклом либо в цикле, при условие либо каждый раз при запуске или проходе по циклу...
По своему они бывают в 2х варианта (в основном могу и ошибаться) исполняющие некий код и исполняющий код и возвращающие значение...
Мы пройдем по всем вариантам...

Первая функция с которой я Вас познакомлю будет OffSetSprite_to_M - это относительно несложная функция будет иметь всего один параметр и будет служить для выравнивания 0й координаты спрайта по центру спрайта.
вот как выглядит это в виду условного изображения.
Прикрепленное изображение

Давайте для наглядности поставим REM на следующую строку нашего кода и я думаю сразу будет понятно зачем нам необходима данная функция
Код
sync rate 60
rem hide mouse

Теперь мы видим, что курсор мыши находиться в координатах спрайта 0, надо это исправить...

Для перемещения 0й координаты спрайта в ДБп есть команда Offset Sprite Номер спрайта, координата X, координата Y ,
мы знаем, что наш спрайт имеет параметры 64 на 64 pix значит 0й координат нам надо перенести на середину 32*32 мы получаем следующее
Offset Sprite 2, 32, 32 , теоретически мы решили нашу задачу, но предположим, что мы не знали размер картинки(спрайта)
В этом случаем мы это можем выяснить в самой программе 2мя командоми
sprite width(номер спрайта) - возвращает ширину спрайта в pix
sprite height(номер спрайта) - возвращает высоту спрайта в pix
Если поделить это значение на 2 то мы получим 32 pix - таким образом выглядеть это будет так
Offset Sprite 2,sprite width(2)/2,sprite height(2)/2
НО писать это для каждого спрайта занятие долгое по этой причини мы объединим это в одну пользовательскую функцию.

Любая пользовательская функция начинается с ее объявления, Function далее мы указываем имя и параметры в "()" закрываем ПФ EndFunction если мы хотим получить какое либо значение переменной из ПФ после EndFunction мы указываем название переменной.

В нашем случае ПФ будет называться OffSetSprite_to_M и иметь одну переменную spriteOffSet - спрайт над которым мы будет производить перемены.

Function OffSetSprite_to_M(spriteOffSet)
Offset Sprite spriteOffSet,sprite width(spriteOffSet)/2,sprite height(spriteOffSet)/2
EndFunction

Теперь можно использовать ПФ для получения результата в нашем проекте...
Поместите данную ПФ после основного цикла и объявите ее после загрузки нашего спрайта OffSetSprite_to_M(2), рекомендую проделать тоже самое и для спрайта 1 ( жука )
Листинг:
Код
set display mode 800,600,32
sync on
sync rate 60
Rem hide mouse

create animated sprite 1,"Media\Bug.png",4,1,1
sprite 1,300,400,1
SET SPRITE FRAME 1 , 4
OffSetSprite_to_M(1)

load image "Media\curs.png",2
sprite 2,300,400,2
OffSetSprite_to_M(2)

DO

sprite 2,aimX,aimY,2
aimX = mouseX()
aimY = mouseY()
    sync
LOOP

Function OffSetSprite_to_M(spriteOffSet)
Offset Sprite spriteOffSet,sprite width(spriteOffSet)/2,sprite height(spriteOffSet)/2
EndFunction


Предлагаю написать еще одну функцию которая будет полезна в нашем проекте...
rndx(min,max) - данная функция будет возвращать случайное число в промежутке от min до max.
В DBp есть встроенная команда для возвращения случайного числа называется от 0 до заданного числа rnd() - к сожалению для наших целей она немного huh.gif бедноватая , по этому мы слегка ее модифицируем.

Мы знаем что команда Rnd() возвращает некое число по этому в коде ее обычно используют так
Код
a=rnd(2)
print str$(a)

Тут скорей всего будет 1 cool.gif - мы указали промежуток от 0 до 2

function rndx(min,max)
value=rnd(max-min)+min
endfunction value

Данная ПФ отличается от первой тем, что она возвращает значение value полученное после того как исполниться основная микропрограмма
value=rnd(max-min)+min

Подробно эту функцию мы не будем рассматривать т.к. она обсуждалась и создавала при помощи участников форума http://area.mediahouse.ru.
Вот ссылка на обсуждение одного из моих ранних постов http://area.mediahouse.ru/index.php?showtopic=2148&hl= и еще один мой пост с изысканиями на данную тему http://area.mediahouse.ru/index.php?s=&...ost&p=30051 .

Давайте поместим данную ПФ после первой и попробуем ей воспользоваться добавив ее в качества параметра к следующей команде
sprite 1,rndx(64,600),rndx(64,500),1 ..

Листинг:
Код
set display mode 800,600,32
sync on
sync rate 60
Rem hide mouse

create animated sprite 1,"Media\Bug.png",4,1,1
sprite 1,rndx(64,600),rndx(64,500),1
SET SPRITE FRAME 1 , 4
OffSetSprite_to_M(1)

load image "Media\curs.png",2
sprite 2,300,400,2
OffSetSprite_to_M(2)

DO

sprite 2,aimX,aimY,2
aimX = mouseX()
aimY = mouseY()
    sync
LOOP

Function OffSetSprite_to_M(spriteOffSet)
Offset Sprite spriteOffSet,sprite width(spriteOffSet)/2,sprite height(spriteOffSet)/2
EndFunction

function rndx(min,max)
value=rnd(max-min)+min
endfunction value


И так при запуске нашей игры мы видим, что жук появиться на экране в заданных пределах от 64 до 600 по горизонтали и от 64 до 500 по вертикали.

Теперь давайте попробуем отловить нажатие на левую кнопку мыши в нашей игре...
В DBp есть встроенная команда mouseclick() - которая позволяет узнать какая кнопка мыши нажата в данный момент с ней мы и будем работать..

mouseclick() = 1 - левый клик мышиной кнопки.

Для этого мы воспользуемся командой IF ( если ) условие - если условие удовлетворено то исполняется код стоящий после условия If и перед закрывающей ее командой EndIf.( с условиями мы будем развлекаться по полной smile.gif )
(If - наиболее часто используемая команда в DBp/DBc при создание игр - более подробно можно узнать из справочника по ДБ)

Давайте добавим в основной цикл следующие строки

If mouseclick()=1
text 10,10, "Бабах"
EndIf

В результате мы видим, что у нас появилась надпись в правом верхнем углу экрана с надписью "Бабах", мы удачно перехватили клик мыши, но если обратите внимание то не все так гладко как хотелось бы, у нас 1 клик = 1 выстрел отсюда нам надо что бы при нажатие обрабатывалось немного по другому

Давайте добавим еще одно условие для нашего кода
If click = 0 и разместим его сразу после проверки на нажатие кнопки главное не забыть обозначить его конец командой EndIf

if mouseclick()=1
If click = 0
text 10,10, "Бабах"
EndIf
EndIf
Теперь мы знаем что наше событие будет выполнено если флаг click = 0 при нажатие на ЛКМ(левая кнопка мыши) мы будем делать так click = 1 а для регистрации поднятой мышки мы добавим еще одно небольшое примечание к условию else( в противном случает от IF ).

if mouseclick()=1
If click = 0
text 10,10, "Бабах"
click = 1
EndIf
else
click = 0
EndIf

Теперь это больше похоже на 1 клик = 1 выстрел.. В верхнем левом углу появляется надпись "Бабах" laugh.gif

Как всегда полный лист сегодняшнего урока:

CODE
set display mode 800,600,32
sync on
sync rate 60
Rem hide mouse

create animated sprite 1,"Media\Bug.png",4,1,1
sprite 1,rndx(64,600),rndx(64,500),1
SET SPRITE FRAME 1 , 4
OffSetSprite_to_M(1)

load image "Media\curs.png",2
sprite 2,300,400,2
OffSetSprite_to_M(2)


DO

if mouseclick()=1
If click = 0
text 10,10, "Бабах"
click = 1
EndIf
Else
click = 0
EndIf


sprite 2,aimX,aimY,2
aimX = mouseX()
aimY = mouseY()
sync
LOOP

Function OffSetSprite_to_M(spriteOffSet)
Offset Sprite spriteOffSet,sprite width(spriteOffSet)/2,sprite height(spriteOffSet)/2
EndFunction

function rndx(min,max)
value=rnd(max-min)+min
endfunction value



Конец 3й части...

И как всегда Фуххх blink.gif

The Bugs Killer Часть 4.


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

Команды которые мы будем сегодня применять в нашем уроке:

1 sprite collision (номер спрайта 1,номер спрайта 2) - позволяет узнать столкнулись(пересеклись) ли спрайты
2 play sprite номер спрайта,первый кадр,последний кадр,задержка в МС - позволяет воспроизвести анимацию в нашем спрайте ( жук )
3 MOVE SPRITE номер спрайта, скорость перемещения - позволяет передвигать спрайт в 2д пространстве с заданной скоростью
4 ROTATE SPRITE номер спрайта, направление ( 0 - 360 градусов) - позволяет развернуть спрайт на определенный градус
5 clone sprite Спрайт для клонирования(номер спрайта),номер спрайта клона - позволяет клонировать спрайт перенося на клон большинство параметров своего исходного брата(жука laugh.gif ).
В принципе этих команд на сегодня хватит...

Давайте добавим несколько следующих команд в основной цикл игры

play sprite 1,1,3,300 - в данном случае мы сказали нашему жуку начать дергать лапками от первого куска спрайта до 3 (вклчительно)
всего 3 кадра..
MOVE SPRITE 1, spriteMoveSpeed# - в этом случае я специально не стал указывать скорость перемещения жука т.к. мы пока не сможем его поймать если это нам понадобиться.. ( мы укажем скорость чуть позже )

Теперь предлагаю заняться отловом нашего жука.
Давайте воспользуемся командой 1 из нашего списка и на ее основе добавим еще одно условие к нашему щелчку мыши. unsure.gif
Код
if sprite collision(2,1)> 0
    if mouseclick()=1
        If click = 0
                text 10,10, "Бабах"
                    click = 1
        endif
      else
          click = 0
    endif
    
endIf


Запустив игру мы увидим, что наш жук шевелится и если щелкнуть мышкой по жуку появляется надпись "Бабах".
Вот мы и подошли к финишной черте когда можно было бы пострелять по жуку но он скучный да и к тому же не двигается..
Давайте исправлять...

В наше условие теперь следует добавить следующие команды( сразу после text 10,10, "Бабах")

n = n + 3 - добавляем небольшой счетчик
clone sprite 1,n - клонируем спрайта 1 и клону даем номер 3 ( с каждым разом этот номер будет возрастать на 3 единицы ) ( wink.gif можно это обойти и по другому, если у Вас есть предложения пишем)
SET SPRITE FRAME n , 4 - устанавливаем ново испеченному спрайту кадр
sprite n,sprite x(1),sprite y(1),1 - задаем координаты нашему клону координаты его родителя ( команды sprite x(номер спрайта) и sprite y(номер спрайта) работают аналогично командам mouseX()/mouseY() - возвращая значение координат для заданного спрайта)
sprite 1,rndx(64,600),rndx(64,500),1 - задаем новую координату нашему жуку ( при попадание в жука жук переместиться в случайную точку на экране)
ROTATE SPRITE 1, rnd(360) - разворачиваем жука случайным образом от 0 до 360

С условием выстрела пока покончено, предлагаю добавить скорости нашему жуку( пинок под зад ), перед основным циклом допишите строчку spriteMoveSpeed# = 0.3

Теперь можно проверять... rolleyes.gif

Самостоятельно можно поиграться со скоростью перемещения жука, задержкой между кадрами...
Большинство параметров я подбирал на глазок, можете менять их как Вам будет угодно... huh.gif

Полный листинг игры :
CODE

set display mode 800,600,32
sync on
sync rate 60
hide mouse

create animated sprite 1,"Media\Bug.png",4,1,1
sprite 1,rndx(64,600),rndx(64,500),1
SET SPRITE FRAME 1 , 4
OffSetSprite_to_M(1)

load image "Media\curs.png",2
sprite 2,300,400,2
OffSetSprite_to_M(2)

spriteMoveSpeed# = 0.3
DO

if sprite collision(2,1)> 0
if mouseclick()=1
If click = 0
text 10,10, "Бабах"
n = n + 3
clone sprite 1,n
SET SPRITE FRAME n , 4
sprite n,sprite x(1),sprite y(1),1
sprite 1,rndx(64,600),rndx(64,500),1
ROTATE SPRITE 1, rnd(360)
click = 1
EndIf
Else
click = 0
EndIf
EndIf

play sprite 1,1,3,300
MOVE SPRITE 1, spriteMoveSpeed#

sprite 2,aimX,aimY,2
aimX = mouseX()
aimY = mouseY()
sync
LOOP

Function OffSetSprite_to_M(spriteOffSet)
Offset Sprite spriteOffSet,sprite width(spriteOffSet)/2,sprite height(spriteOffSet)/2
EndFunction

function rndx(min,max)
value=rnd(max-min)+min
endfunction value




Конец 4й части....

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

The Bugs Killer Часть 5.


Всем доброго времени суток...

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

В этом уроке мы закончим нашу идею с убиванием жуков:
Узнаем как реализовать простенькое стартовое меню для игры rolleyes.gif
Добавим счетчик времени для игры ohmy.gif ( если помните в первой части я написал что - )
Цитата
Цель игры: Убить как можно больше жучков за определенный отрезок времени

Добавим счетчик убитых жуков wink.gif
Введем систему поощрения tongue.gif и наказания angry.gif пользователя в виде заработанных $ за раунд.

huh.gif Ну что же давайте наберемся терпения и приступим, оно нам понадобиться!!! angry.gif - адский смайлик

После 4й части у Вас должен был появиться вопрос " а что делать если жук уполз за пределы экрана " - да вопрос вполне логичный и наверняка у большинства возникла мысль каким либо образом его перехватить, ну в общем это можно реализовать.
Из пред идущих частей мы знаем как узнать координаты жука и знаем о системе координат в ДБ.п.
Наша задача узнать когда он выйдет за рамки нашего экрана x0 x800 y0 y600

Давайте добавим следующее условие в наш основной цикл.
Код
If sprite x(1) < 0 or sprite y(1) < 0 or sprite x(1) > 800 or sprite y(1) > 600
ENDIF

or - означает "или" , в нашем случае вместо описания условий для каждого sprite x и sprite y положения жука мы немного сократили нашу работу.
Теперь мы перехватили жука и стало быть надо добавить нашему условию действие, давайте позаимствуем его из условия где мы стреляли в жука..

Код
If sprite x(1) < 0 or sprite y(1) < 0 or sprite x(1) > 800 or sprite y(1) > 600
   text 10,10, "Удрал жучара"
   sprite 1,rndx(64,600),rndx(64,500),1
   ROTATE SPRITE 1, rnd(360)
ENDIF


Теперь каждый раз когда жук будет убегать за границу экрана мы увидим его в случайной координате экрана и он продолжит свой путь в сторону границ экрана.

Теперь мы можем заняться таймером, для этого мы воспользуемся командой timer() - данная команда возвращает время прошедшее с начала запуска нашей игры ( что не всегда удобно " или возможно я чего то еще не знаю ") единица измерения таймера это миле секунды т.е. 1000МС = 1 секунда, в игре мы остановимся на на отрезке в 1 минуту - 60сек.

До начала основного цикла предлагаю объявить переменную Time и поровнять ее к timer()
Код
Time = timer()

далее в основном цикле добавим еще одну строчку
Код
GameTime = abs( Time - timer() )

Зачем и почему это выглядит именно так:
время до начало цикла - время в цикле = отрицательное число но время не может быть отрицательным в нашей игре и по этому мы добавим команду abs() - по сути конвертирует отрицательное число в положительное =)
И так мы только что соорудили довольно простенький таймер, давайте его проверим, для этого стоит добавить следующую строчку кода в основной цикл
Код
text 10,30, "Time" + str$(GameTime/1000)

str$() - возвращает символьное представление заданного значения.( если мы хотим вывести на экран числовое значение некой переменно, то рекомендую воспользоваться этой командой)
Добавляем условие при котором наша игра будет заканчиваться...
Код
If GameTime > 60000
End
ENDIF

Теперь по истечение 60 секунд игра будет заканчиваться =) но это не конец, а только начало tongue.gif

Давайте ускорим жука путем добавления еще одного условия связанного со временем
Код
If GameTime > 30000
spriteMoveSpeed# = 0.6
ENDIF

Теперь жучара будет бегать шустро по истечению 30 секунд.
На эту тему можно поэкспериментировать самостоятельно добавьте еще пару условий на любое время с любой скорость.

А теперь пряники и кнут, давайте добавим перед началом цикла переменную Score равную 0 и переменную BugsKilled равную 0
Код
Score = 0
BugsKilled = 0
GameTime = 0
show sprite 1
show sprite 2

Теперь у нас есть 2 переменные, по названиям переменных понятно, что одна будет для подсчета игровых очков, а другая для кол-ва убитых жучар
Давайте начнем считать к нашему любимому условию с выстрелом сразу после "text 10,10, "Бабах"" добавим следующие строки
Код
            Score = Score + 100
            BugsKilled = BugsKilled  + 1

Теперь при каждом удачном попадание наш счет будет пополняться 100$ и + 1 убитым жуком =)

Давайте попробуем вывести на экран информацию о нашем заработке.
Опять же в основном цикле, перед строчкой text 10,30, "Time" + str$(... мы добавим строку
Код
text 10,10, "Score" + str$(Score) + "$"


Давайте подумаем при коком условие лучше всего отнять у игрока эти самые $ - да правильно если жук убежал за пределы экрана.
Добавляем строку в условие If sprite .......
Код
Score = Score - 50

Ну я думаю с него хватит.

Предлагаю убрать несколько лишних строк кода, они нам больше не понадобятся.

text 10,10, "Бабах"
text 10,10, "Удрал жучара"
Обе строки вводились в игру только для проверки работоспособности нашего кода.

И так проверяем, промежуточный лист кода:
CODE

set display mode 800,600,32
sync on
sync rate 60
hide mouse

create animated sprite 1,"Media\Bug.png",4,1,1
sprite 1,rndx(64,600),rndx(64,500),1
SET SPRITE FRAME 1 , 4
OffSetSprite_to_M(1)

load image "Media\curs.png",2
sprite 2,300,400,2
OffSetSprite_to_M(2)

spriteMoveSpeed# = 0.3
Score = 0
BugsKilled = 0
Time = timer()
GameTime = 0
show sprite 1
show sprite 2
DO

if sprite collision(2,1)> 0
if mouseclick()=1
If click = 0
Score = Score + 100
BugsKilled = BugsKilled + 1
n = n + 3
clone sprite 1,n
SET SPRITE FRAME n , 4
sprite n,sprite x(1),sprite y(1),1
sprite 1,rndx(64,600),rndx(64,500),1
ROTATE SPRITE 1, rnd(360)
click = 1
EndIf
Else
click = 0
EndIf
EndIf

If sprite x(1) < 0 or sprite y(1) < 0 or sprite x(1) > 800 or sprite y(1) > 600
sprite 1,rndx(64,600),rndx(64,500),1
ROTATE SPRITE 1, rnd(360)
Score = Score - 50
ENDIF

If GameTime > 60000
End
ENDIF

If GameTime > 60000
spriteMoveSpeed# = 0.6
ENDIF

play sprite 1,1,3,300
MOVE SPRITE 1, spriteMoveSpeed#

text 10,10, "Score" + str$(Score) + "$"
text 10,30, "Time" + str$(GameTime/1000)

GameTime = abs( Time - timer() )
sprite 2,aimX,aimY,2
aimX = mouseX()
aimY = mouseY()
sync
LOOP

Function OffSetSprite_to_M(spriteOffSet)
Offset Sprite spriteOffSet,sprite width(spriteOffSet)/2,sprite height(spriteOffSet)/2
EndFunction

function rndx(min,max)
value=rnd(max-min)+min
endfunction value


Теперь предлагаю разобраться с тем как нам реализовать стартовый экран игры(меню) и концовку игры(выводить инфо о кол-ве убитых жуков)
Для этого мы воспользуемся командой Goto и добавим несколько меток(указателей) на которые будет ссылаться команда Goto.

Goto - позволяет осуществлять переход на метку(указатель) в коде, если немного по другому:
у нас есть некий код который в процессе выполнения читается с верху вниз с лева на право, что бы пропустить некую часть кода мы можем использовать команду Goto и некую метку, в итоге исполнения нашего кода программа пропустит ту часть которая стоит после команды Goto _step и и исполнить ту часть кода которая стоит после нашей метки _step: .
Метка может иметь любое сочетание символов букв\цифр и должна заканчиваться двоеточием (:) , после команды Goto и указания метки двоеточием не ставиться.

Простенький пример:
Код
print "шаг 1"
print "шаг 2"
print "шаг 3"
wait key

Если мы хотим пропустить шаг 2 то надо написать так:
Код
print "шаг 1"
goto _step
print "шаг 2"
_step:
print "шаг 3"
wait key

Теперь мы видим, что второй шаг мы пропустили, в нашем случае мы введем сразу несколько указателей _gameLoad: _gameLoop: _scroteLoop: _startscreanLoop:
Поскольку наш проект усложнился нам понадобиться некий визуальный ориентир по которому мы будем строить его дальше что бы не сбиваться с курса.. Блок схема - самый удобный вариант и самый наглядный..
Ну для наглядности того, что мы собираемся сделать рекомендую ознакомиться.
Прикрепленное изображение

На самом деле БС надо рисовать еще на стадии подготовки к проекту, не обязательно на ПК можно и карандашиком на бумаге, но в нашем случае мы идем от простого к сложному(для более простых вещей БС нужен не всегда), а для более сложных проектов нужна БС.
Хотя я знаю очень много людей (программистов) которые БС держат в голове, как мне пояснили "со временем это становиться нормой для простых проектов".

Разместим указатель _gameLoad: перед строками с загрузкой наших спрайтов, _gameLoop: - разместим перед основным циклом (перед строкой spriteMoveSpeed# = 0.3), _scroteLoop: - после основного цикла и после наших ПФ, _startscreanLoop: еще ниже.
После указателей _startscreanLoop: и _scroteLoop: добавим
Следующий код:
Код
Do

Sync
Loop


Еще один промежуточный код:
CODE

set display mode 800,600,32
sync on
sync rate 60
hide mouse

_gameLoad:

create animated sprite 1,"Media\Bug.png",4,1,1
sprite 1,rndx(64,600),rndx(64,500),1
SET SPRITE FRAME 1 , 4
OffSetSprite_to_M(1)

load image "Media\curs.png",2
sprite 2,300,400,2
OffSetSprite_to_M(2)

_gameLoop:

spriteMoveSpeed# = 0.3
Score = 0
BugsKilled = 0
Time = timer()
GameTime = 0
show sprite 1
show sprite 2
DO

if sprite collision(2,1)> 0
if mouseclick()=1
If click = 0
Score = Score + 100
BugsKilled = BugsKilled + 1
n = n + 3
clone sprite 1,n
SET SPRITE FRAME n , 4
sprite n,sprite x(1),sprite y(1),1
sprite 1,rndx(64,600),rndx(64,500),1
ROTATE SPRITE 1, rnd(360)
click = 1
EndIf
Else
click = 0
EndIf
EndIf

If sprite x(1) < 0 or sprite y(1) < 0 or sprite x(1) > 800 or sprite y(1) > 600
sprite 1,rndx(64,600),rndx(64,500),1
ROTATE SPRITE 1, rnd(360)
Score = Score - 50
ENDIF

If GameTime > 60000
End
ENDIF

If GameTime > 60000
spriteMoveSpeed# = 0.6
ENDIF

play sprite 1,1,3,300
MOVE SPRITE 1, spriteMoveSpeed#

text 10,10, "Score" + str$(Score) + "$"
text 10,30, "Time" + str$(GameTime/1000)

GameTime = abs( Time - timer() )
sprite 2,aimX,aimY,2
aimX = mouseX()
aimY = mouseY()
Sync
LOOP

Function OffSetSprite_to_M(spriteOffSet)
Offset Sprite spriteOffSet,sprite width(spriteOffSet)/2,sprite height(spriteOffSet)/2
EndFunction

function rndx(min,max)
value=rnd(max-min)+min
endfunction value

_scroteloop:

DO

Sync
LOOP

_startscreanloop:

DO

Sync
LOOP

End


Теперь попробуем разобраться с меню игры и стартовым экраном.
Мы уже знаем несколько команд для вывода текста на экран, давайте познакомимся еще с несколькими.
SET TEXT SIZE размер шрифта - позволяет задать размер шрифта
INK RGB(150,150,150),RGB(255,255,255) - позволяет задать цвет текста и фона для текста.

Теперь между нашим указателем и циклом поместим строки
HIDE ALL SPRITES - эта команда убирает все спрайты с экрана
newgameFlag = 1 - небольшой флаг для будущей меню

В начале цикла мы выставляем размер шрифта для нашего заголовка ( названия игры ) у меня он равен 50, дальше используя команду изменения цвета шрифта мы сделаем его светящимся(мерцающим)
Заменив стандартное значение RGB(R(от 0 до 255),G(от 0 до 255),B(от 0 до 255)) командой RND(c параметром 255)
Но не везде а только для параметров G и B для красного R оставим 255 так будет красивей.
далее добавляем текст командой text и помещаем его на середину экрана для этого можно использовать 2 варианта:
1) мы знаем что разрешение экрана 800*600 следовательно середина это 400*300
2) мы можем воспользоваться командами которые будут возвращать ширину экрана и высоту разделив ее на 2 мы получим те же самые значения что и в случае 1 ( SCREEN WIDTH()/2 SCREEN HEIGHT()/2 )
В поле текст указываем название игры.. "The Bugs Killer"

Титул готов теперь давайте разберемся с нашими флагами и меню игры..
Поскольку наш код исполняется от первой строки к последней, мы можем для каждой команды вывода текста задать свой размер, цвет и т.д.
Этим мы и воспользуемся.
До начала цикла мы объявили флаг равный 1 - значит первый флаг будет начало игры.
Для флаг 1 надо задать условие при котором будет выводиться текст и внутри условия еще одно для перехода при нажатие кнопки пробел.
Внутри нашего флага следует выставить размер шрифта 12 и задать цвет для первой надписи с rnd(255) для всех параметров RGB,ну и собственно надпись text 150,150, "Начать игру" ,после этого следует выставить значение цвета шрифта для второй надписи, поскольку она еще не выбрана то мы не будем пользоваться командой rnd() для указания цветов, вместо этого мы укажем серый цвет RGB(150,150,150) далее выводим надпись text 150,170, "Выход", и в финале нашего условия добавляем переход по условию нажатой кнопки if spacekey()=1 then goto _gameLoad
закрываем наше условие..
И так мы создали мерцающий пункт меню "Начать игру" и серый пункт "Выход", предлагаю Вам самостоятельно добавить условие для флага newgameFlag = 0, поменяв местами значения цвета текста для первого и второго пункта меню. Во второе условие добавляем условие выхода по нажатию кнопки пробел if spacekey()=1 then end
Добавив следующие строки мы сможем осуществлять навигацию по нашему меню.

if upkey()=1 then newgameFlag = 1 - при нажатие кнопки вверх флаг будет равен 1
if downkey()=1 then newgameFlag = 0 - при нажатие кнопки вниз флаг будет равен 0


Следующий кусок кода выглядит громоздко, но если присмотреться Вы увидите, что ничего нового в нем нет.
Код
_startscreanloop:
HIDE ALL SPRITES
newgameFlag = 1
DO
SET TEXT SIZE 50    
INK RGB(255,rnd(255),rnd(255)),RGB(255,255,255)
text SCREEN WIDTH()/2,SCREEN HEIGHT()/2, "The Bugs Killer"    
    
IF newgameFlag = 1
SET TEXT SIZE 12
INK RGB(rnd(255),rnd(255),rnd(255)),RGB(255,255,255)
text 150,150, "Начать игру"
INK RGB(150,150,150),RGB(255,255,255)
text 150,170, "Выход"
if spacekey()=1 then goto _gameLoad
endIF

IF newgameFlag = 0
SET TEXT SIZE 12
INK RGB(150,150,150),RGB(255,255,255)
text 150,150, "Начать игру"
INK RGB(rnd(255),rnd(255),rnd(255)),RGB(255,255,255)
text 150,170, "Выход"
if spacekey()=1 then end
endIF

if upkey()=1 then newgameFlag = 1
if downkey()=1 then newgameFlag = 0

sync    
LOOP


Как видно из кода ничего сложного нет...

Продолжение следует.

The Bugs Killer Часть 5. продолжение


И так с меню мы покончили предлагаю вывести концовку игры и посчитать кол-во убитых жуков и кол-во баллов за игру.

Давайте вернемся к еще одной метке которую мы сделали ранее _scroteloop:, сразу после метки мы должны спрятать все спрайты HIDE ALL SPRITES а в цилк добавляем команды вывода текста? и условие для нажатого пробела с переходом обратно в игру.

Код
_scroteloop:
HIDE ALL SPRITES
DO

    text 150,150, "Очки : " + str$(Score) + " $"
    text 150,170, "Всего жуков убито : " + str$(BugsKilled)
    text 150,190, "Для перезапуска игры жми пробел."
        
    if spacekey()=1 then goto _gameLoop
    
    Sync    
LOOP


Теперь в нашем игровом цикле для условия когда у нас кончается время мы можем смело добавить строчку:
goto _scroteloop и убрать команду END

Код
If GameTime > 60000
Goto _scroteloop
ENDIF


В основном цикле игры следует добавить строчку

Код
if escapekey()=1 then Goto _scroteloop

Это позволить по нажатию кнопки ESC переходить в цикл вывода инфо о игры _scroteloop
В случае с циклом _scroteloop все немнго сложнее если мы добавим строчку if escapekey()=1 then Goto _startscreanloop то обнаружим неприятный сюрприз, а именно мы будем проскакивать наш цикл с выводом инфо экрана так, что мы поступим аналогично как и для мышки.
до начало цикла введем флаг tupESC = 1

В цикле _scroteloop следует добавить такую же строчки, но уже с указанием на переход в экран стартового меню

Код
    if escapekey()=1
        If tupESC = 0
                goto _startscreanloop
            tupESC = 1            
        endif
      else
          tupESC = 0
    endif



В общем на этом можно было бы и закончить, но надо добавить еще несколько штрихов.

В самом начале игры следует отключить кнопку ESC как кнопку для выхода из игры по умолчанию.
Команда disable escapekey

Перед нашей меткой _gameLoad: следует добавить команду Goto _startscreanloop - это позволит нам перейти в меню игры , миную загрузку наших спрайтов..
После нашей метки _gameLoad: следует добавить строчку

If initPass = 1 then Goto _gameLoop
Т.к. нам не нужно будет загружать изображения повторно нам надо перескочить этот блок еще раз.
После кода с загрузкой изображений(спрайтов) следует установить флаг initPass = 1

А Вот и финальный код нашей игры.. Если честно я его немного поправил, изменив надписи выводимые на экран командой text.

CODE

Rem Project: TheBugsKillerTUT01
Rem Created: Thursday, September 16, 2010

Rem ***** Main Source File *****

set display mode 800,600,32
Sync on
Sync rate 60
hide mouse
disable escapekey

Goto _startscreanloop

_gameLoad:

If initPass = 1 then Goto _gameLoop

create animated sprite 1,"Media\Bug.png",4,1,1
sprite 1,rndx(64,600),rndx(64,500),1
SET SPRITE FRAME 1 , 4
OffSetSprite_to_M(1)

load image "Media\curs.png",2
sprite 2,300,400,2
OffSetSprite_to_M(2)

initPass = 1

_gameLoop:

spriteMoveSpeed# = 0.3
Score = 0
BugsKilled = 0
Time = timer()
GameTime = 0
show sprite 1
show sprite 2
DO


If escapekey()=1 then Goto _scroteloop

If sprite collision(2,1)> 0
If mouseclick()=1
If click = 0
Score = Score + 100
BugsKilled = BugsKilled + 1
n = n + 3
clone sprite 1,n
SET SPRITE FRAME n , 4
sprite n,sprite x(1),sprite y(1),1
sprite 1,rndx(64,600),rndx(64,500),1
ROTATE SPRITE 1, rnd(360)
click = 1
EndIf
Else
click = 0
EndIf
EndIf

If sprite x(1) < 0 or sprite y(1) < 0 or sprite x(1) > 800 or sprite y(1) > 600
sprite 1,rndx(64,600),rndx(64,500),1
ROTATE SPRITE 1, rnd(360)
Score = Score - 50
EndIf

If GameTime > 30000
Goto _scroteloop
EndIf

If GameTime > 10000
spriteMoveSpeed# = 0.6
EndIf

play sprite 1,1,3,300
MOVE SPRITE 1, spriteMoveSpeed#

text 10,10, "Очки : " + str$(Score) + " $"
text 10,30, "Время игры :" + str$(GameTime/1000)

GameTime = abs( Time - timer() )

sprite 2,aimX,aimY,2
aimX = mouseX()
aimY = mouseY()

Sync
LOOP

Function OffSetSprite_to_M(spriteOffSet)
Offset Sprite spriteOffSet,sprite width(spriteOffSet)/2,sprite height(spriteOffSet)/2
EndFunction

function rndx(min,max)
value=rnd(max-min)+min
endfunction value

_scroteloop:
tupESC = 1
HIDE ALL SPRITES
DO

text 150,150, "Очки : " + str$(Score) + " $"
text 150,170, "Всего жуков убито :" + str$(BugsKilled)
text 150,190, "Для перезапуска игры жми пробел."

If spacekey()=1 then goto _gameLoop

If escapekey()=1
If tupESC = 0
goto _startscreanloop
tupESC = 1
EndIf
Else
tupESC = 0
EndIf

Sync
LOOP

_startscreanloop:

HIDE ALL SPRITES
newgameFlag = 1
DO
SET TEXT SIZE 50
INK RGB(255,rnd(255),rnd(255)),RGB(255,255,255)
text SCREEN WIDTH()/2,SCREEN HEIGHT()/2, "The Bugs Killer"

If newgameFlag = 1
SET TEXT SIZE 12
INK RGB(rnd(255),rnd(255),rnd(255)),RGB(255,255,255)
text 150,150, "Начать игру"
INK RGB(150,150,150),RGB(255,255,255)
text 150,170, "Выход"
If spacekey()=1 then goto _gameLoad
EndIf

If newgameFlag = 0
SET TEXT SIZE 12
INK RGB(150,150,150),RGB(255,255,255)
text 150,150, "Начать игру"
INK RGB(rnd(255),rnd(255),rnd(255)),RGB(255,255,255)
text 150,170, "Выход"
If spacekey()=1 then end
EndIf

If upkey()=1 then newgameFlag = 1
If downkey()=1 then newgameFlag = 0

Sync
LOOP





В общем вот и все...

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

Anjimo - спасибо!

The Bugs Killer О звуке и музыке. Дополнение и финал!!!


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

Первое, что бросается в глаза это черный экран перед меню и то как он становиться синим после первого сыгранного матча. Я думаю это очень легко поправить воспользовавшись командой backdrop on - эта команда активирует 3д задник =) вообще 3д задник включается как только мы подгружаем(или выводим на экран) 3д объект, а поскольку когда мы только начинаем нашу игру первые объекты это текст который не является 3д., он не включается.
Добавьте эту команду после строчки где мы прятали мышку от пользователя..

Попробуйте скомпилировать наш пример и посмотреть, что получиться..

Второе что бросается в глаза это конечно жук который проползает под раздавленными товарищами, да это не есть хорошо, для исправления данной проблемы мы воспользуемся командой SET SPRITE PRIORITY спрайт номер, приоритет - данная команда назначает приоритет для отображения спрайта...
Легче всего это представить в виде витрины где в наклеены некие бумажки с информацией, первое стекло ближайшее к нам будет последним слоем а дальнее первым.
Следовательно последним у нас будет курсор, вторым жук который передвигается, 1м слоем мертвые жуки...

После загрузки наших спрайтов добавляем строчку : SET SPRITE PRIORITY 1, 2 ( для жука), SET SPRITE PRIORITY 2, 3 ( для курсора) и добавляем строчку для вновь созданных жуков трупов SET SPRITE PRIORITY n, 1 в наше условие попадания.

Для работы со звуком предлагаю немного изменить конструкцию переходов.
Строчку Goto _startscreanloop необходимо перенести чуть ниже и разместить ее под нашим флагом initPass = 1 и перед указателем(меткой) _gameLoop: - это позволит нам загружать всё необходимое включая звуки и музыку для нашего урока...

Теперь если убрать строчку backdrop on и попробовать скомпилировать наш пример то Вы увидите, что и этой строчкой..

И так я надеюсь вы уже скачали файл(7zip) со звуками, если нет то советую это сделать..
Прикрепленный файл  Media.7z ( 866,81 килобайт ) Кол-во скачиваний: 110
- в данном файле лежит 3 звуковые дорожки shot.wav(звук выстрела), smash.wav(звук раздавленного жука), music fun.mp3(музыка для игры) .

звук загружается в игру командой load sound "путь к файлу звука",номер звука , музыка командой load music "путь к файлу музыки",номер музыки

Давайте загрузим наши звуковые файлы
Код
load sound "Media\shot.wav",1
load sound "Media\smash.wav",2


Предлагаю познакомиться с еще одной командой для работы со звуком.
SET SOUND VOLUME номер звука,громкость - громкость нашего звукового файла от 0 до 100
Сделаем звук выстрела немного тише звука раздавленного жука....
SET SOUND VOLUME 1,95
SET SOUND VOLUME 2,100

Далее загружаем музыку

load music "Media\music fun.mp3",1

в итоге мы получим примерно такой кусок сода:
Код
load sound "Media\shot.wav",1
load sound "Media\smash.wav",2
SET SOUND VOLUME 1,95
SET SOUND VOLUME 2,100

load music "Media\music fun.mp3",1


................................................................................
..................

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

Команда loop music номер музыки - позволяет зациклить музыку, т.е. если дорожка кончилась она будет проиграна еще раз.. это позволит избежать ненужной возни с таймерами и перезапуском музыки.
Давайте поместим команду loop music 1 после указателей(меток) _startscreanloop: _scroteloop: .
Запустив наш проект мы услышим музыку, но начав отстрел жуком музыка еще продолжает играть, остановить ее можно командой stop music 1 , давайте разместим ее после указателя(метки) _gameLoop:
Теперь у нас все должно быть в порядке.

................................................................................
..................

Для того что бы заставить звук воспроизвестись мы воспользуемся командой play sound номер_звука - это команда заставляет воспроизвестись звук единожды.

Добавим ее для первого и второго звука в нашего условия с раздавленными жуками.

Код
play sound 1
play sound 2


ну и пожалуй мы допишем еще немного, что бы был звук выстрела при стрельбе в холостую..
Для нашего условия If sprite collision(2,1)> 0
В самом низу вместо EndIF добавляем следующие строки.

Код
Else
    If mouseclick()=1
        If click = 0
        
        play sound 1
           click = 1
        EndIf
    Else
        click = 0
    EndIf
EndIf



Ну вот в общем и все...


Финальный код урока
CODE


Rem Project: TheBugsKillerTUT01
Rem Created: Thursday, September 16, 2010

Rem ***** Main Source File *****

set display mode 800,600,32
backdrop on
Sync on
Sync rate 60
hide mouse
disable escapekey

_gameLoad:

If initPass = 1 then Goto _gameLoop

create animated sprite 1,"Media\Bug.png",4,1,1
sprite 1,rndx(64,600),rndx(64,500),1
SET SPRITE FRAME 1 , 4
OffSetSprite_to_M(1)
SET SPRITE PRIORITY 1, 2

load image "Media\curs.png",2
sprite 2,300,400,2
OffSetSprite_to_M(2)
SET SPRITE PRIORITY 2, 3


load sound "Media\shot.wav",1
load sound "Media\smash.wav",2
SET SOUND VOLUME 1,95
SET SOUND VOLUME 2,100


load music "Media\music fun.mp3",1

initPass = 1

Goto _startscreanloop

_gameLoop:

spriteMoveSpeed# = 0.3
Score = 0
BugsKilled = 0
Time = timer()
GameTime = 0
show sprite 1
show sprite 2
stop music 1
DO


If escapekey()=1 then Goto _scroteloop

If sprite collision(2,1)> 0
If mouseclick()=1
If click = 0
Score = Score + 100
BugsKilled = BugsKilled + 1
n = n + 3
clone sprite 1,n
SET SPRITE FRAME n , 4
SET SPRITE PRIORITY n, 1
sprite n,sprite x(1),sprite y(1),1
sprite 1,rndx(64,600),rndx(64,500),1
ROTATE SPRITE 1, rnd(360)

play sound 1
play sound 2
click = 1
EndIf
Else
click = 0
EndIf
Else
If mouseclick()=1
If click = 0

play sound 1
click = 1
EndIf
Else
click = 0
EndIf
EndIf

If sprite x(1) < 0 or sprite y(1) < 0 or sprite x(1) > 800 or sprite y(1) > 600
sprite 1,rndx(64,600),rndx(64,500),1
ROTATE SPRITE 1, rnd(360)
Score = Score - 50
EndIf

If GameTime > 60000
Goto _scroteloop
EndIf

If GameTime > 10000
spriteMoveSpeed# = 0.6
EndIf

play sprite 1,1,3,300
MOVE SPRITE 1, spriteMoveSpeed#

text 10,10, "Очки : " + str$(Score) + " $"
text 10,30, "Время игры :" + str$(GameTime/1000)

GameTime = abs( Time - timer() )

sprite 2,aimX,aimY,2
aimX = mouseX()
aimY = mouseY()

Sync
LOOP

Function OffSetSprite_to_M(spriteOffSet)
Offset Sprite spriteOffSet,sprite width(spriteOffSet)/2,sprite height(spriteOffSet)/2
EndFunction

function rndx(min,max)
value=rnd(max-min)+min
endfunction value

_scroteloop:
tupESC = 1
HIDE ALL SPRITES
loop music 1
DO

text 150,150, "Очки : " + str$(Score) + " $"
text 150,170, "Всего жуков убито :" + str$(BugsKilled)
text 150,190, "Для перезапуска игры жми пробел."

If spacekey()=1 then goto _gameLoop

If escapekey()=1
If tupESC = 0
goto _startscreanloop
tupESC = 1
EndIf
Else
tupESC = 0
EndIf

Sync
LOOP

_startscreanloop:

HIDE ALL SPRITES
newgameFlag = 1
loop music 1
DO
SET TEXT SIZE 50
INK RGB(255,rnd(255),rnd(255)),RGB(255,255,255)
text SCREEN WIDTH()/2,SCREEN HEIGHT()/2, "The Bugs Killer"

If newgameFlag = 1
SET TEXT SIZE 12
INK RGB(rnd(255),rnd(255),rnd(255)),RGB(255,255,255)
text 150,150, "Начать игру"
INK RGB(150,150,150),RGB(255,255,255)
text 150,170, "Выход"
If spacekey()=1 then goto _gameLoad
EndIf

If newgameFlag = 0
SET TEXT SIZE 12
INK RGB(150,150,150),RGB(255,255,255)
text 150,150, "Начать игру"
INK RGB(rnd(255),rnd(255),rnd(255)),RGB(255,255,255)
text 150,170, "Выход"
If spacekey()=1 then end
EndIf

If upkey()=1 then newgameFlag = 1
If downkey()=1 then newgameFlag = 0

Sync
LOOP



--------------------
Scio me nihil scire

Function OffSetSprite_to_M(spriteOffSet)
Offset Sprite spriteOffSet,sprite width(spriteOffSet)/2,sprite height(spriteOffSet)/2
EndFunction
Перейти в начало страницы
 
+Цитировать сообщение
Anjimo
сообщение 16.9.2010, 20:18
Сообщение #2


Активный участник
***

Группа: Пользователи
Сообщений: 560
Регистрация: 14.6.2008
Пользователь №: 9848



Неплохая идея делать такие уроки.
Вопрос: почему "sync rate 240"???
Мне кажется имеет смысл либо делать не больше 60ти, либо совсем отключать лимит кадров


--------------------
Перейти в начало страницы
 
+Цитировать сообщение
Vova
сообщение 16.9.2010, 21:46
Сообщение #3


Активный участник
***

Группа: Пользователи
Сообщений: 569
Регистрация: 27.8.2009
Из: Москва
Пользователь №: 65609



Anjimo Честно говоря не помню откуда взялось именно это число...
Макс - это только первая часть, завтра будет вторая, можно будет жука реанимировать...


--------------------
Scio me nihil scire

Function OffSetSprite_to_M(spriteOffSet)
Offset Sprite spriteOffSet,sprite width(spriteOffSet)/2,sprite height(spriteOffSet)/2
EndFunction
Перейти в начало страницы
 
+Цитировать сообщение
Engineer
сообщение 17.9.2010, 8:28
Сообщение #4


Активный участник
***

Группа: Пользователи
Сообщений: 71
Регистрация: 2.9.2010
Пользователь №: 65662



Цитата(Vova @ 16.9.2010, 22:46) *
Честно говоря не помню откуда взялось именно это число...

от этого числа (ограничения ФПС) напрямую зависит скорость и плавность движения в игре. у меня на работе например на интегрированной intell'овской видеокарте при 30-40 спрайтах на экране (в том числе ГУЙ) ФПС больше 200 не поднимается. если всё движение в игре будет завязано на ФПСе, скорость выполнения на разных машинах будет разной, а это не есть гуд. Я за то, чтобы с самого начала правильно управлять скоростью игры, т.е. через синхронизацию таймером и выставление sync rate 0.
Перейти в начало страницы
 
+Цитировать сообщение
maximilian
сообщение 17.9.2010, 16:33
Сообщение #5


Активный участник
***

Группа: Пользователи
Сообщений: 568
Регистрация: 26.3.2009
Из: EARTH, UKRAINE
Пользователь №: 65574



Клёво.) Вова, ты иконку для тутора нарисовал?
я пытался помочь... честно... вышла ... бяка
Прикрепленный файл  icon.bmp ( 16,43 килобайт ) Кол-во скачиваний: 298
.... *ico - немогу загрузить)))


--------------------
"... Стоя на краю пропасти на одной ноге, можно попасть стрелой не только в цель, но и второй стрелой в первую ещё в полёте... "
Лабироникс © ...отрывок из неизданного.
Перейти в начало страницы
 
+Цитировать сообщение
Anjimo
сообщение 17.9.2010, 20:54
Сообщение #6


Активный участник
***

Группа: Пользователи
Сообщений: 560
Регистрация: 14.6.2008
Пользователь №: 9848



Цитата
Я за то, чтобы с самого начала правильно управлять скоростью игры, т.е. через синхронизацию таймером и выставление sync rate 0.

В перспективе мы же хотим чтобы не только игра шла хорошо, но и чтобы видеокарточка прожила подольше, зачем ее заставлять делать 1000 кадров когда и 60 достаточно? А вот если уже меньше 60 кадров тогда можно и напрямую скорось игры регулировать. Имхо


--------------------
Перейти в начало страницы
 
+Цитировать сообщение
Vova
сообщение 17.9.2010, 21:07
Сообщение #7


Активный участник
***

Группа: Пользователи
Сообщений: 569
Регистрация: 27.8.2009
Из: Москва
Пользователь №: 65609



Клево!!!! Макс... залей в zipе, =)
Anjimo -согласен.
Это урок начального уровня, тут не до ухищрений я старался, что бы все было предельно ясно и понятно для людей которые в первый раз запустят ДБ и решать начать, что то делать.. имхо


--------------------
Scio me nihil scire

Function OffSetSprite_to_M(spriteOffSet)
Offset Sprite spriteOffSet,sprite width(spriteOffSet)/2,sprite height(spriteOffSet)/2
EndFunction
Перейти в начало страницы
 
+Цитировать сообщение
maximilian
сообщение 22.9.2010, 11:04
Сообщение #8


Активный участник
***

Группа: Пользователи
Сообщений: 568
Регистрация: 26.3.2009
Из: EARTH, UKRAINE
Пользователь №: 65574



Вова, в 4-части в Полном листинге ты упустил : if sprite collision(2,1)> 0 ..... endif и теперь где ни кликни жук помирает... да и ещё ремарку перед hide mouse забыл убрать. Я понимаю, что нужно оставлять ученикам поле для фантазии и самостоятельной работы, но.... что бы не запутались поправь.
з.ы. Нужно было запостить в разделе Статьи или Для начинающих. Ну или когда закончишь урок и проведёшь оптимизацию(если понадобиться), тогда и запости туда.
з.ы. 2 а ваще молоток!


--------------------
"... Стоя на краю пропасти на одной ноге, можно попасть стрелой не только в цель, но и второй стрелой в первую ещё в полёте... "
Лабироникс © ...отрывок из неизданного.
Перейти в начало страницы
 
+Цитировать сообщение
maximilian
сообщение 22.9.2010, 11:21
Сообщение #9


Активный участник
***

Группа: Пользователи
Сообщений: 568
Регистрация: 26.3.2009
Из: EARTH, UKRAINE
Пользователь №: 65574



а что делать когда жук за экран вылез?... покумекай... а то он ушол и игра застряла.)))


--------------------
"... Стоя на краю пропасти на одной ноге, можно попасть стрелой не только в цель, но и второй стрелой в первую ещё в полёте... "
Лабироникс © ...отрывок из неизданного.
Перейти в начало страницы
 
+Цитировать сообщение
Vova
сообщение 22.9.2010, 12:49
Сообщение #10


Активный участник
***

Группа: Пользователи
Сообщений: 569
Регистрация: 27.8.2009
Из: Москва
Пользователь №: 65609



Макс поправил, спасибо... на работе пишу а как известно на работе работать надо... happy.gif а я туториалы пишу dry.gif.
Я в общем планирую перетащить это в готовые проекты когда добью до конца эдокий проект само училка для вновь пришедших, а в разделе для новичков я видел тему с вопросом где взять уроки вот туда ссылку и размещу на эту тему.

Сейчас пытаюсь главный экран простенький начертить(легкоусвояемый) - как раз к 5му уроку. rolleyes.gif
Как думаешь звук стоит добавлять??

Цитата
... так легче разобраться

В финальной версии постараюсь все поровнять по максимуму... с отступами и ремарками.
/----------------------------/
Цитата
а оно чё так и было?... я когда в едитор скопировал всё было свалено в кучу...

что в кучу??? отредактировал только вот сейчас, условие забыл да =(, но оно не в кучку было, отступы есть

Цитата
а что делать когда жук за экран вылез?... покумекай... а то он ушол и игра застряла.)))


А об этом в 5й части будет...


--------------------
Scio me nihil scire

Function OffSetSprite_to_M(spriteOffSet)
Offset Sprite spriteOffSet,sprite width(spriteOffSet)/2,sprite height(spriteOffSet)/2
EndFunction
Перейти в начало страницы
 
+Цитировать сообщение
maximilian
сообщение 22.9.2010, 15:08
Сообщение #11


Активный участник
***

Группа: Пользователи
Сообщений: 568
Регистрация: 26.3.2009
Из: EARTH, UKRAINE
Пользователь №: 65574



Звук? Ставь... и шорох жучачьего ползновения и выстрел и чваканье раздавленноко супостата!))))) ...а и на бекграунд музон, что б уж как полное пособие по созданию 2D-шутера!.... хотя можно и не заморачиваться- достаточно показать как поставить музон и звуки выстрелов.... как знаешь.


--------------------
"... Стоя на краю пропасти на одной ноге, можно попасть стрелой не только в цель, но и второй стрелой в первую ещё в полёте... "
Лабироникс © ...отрывок из неизданного.
Перейти в начало страницы
 
+Цитировать сообщение
maximilian
сообщение 24.9.2010, 12:34
Сообщение #12


Активный участник
***

Группа: Пользователи
Сообщений: 568
Регистрация: 26.3.2009
Из: EARTH, UKRAINE
Пользователь №: 65574



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

Прикрепленное изображение


-----отредактировал-------------
гы) у меня там было две Ф вместо двух С в слове Professional - переделал


--------------------
"... Стоя на краю пропасти на одной ноге, можно попасть стрелой не только в цель, но и второй стрелой в первую ещё в полёте... "
Лабироникс © ...отрывок из неизданного.
Перейти в начало страницы
 
+Цитировать сообщение
maximilian
сообщение 24.9.2010, 17:45
Сообщение #13


Активный участник
***

Группа: Пользователи
Сообщений: 568
Регистрация: 26.3.2009
Из: EARTH, UKRAINE
Пользователь №: 65574



Вова.... тут и я запуталси... не то что новоиспечённый кодер. ГЫ) прилепи финальный Соурс-код. Чтоб народ не валновался. angry.gif - убойный смайлик!)
з.ы. кстати ремарки в строчке с кодом глюкают.... (7.5).. спасает '-символ перед рем... перенеси на всяк случай их вверх по старинке


--------------------
"... Стоя на краю пропасти на одной ноге, можно попасть стрелой не только в цель, но и второй стрелой в первую ещё в полёте... "
Лабироникс © ...отрывок из неизданного.
Перейти в начало страницы
 
+Цитировать сообщение
Vova
сообщение 24.9.2010, 22:37
Сообщение #14


Активный участник
***

Группа: Пользователи
Сообщений: 569
Регистрация: 27.8.2009
Из: Москва
Пользователь №: 65609



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


--------------------
Scio me nihil scire

Function OffSetSprite_to_M(spriteOffSet)
Offset Sprite spriteOffSet,sprite width(spriteOffSet)/2,sprite height(spriteOffSet)/2
EndFunction
Перейти в начало страницы
 
+Цитировать сообщение
maximilian
сообщение 27.9.2010, 10:26
Сообщение #15


Активный участник
***

Группа: Пользователи
Сообщений: 568
Регистрация: 26.3.2009
Из: EARTH, UKRAINE
Пользователь №: 65574



Вов, да мне то всё понятно.... но думаю для целевой аудитории немного ... эээ... неразборчиво и сумбурно)


--------------------
"... Стоя на краю пропасти на одной ноге, можно попасть стрелой не только в цель, но и второй стрелой в первую ещё в полёте... "
Лабироникс © ...отрывок из неизданного.
Перейти в начало страницы
 
+Цитировать сообщение
Vova
сообщение 27.9.2010, 11:02
Сообщение #16


Активный участник
***

Группа: Пользователи
Сообщений: 569
Регистрация: 27.8.2009
Из: Москва
Пользователь №: 65609



Это все усталость!!! rolleyes.gif, а так я еще поковыряю может перепишу малость wub.gif


--------------------
Scio me nihil scire

Function OffSetSprite_to_M(spriteOffSet)
Offset Sprite spriteOffSet,sprite width(spriteOffSet)/2,sprite height(spriteOffSet)/2
EndFunction
Перейти в начало страницы
 
+Цитировать сообщение
admin
сообщение 28.9.2010, 18:05
Сообщение #17


Администратор
***

Группа: Главные администраторы
Сообщений: 737
Регистрация: 30.8.2004
Пользователь №: 1



Спасибо на добром слове smile.gif
В развитие инициативы создания уроков,
постараюсь сделать доступнее и короче путь к теме,
для новичков на форуме это может быть актуально.
Перейти в начало страницы
 
+Цитировать сообщение
Vova
сообщение 29.9.2010, 9:17
Сообщение #18


Активный участник
***

Группа: Пользователи
Сообщений: 569
Регистрация: 27.8.2009
Из: Москва
Пользователь №: 65609



Вот вроде на данный момент пока все.. Максим проверь скомпилится у тебя?!
admin - это только начало, сейчас отдохну малость и продолжу.

http://www.youtube.com/watch?v=BTuZbRQL_DQ




--------------------
Scio me nihil scire

Function OffSetSprite_to_M(spriteOffSet)
Offset Sprite spriteOffSet,sprite width(spriteOffSet)/2,sprite height(spriteOffSet)/2
EndFunction
Перейти в начало страницы
 
+Цитировать сообщение
maximilian
сообщение 29.9.2010, 11:07
Сообщение #19


Активный участник
***

Группа: Пользователи
Сообщений: 568
Регистрация: 26.3.2009
Из: EARTH, UKRAINE
Пользователь №: 65574



Пока из того, что заметил.
1. ускорение жука стоит на 60 сек.(а это какбэ поздновато)
2. перезапуск не работает(пауза из игры) .... Show all sprites нужно вставить после _GameLoop:
3. перезапуск по окончании времени - неработает
4... ну и жучара ползает под убитыми комрадес.... поправь

_____________
з.ы. прикольное видео. Поставь на фон листик в клеточку и черкани там на нём чё нить для прикола. (ТАРАКАНЫ В ШКОЛЕ!)


--------------------
"... Стоя на краю пропасти на одной ноге, можно попасть стрелой не только в цель, но и второй стрелой в первую ещё в полёте... "
Лабироникс © ...отрывок из неизданного.
Перейти в начало страницы
 
+Цитировать сообщение
Vova
сообщение 30.9.2010, 15:01
Сообщение #20


Активный участник
***

Группа: Пользователи
Сообщений: 569
Регистрация: 27.8.2009
Из: Москва
Пользователь №: 65609



А листика в клетку у меня нет но обычный я уже прилепил... да чет я где то упустил судя по всему...

Чуть ниже линк на игру...

https://sites.google.com/site/ibinaryway/ra...rects=0&d=1


--------------------
Scio me nihil scire

Function OffSetSprite_to_M(spriteOffSet)
Offset Sprite spriteOffSet,sprite width(spriteOffSet)/2,sprite height(spriteOffSet)/2
EndFunction
Перейти в начало страницы
 
+Цитировать сообщение

2 страниц V   1 2 >
Ответить в данную темуНачать новую тему
1 чел. читают эту тему (гостей: 1, скрытых пользователей: 0)
Пользователей: 0

 



RSS Текстовая версия Сейчас: 25.9.2017, 5:43
 X 
Ссылки на работы форумчан:
1. Cайт по использованию 3D технологий
в образовании

2. 15 Defense. Underwater Battle

3. GlaZ в Steam Greenlight