Чтобы писать карточные игры, нужно прежде всего иметь колоду карт. Этот вопрос решается очень просто,
нужно лишь использовать в проекте библиотечку cards.dll или cards32.dll , обычно одна из этих библиотек уже
присутствует на компе, и используется в играх. По использованию этой библиотечки громадное колличество
публикаций и море исходников, поэтому я не буду на этом останавливаться.
Чтобы написать красивую игрушку использование cards32.dll не поможет,так как карты там примитивные, "рубашек"мало
и размер карт маленький.И вообще приятно со своими картами что-то соорудить
Для себя я выбрал не самый лёгкий путь, но результат идеальный.
Это метод , когда карта рассматривается как обычный спрайт. Для реализации этой идеи сначало я хотел использовать
API функцию BitBlt . По этой ссылочке можете ознакомиться с этой функцией поподробнее,
http://vsokovikov.narod.ru/New_MSDN_API … 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