C++ Builder :: Игрописательство :: Как написать игру за 21 день ?

Главная

Введение

ЛИКБЕЗ
C++ Builder


ЛИКБЕЗ
C++

Глава №1
Глава №2
Глава №3
Глава №4
Глава №5
Глава №6

Исходники
к пособию

Мои исходники

Статьи
&
Книги


Гостевая

Ссылки

About

E-mail

Rambler's Top100


Создай игру на C++Builder за 21 день - Глава №3 (Черновой вариант)
 
Глава №3.

Привет всем! Сегодня вы узнаете, как поменять кругляшки на осмысленные картинки и задать фон для ваших боевых действий.

Немного изменим нашим традициям и создадим совершенно новый проект.

Сперва налепите на форму два Image'a (Image находится на вкладке Additional). А теперь вам предстоит сложная задача – нарисовать вашего героя (в виде сверху). В принципе это может быть человек (или что-то человекоподобное), какое-нибудь животное или машина. К примеру, у меня это самолет.

Самое главное – картинка обязательно должна быть нарисована на черном фоне. Зачем это нужно вы узнаете потом. Необязательно, но очень желательно, чтобы она была не слишком большая и квадратная (для вашего же удобства): обычно в играх используются 32х32, 64Х64, 128х128.

Нарисовали? А теперь в один из Image’ей (например, Image2) загрузите картинку.

Стоп … нет, сначала дайте Image’ам какие-то осмысленные имена, чтобы потом не запутаться. Пускай тот, на котором мы будем рисовать, будет называться - MainImage, а тот, в котором будет ваш человечек – Chel.

После этого, вам нужно зайти в инспектор объектов (F11), найти у Chel’a свойство Picture и кликнуть на него 2 раза. Укажите там свою картинку.

Сделайте этот Image невидимым (установите его Visible=false).

Затем налепим на форму еще кнопочку и пропишем в ней:

MainImage ->Canvas->CopyRect(Rect(0,0,100,100),Chel->Canvas,Rect(0,0,100,100));

Теперь наступил ответственный момент – запускаем наше приложение (F9), нажимаем кнопку и … о чудо … (!!!) из ничего у вас появилась картинка с вашим роботом (мутантом, инопланетянином или еще с какой-нибудь нечистью ?).

Дам небольшие пояснения относительно CopyRect’a. CopyRect – это функция, которая копирует прямоугольный участок изображения из одного графического объекта, на котором можно рисовать (у которого есть свойство Canvas), в другой.

ОЧЕНЬ ВАЖНО !!! Все картинки должны быть в BMP. Если будет, например в формате JPG, то программа запустится, однако работать ничего не будет.

Теперь попробуем тем же макаром нарисовать фон – создайте Image размером побольше и загрузите в него картинку соответственно тоже побольше. Опять же сделайте его невидимым и дайте какое-нибудь осмысленное имя типа Background. Создайте еще одну кнопку с кодом:

MainImage->Canvas->CopyRect(Rect(0,0,500,500),Background->Canvas,Rect(0,0,500,500));

Вот теперь можете запускать. Работает? Да, однако, мы можем заметить один очень и очень неприятный артефакт – так как копируется прямоугольник, а не человечек, вы увидите своего человечка в черном квадрате (как он и был нарисован).

Чтобы это исправить, надо сделать так, чтобы черный цвет воспринимался как прозрачный. Это можно сделать при помощи «маски».

Маска это та же картинка, только заместо черного цвета на ней должен быть белый, а заместо всех остальных – черный. Вы можете получить маску путем нехитрых манипуляций в Paint’e сохранив рисунок под другим именем в монохромном формате, или можете воспользоваться моей программой, написанной специально для этого …

СКАЧАТЬ

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

Сделали маску? Отлично. Налепите еще один Image и подгрузите ее туда. Теперь у вас на форме должно быть четыре Image’a. Один – для окончательного рисования и три других с ресурсами (фон, картинка и маска картинки).

Значит так, чтобы нарисовать картинку на фоне так, чтобы вокруг нее не отображался черный квадрат нужно прописать вместо:

MainImage->Canvas->CopyRect(Rect(0,0,100,100), Chel->Canvas,Rect(0,0,100,100));

следующее:

MainImage ->Canvas->CopyMode = cmSrcAnd;
MainImage ->Canvas->CopyRect(Rect(0,0,100,100), Maska->Canvas, Rect(0,0,100,100));

MainImage ->Canvas->CopyMode = cmSrcPaint;
MainImage ->Canvas->CopyRect(Rect(0,0,100,100), Chel->Canvas, Rect(0,0,100,100));

Попробуйте запустить вашу программу теперь. Работает? Вот и замечательно. Кое-что уже есть. Теперь стало дело за движением. Чтобы не заморачиваться с мышкой сделаем движение стрелочками.

Объявим глобальные переменные x,y. Напоминаю, объявлять их нужно в самом начале кода Unit1.cpp после слов

//---------------------------------------------------------------------------
#include <vcl.h>
#pragma hdrstop

#include "Unit1.h"
//---------------------------------------------------------------------------
#pragma package(smart_init)
#pragma resource "*.dfm"
TForm1 *Form1;

//// здесь можно объявлять глобальные переменные
int x,y; // а вот и они собственной персоной …

Чтобы движение было видно, картинка должна перерисовываться по таймеру например каждые 100 мс. Создадим таймер с таким интервалом. Timer находится во вкладке System.

Щелкните на него 2 раза и напишите:

///* ПРОРИСОВКА ФОНА *////

MainImage->Canvas->CopyRect(Rect(0,0,500,500),Background->Canvas,Rect(0,0,500,500));

///* ПРОРИСОВКА ВАШЕГО ЧЕЛОВЕЧКА *////

MainImage ->Canvas->CopyMode = cmSrcAnd;
MainImage ->Canvas->CopyRect(Rect(x,y,x+100,y+100), Maska->Canvas, Rect(0,0,100,100));

MainImage ->Canvas->CopyMode = cmSrcPaint;
MainImage ->Canvas->CopyRect(Rect(x,y,x+100,y+100), Chel->Canvas, Rect(0,0,100,100));

Теперь код кнопок можно стереть, а самих их удалить.

Движение по стрелочкам мы проходили с вами на первом занятии, а сейчас повторим.

Создайте обработчик события формы OnKeyDown и в нем напишите следующее:

switch(Key)
{
case VK_LEFT : x-=30; break; // влево
case VK_RIGHT : x+=30; break; // вправо
case VK_UP : y-=30; break; // вверх
case VK_DOWN : y+=30;; break; // вниз
}

Теперь запустите программу, понажимайте стрелочки - у вас должно все работать. Если что-то не работает, то скорее всего вы не удалили кнопки на форме. Если они вам понравились, и вы не хотите их удалять поставьте им свойство TabStop=false;

Все бы хорошо, да только выглядит как-то нереально – человек не идет, а летает. Даже не двигает ногами. Проблема? Да, но не для нас, жестоких программеров ?.

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

Ну, суть, я думаю, уловили. Нам надо сделать что-то наподобие этого. Нарисовать хотя бы два кадра вашего монстра (или уж не знаю, что у вас там). Между прочим, задача упрощена до минимума – один кадр у вас уже есть. Осталось нарисовать еще один. Если у вас нарисован человечек, советую поменять как-нибудь положение его рук и ног. Для примера вы можете посмотреть моего человечка из старенькой игры tl-survival. Чтобы вам не качать всю игру я выложил его отдельно (СКАЧАТЬ). Кстати, там не 2 положения, а целых 8 (тогда я еще не знал, как можно программно повернуть изображение).

/* ПЕРЕКУР */

Как продвигаются дела? Нарисовали 2-е положение спрайта? Что такое спрайт? Ну, собственно то, что мы делаем и есть спрайт. А маску ему на маскарад не забыли? Ну тогда поехали: налепите на форму еще две Имаги и придайте им опять же осмысленные названия. Возьмите это в привычку - сейчас это кажется ненужным, но в дальнейшем, это вам очень пригодится.

На данный момент в таймере мы имеем:

///* ПРОРИСОВКА ФОНА *////

MainImage->Canvas->CopyRect(Rect(0,0,500,500),Background->Canvas,Rect(0,0,500,500));

///* ПРОРИСОВКА ВАШЕГО ЧЕЛОВЕЧКА *////

MainImage ->Canvas->CopyMode = cmSrcAnd;
MainImage ->Canvas->CopyRect(Rect(x,y,x+100,y+100), Maska->Canvas, Rect(0,0,100,100));

MainImage ->Canvas->CopyMode = cmSrcPaint;
MainImage ->Canvas->CopyRect(Rect(x,y,x+100,y+100), Chel->Canvas, Rect(0,0,100,100));

Надо как-то сделать, чтобы два изображения человечка как-то чередовались. Самое логичное – это завести переменную флажок, которая будет показывать, какой у нас сейчас кадр. Т.к. кадра у нас только 2 можно завести булевскую переменную. Булевская переменная, напомню, может содержать 0 или 1 и ничего более.

Объявите глобально (как это сделать, читайте выше, когда мы объявляли x и y):

bool ANIM;

В начале Таймера пропишите:

If(ANIM==true)
ANIM=false;
else
ANIM=true

Можно и покороче ?

ANIM=!ANIM;

Теперь наш текст таймера станет приблизительно таким:

ANIM=!ANIM;

///* ПРОРИСОВКА ФОНА *////

MainImage->Canvas->CopyRect(Rect(0,0,500,500),Background->Canvas,Rect(0,0,500,500));

///* ПРОРИСОВКА ВАШЕГО ЧЕЛОВЕЧКА *////

if(ANIM)
{
MainImage ->Canvas->CopyMode = cmSrcAnd;
MainImage ->Canvas->CopyRect(Rect(x,y,x+100,y+100), Maska->Canvas, Rect(0,0,100,100));

MainImage ->Canvas->CopyMode = cmSrcPaint;
MainImage ->Canvas->CopyRect(Rect(x,y,x+100,y+100), Chel->Canvas, Rect(0,0,100,100));
}
else
{
MainImage ->Canvas->CopyMode = cmSrcAnd;
MainImage ->Canvas->CopyRect(Rect(x,y,x+100,y+100), Maska2->Canvas, Rect(0,0,100,100));

MainImage ->Canvas->CopyMode = cmSrcPaint;
MainImage ->Canvas->CopyRect(Rect(x,y,x+100,y+100), Chel2->Canvas, Rect(0,0,100,100));
}

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

Если у вас что-то не получилось вы можете скачать рабочий пример №10

Удачи!

 

 

 

 
 
Hosted by uCoz