|
BitBlt или PaintPicture для создания карточных игрСправочная информация по методу PaintPicture PaintPicture.rtf!!! Чтобы писать карточные игры, нужно прежде всего иметь колоду карт. Этот вопрос решается очень просто, нужно лишь использовать в проекте библиотечку cards.dll или cards32.dll , обычно одна из этих библиотек уже присутствует на компе, и используется в играх. По использованию этой библиотечки громадное колличество публикаций и море исходников, поэтому я не буду на этом останавливаться. Чтобы написать красивую игрушку использование cards32.dll не поможет,так как карты там примитивные, "рубашек"мало и размер карт маленький.И вообще приятно со своими картами что-то соорудить :) Для себя я выбрал не самый лёгкий путь, но результат идеальный. Это метод , когда карта рассматривается как обычный спрайт. Для реализации этой идеи сначало я хотел использовать API функцию BitBlt . По этой ссылочке можете ознакомиться с этой функцией поподробнее, http://vsokovikov.narod.ru/New_MSDN_API/Bitmaps/fn_bitblt.htm к тому же я в свою демку включил эту функцию, так что там всё понятно. Спрайт создаётся двумя вызовами, сначало выводится маска с наложением по "И", а затем картинка карты с наложением по "ИЛИ", при этом маска должна быть чёрной на белом фоне, а сама карта должна быть на чёрном фоне!!! По идее у карты надо закрасить чёрным только уголки. Маска одна на всю колоду. Ещё надо сделать одну карту пустой, только залитую фоновым цветом и конечно же с чёрными уголками, эта карта будет использоваться в дальнейшем для удаления карты! Но я всё таки в своих проектах API функцию BitBlt не использую, так как в самом VB есть более мощный и удобный инструмент, это метод - PaintPicture ! Он чуток медлительней чем BitBlt , но скорость то при карточной игре не нужна, это ведь не шутер по летающим тарелкам и не гоночное дерби. Ну приступим к написанию демки. Для начала на форме разместим три пикчербокса и две кнопки. пикчерсы должны иметь размеры картинок карт!!! На форме и пикчерсах установите ScaleMode в 3-pixel, а свойство AutoRedraw в true. У пикчерсов ещё установите BorderStyle в 0 !!! Установите у формы BackColor нужного цвета. ( я уже писал чуть выше , что нужна третья карта цвета фона). Теперь напишем код. Прежде всего декларация функции BitBlt Private Declare Function BitBlt Lib "gdi32" (ByVal hDestDC As Long, ByVal x As Long, _ ByVal y As Long, ByVal nWidth As Long, ByVal nHeight As Long, ByVal hSrcDC As Long, _ ByVal xSrc As Long, ByVal ySrc As Long, ByVal dwRop As Long) As Long А теперь в наши три пикчерса зальём три наши картинки, в первый пикчерс зальём маску, во второй карту, а в третий пустую карту. Private Sub Form_Load() Picture1.Picture = LoadPicture(CurDir + "\mackcfrd01.bmp") Picture2.Picture = LoadPicture(CurDir + "\card01.bmp") Picture3.Picture = LoadPicture(CurDir + "\mackcfrd02.bmp") End Sub В реальной программе надо ещё свойство Visible не забыть установить в false . Но в демке для наглядности всё как есть оставил. Далее по нажатию кнопки выведем карту два раза, чтобы продемонстрировать оба метода! Private Sub Command1_Click() BitBlt Form1.hDC, 100, 10, Picture1.ScaleWidth, Picture1.ScaleHeight, Picture1.hDC, 0, 0, vbSrcAnd BitBlt Form1.hDC, 100, 10, Picture2.ScaleWidth, Picture2.ScaleHeight, Picture2.hDC, 0, 0, vbSrcPaint Form1.PaintPicture Picture1, 200, 20, Picture1.ScaleWidth, Picture1.ScaleHeight, , , , , vbSrcAnd Form1.PaintPicture Picture2, 200, 20, Picture2.ScaleWidth, Picture2.ScaleHeight, , , , , vbSrcPaint Form1.Refresh End Sub Функция BitBlt предполагает, что надо перерисовать форму Form1.Refresh, я тестироват без Form1.Refresh и у меня всё работало) Результат того, что получилось, смотрите ниже на картинке!!! А теперь о том как стереть карту. Всё конечно очень просто, для этого мы и делали третью карту цвета фона, так что сначало выводим эту карту, а затем выводим карту которую она прикрывала. в общем всё как в обычной растровой графике, никакого велосипеда я не изобретал. Private Sub Command2_Click() Form1.PaintPicture Picture1, 200, 20, Picture1.ScaleWidth, Picture1.ScaleHeight, , , , , vbSrcAnd Form1.PaintPicture Picture3, 200, 20, Picture3.ScaleWidth, Picture3.ScaleHeight, , , , , vbSrcPaint BitBlt Form1.hDC, 100, 10, Picture1.ScaleWidth, Picture1.ScaleHeight, Picture1.hDC, 0, 0, vbSrcAnd BitBlt Form1.hDC, 100, 10, Picture2.ScaleWidth, Picture2.ScaleHeight, Picture2.hDC, 0, 0, vbSrcPaint Form1.Refresh End Sub В большинстве пасьянсов можно вообще обойтись без вывода карт с маской.Так как карты там накладываются лишь с небольшим отступом сверху. Можно для каждой карты сделать свой пикчербокс, а уголки карт которые должны быть цвета фона просто зарисовать используя PSet,Line и любой другой способ на любителя.) Ну вот с картами разобрались, и на последок несколько советов об организации собственно колоды. Я свою колоду селал в виде отдельных карт, разместил их в корневой директории и подгружаю нужную карту по её названию. Названия карт сделал числовыми. с 1 по 52 это карты, потом 2 джокера(чёрный и красный), затем маска, несколько пустых карт разного цвета( под разный фон формы) и много карт рубашек. Вообще я люблю сам рисовать рубашки для карт. Первые 52 карты логически рассортированы по четвёркам одного достоинства но разных мастей, это позволяет элементарно применять математику, для определения по номеру , какая это карта и наоборот. хотя это очень редко надо,далеко не во всех играх. Ещё такая организация помогает в более эффективной тасовке, но это уже отдельная тема. Я реализую тасовку через генерацию трёх псевдослучайных чисел , первое в пределах от 10 до 20 -колличество перестановок в цикле. второе число от 2 до 5 - шаг внутри перестановок, то есть допустим шаг 3, то есть я буду менять текущую карту с третьей вверх. Третье число это шаг внутри тасовки, то есть переход на новый элемент, это число в диапазоне от 3 до 9, если достигнут конец массива, то переход в начало массива + смещение в 1. Если в игре несколько раздач, то я начинаю тасовку с предыдущего состояния массива. Вот улучшенный вариант моего алгоритма тасовки который я описал, немного пределы случайных чисел подправил и перед перебором масива в цикле сразу три пары меняю с хвоста массива. В общем это кусок одной из моих программуль, всё работает великолепно. Dim masiw(52) As Integer Dim r1, r2, r3, swpp, n1, n2 As Integer Private Sub initmasiw() Dim i As Integer For i = 0 To 51 masiw(i) = i + 1 Next i End Sub Private Sub tasowwka() Randomize r1 = Int((Rnd * 10) + 10) r2 = Int((Rnd * 4) + 2) r3 = Int((Rnd * 8) + 4) swpp = masiw(51) masiw(51) = masiw(r1) masiw(r1) = swpp swpp = masiw(50) masiw(50) = masiw(r2) masiw(r2) = swpp swpp = masiw(49) masiw(49) = masiw(r3) masiw(r3) = swpp Dim k As Integer n1 = 0 n2 = 0 For k = 0 To r1 If (n1 > 51) Then n1 = n1 - 50 n2 = n2 + r2 If (n2 > 51) Then n2 = r1 + r3 swpp = masiw(n1) masiw(n1) = masiw(n2) masiw(n2) = swpp n1 = n1 + r3 Next k End Sub Удачного вам написания карточных игр!!! © ЯКВ-мистери 2000-2014 kestrens@mail.ru
|