Игра змейка на vbnet 2003

 
0
 
.NET
ava
WWW123 | 05.10.2016, 11:11
Здравствуйте.
Как сделать поворот змейки не налево и направо, а по и против часовой стрелки?
Ответы (33)
ava
Garmahis | 05.10.2016, 12:10 #
Точно так же как поворот налево и направо :) только против и по часовой стрелке... 
ava
WWW123 | 05.10.2016, 12:46 #
Как сделать чтобы при движении налево и при нажатии клавиши влево, змейка двигалась вниз, то есть против часовой стрелки?
ava
Garmahis | 05.10.2016, 14:03 #
в каждом if, где вы сейчас определяете какая клавиша нажата анализировать текущие значения x и y и уже на основании этого устанавливать новые значения.
ava
WWW123 | 05.10.2016, 16:45 #

   Dim x, y As Integer

    Private Sub Timer1_Tick(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles Timer1.Tick
        PictureBox1.Left = PictureBox1.Left + x
        PictureBox1.Top = PictureBox1.Top + y
    End Sub

    Private Sub Form1_Load(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles MyBase.Load
        y = -2                 'движение после загрузки
        Timer1.Enabled = True
    End Sub

    Private Sub Form1_KeyDown(ByVal sender As Object, ByVal e As System.Windows.Forms.KeyEventArgs) Handles MyBase.KeyDown
        If e.KeyCode = Keys.Left And y = -2 Then x = -2 : y = 0
        If e.KeyCode = Keys.Left And y = 2 Then x = 2 : y = 0
        If e.KeyCode = Keys.Left And x = 2 Then x = 0 : y = -2
        If e.KeyCode = Keys.Right Then x = 2 : y = 0
        If e.KeyCode = Keys.Up Then x = 0 : y = -2
        If e.KeyCode = Keys.Down Then x = 0 : y = 2

    End Sub


Когда изменил третий If , программа стала работать неправильно. Перескакивает и выполняет следующий оператор If
ava
WWW123 | 06.10.2016, 07:37 #
Исходник.
ava
WWW123 | 06.10.2016, 13:07 #
змейка движется правильно. Добавил ElseIf
ava
WWW123 | 06.10.2016, 13:31 #
Как сделать хвост змеи?
ava
Garmahis | 06.10.2016, 13:47 #
Я правильно понимаю что каждая клеточка тела змеи у тебя отдельный PictureBox? Если так то просто переносишь последний в то место куда змея должна шагнуть. Если змея упирается головой в PictureBox еды то, он просто становиться головой и в эту итерацию змея не двигается. 
ava
WWW123 | 06.10.2016, 16:35 #
Спасибо, Garmahis. Сделал хвост. Как сделать чтобы игра прекращалась при ударении о границы формы? У меня не получается.


    Dim x, y, x1, y1, n As Integer

    Private Sub Timer1_Tick(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles Timer1.Tick
        PictureBox1.Left = PictureBox1.Left + x
        PictureBox1.Top = PictureBox1.Top + y
        PictureBox2.Left = PictureBox1.Left + x1
        PictureBox2.Top = PictureBox1.Top + y1

    End Sub

    Private Sub Form1_Load(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles MyBase.Load
        y = -2                 'движение после загрузки
        y1 = y + 20            'показываем хвост
        Timer1.Enabled = True
    End Sub

    Private Sub Form1_KeyDown(ByVal sender As Object, ByVal e As System.Windows.Forms.KeyEventArgs) Handles MyBase.KeyDown
        If e.KeyCode = Keys.Left And y = -2 Then
            x = -2 : y = 0
        elseIf e.KeyCode = Keys.Left And y = 2 Then
            x = 2 : y = 0
        ElseIf e.KeyCode = Keys.Left And x = 2 Then
            x = 0 : y = -2
        ElseIf e.KeyCode = Keys.Left And x = -2 Then
            x = 0 : y = 2
        End If
        If e.KeyCode = Keys.Right And y = -2 Then
            x = 2 : y = 0
        ElseIf e.KeyCode = Keys.Right And y = 2 Then
            x = -2 : y = 0
        ElseIf e.KeyCode = Keys.Right And x = 2 Then
            x = 0 : y = 2
        ElseIf e.KeyCode = Keys.Right And x = -2 Then
            x = 0 : y = -2
        End If

        If x = -2 Then
            x1 = x + 20 : y1 = y
        End If
        If x = 2 Then
            x1 = x - 20 : y1 = y
        End If
        If y = -2 Then
            y1 = y + 20 : x1 = x
        End If
        If y = 2 Then
            y1 = y - 20 : x1 = x
        End If

        

    End Sub
  
    Sub выход_за_границы()
        If x > Width Then
            Timer1.Enabled = False
        End If
        If y > Height Then
            Timer1.Enabled = False
        End If
    End Sub


    Private Sub PictureBox1_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles PictureBox1.Click

    End Sub
ava
Garmahis | 06.10.2016, 18:14 #
если (x, y <= 0) или (x >= Width) или (y >= Height)  значит конец так же я так понимаю если новые координаты головы совпали с координатами другой части змеи тоже конец.   
ava
WWW123 | 06.10.2016, 18:51 #
Я так и делаю. Змейка или прилипает к краю и движется только по краю или движется нормально, но в обоих случаях не реагирует на Timer1.Enabled = False
ava
WWW123 | 06.10.2016, 19:34 #
Сделал . Игра останавливается.
ava
jsharp36 | 07.10.2016, 04:20 (Отредактирован 07.10.2016 04:43) #
Не хочется разбираться в этом адском языке и коде. Но если я понял задачу. Движется куда-то змея. Надо ее поворачивать относительно движения за или против стрелки.

Чуть простой математики и не надо этих ифов.

Давайте условимся направление помечать цифрой. По кругу, от 0 до 3.
Например, как мы привыкли в математике, от угла 0 и против часовой стрелки. (Это не важно на самом деле как, главное по кругу).
Вправо - 0, вверх - 1, влево - 2, вниз - 3.

Теперь, голова змеи всегда движется уже в каком-то направлении. И поворот ее клавишами вправо или влево будет значит к текущему направлению добавить +1 или -1. Желательно в этом же коде сразу проверить на выход за пределы и устанавливать нужное. Т.е. если стало значение -1, то сделать 3. Если +4, делает 0. Хотя подозреваю, работать будет и без этого, (на ходу придумываю алгоритм).

С направлениями определились? Дальше можете написать любимые ифы и в зависимости от направления, выставлять x и y: +2, 0, -2.

Что сложного вообще, вроде очевидно же?

Но и тут можно без ифов обойтись, чтобы красивее код был. Ифы портят код.

В VB деление по модулю Mod. Погуглил.

Допустим направление обозначим как d
Нам надо для икса, чтобы 0 и 2 стало 2 и -2. А 1 и 3 стали 0. Напряжем чуть мозг и:


x = 2 * ((1 - d) Mod 2) * (1 - d)
y = 2 * (d Mod 2) * (d - 2)


Тут я считаю, что координаты, как обычно в компьютере, идут с верхнего левого угла. Т.е. вверх y уменьшается.
Да, работать не будет, если не устанавливать насильно вхождение в диапазон. Можно и без ифов вообще обойдиcь, но надо тогда делить по модулю на 4.
Т.е. вот там, где ифы, чтобы в диапазон вернуть, можно прямо там писать без ифов:

d = d Mod 4
ava
WWW123 | 07.10.2016, 08:30 #
Как сделать чтобы змейка двигалась по сетке? И чтобы яблоки возникали тоже в клетках сетки. Или как ещё сделать чтобы уровень движения змейки и уровень яблок совпадал?
ava
Garmahis | 07.10.2016, 10:39 #
jsharp36 Расскажи про ООП :)))
WWW123 У тебя есть размер одной клетки в пикселях. Значит ты знаешь сколько всего клеток на форме скажем махX и MaxY. Таким образом при генерации яблока ты генерируешь случайное число от 0 до maxX-1 и второе случайное число от 0 до maxY-1. Умножаешь на ширину одной клетки в пикселях и получаешь координаты в пикселях.
ava
WWW123 | 07.10.2016, 13:19 #
Размер клетки у меня 8x8. Форма у меня 304х304. Клеток 38х38. Голова змеи 16х16. Размер яблока 16х16. При генерации яблока я генерирую числа от 0 до 38 и от 0 до 38. Умножаем на 8. Получаем координаты в пикселях. А как привязать координаты яблока и координаты змеи?
ava
Garmahis | 07.10.2016, 13:34 #
Так. Погоди. У тебя получается змея и яблоко занимают 4 клетки??? Какой в этом смысл? Насколько я понимаю логику этой игры один сегмент змеи = 1 клетке. и яблоко = 1 клетке. И змея каждую итерацию перемещается на одну клетку.
ava
WWW123 | 07.10.2016, 13:39 #
Крупнее лучше видно и красивее. Змея движется по таймеру. 
ava
Garmahis | 07.10.2016, 13:53 #
Тогда делай клетку тоже 16х16
ava
WWW123 | 07.10.2016, 14:02 #
Сделал клетку 16х16. Что дальше?
ava
Garmahis | 07.10.2016, 14:25 #
ну вот теперь у тебя 19 клеток.
И так алгоритм следующий.
1. у тебя всего 361 клетка. Ты должен сравнить число существующих PictureBox, которые являются телом змеи и уже созданными яблоками и убедиться что их число < 361.
2. Получаешь координаты x и y:  случайное число от 0 до 18 * 16. Дальше ты сравниваешь их с координатами существующих PictureBox, которые являются телом змеи и уже созданными яблоками и убедиться что они не совпадают. Если совпадают то повторяешь генерацию еще раз.
3. Создаешь новый PictureBox по этим координатам.
Вот это простейший алгоритм. На самом деле он ущербен. Так как по мере увеличения занятых клеток генерация новых координат будет занимать все больше и больше времени. Какие способы решения? Их множество. Например ты можешь создать массив по всем клеткам 1 - клетка занята, 0 - свободна. Дальше ты генерируешь случайное число от 1 до количества свободных клеток. А дальше смотришь в твоем массиве какая эта клетка. Это гарантирует что он всегда с первого раза будет попадать в свободную клетку. Именно по этому для решения этих задач предпочтителен объектно оринтированый подход. 
ava
WWW123 | 07.10.2016, 14:56 #
Вот исходник. Змея и яблоко на разных уровнях.



Dim x, y, x1, y1, n As Integer

    Private Sub Timer1_Tick(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles Timer1.Tick

        PictureBox1.Left = PictureBox1.Left + x   'движем голову
        PictureBox1.Top = PictureBox1.Top + y
        PictureBox2.Left = PictureBox1.Left + x1  'движем хвост
        PictureBox2.Top = PictureBox1.Top + y1
        If PictureBox1.Left + 35 >= Width Then Timer1.Enabled = False 'проверка выхода за границу
        If PictureBox1.Left <= 0 Then Timer1.Enabled = False
        If PictureBox1.Top + 55 >= Height Then Timer1.Enabled = False
        If PictureBox1.Top <= 0 Then Timer1.Enabled = False
        If PictureBox1.Top <= 0 Then Label1.Visible = True 'игра окончена
        If PictureBox1.Top + 55 >= Height Then Label1.Visible = True
        If PictureBox1.Left <= 0 Then Label1.Visible = True
        If PictureBox1.Left + 35 >= Width Then Label1.Visible = True
    End Sub

    Private Sub Form1_Load(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles MyBase.Load
        y = -2                 'движение после загрузки
        y1 = y + 20            'показываем хвост
        Timer1.Enabled = True
        Randomize()
        PictureBox0.Left = (272 * Rnd())     'добавляем яблоко
        PictureBox0.Top = (256 * Rnd())
    End Sub

    Private Sub Form1_KeyDown(ByVal sender As Object, ByVal e As System.Windows.Forms.KeyEventArgs) Handles MyBase.KeyDown
        If e.KeyCode = Keys.Left And y = -2 Then
            x = -2 : y = 0
        ElseIf e.KeyCode = Keys.Left And y = 2 Then
            x = 2 : y = 0
        ElseIf e.KeyCode = Keys.Left And x = 2 Then
            x = 0 : y = -2
        ElseIf e.KeyCode = Keys.Left And x = -2 Then
            x = 0 : y = 2
        End If
        If e.KeyCode = Keys.Right And y = -2 Then
            x = 2 : y = 0
        ElseIf e.KeyCode = Keys.Right And y = 2 Then
            x = -2 : y = 0
        ElseIf e.KeyCode = Keys.Right And x = 2 Then
            x = 0 : y = 2
        ElseIf e.KeyCode = Keys.Right And x = -2 Then
            x = 0 : y = -2
        End If

        If x = -2 Then
            x1 = x + 20 : y1 = y
        End If
        If x = 2 Then
            x1 = x - 20 : y1 = y
        End If
        If y = -2 Then
            y1 = y + 20 : x1 = x
        End If
        If y = 2 Then
            y1 = y - 20 : x1 = x
        End If



    End Sub
ava
Garmahis | 07.10.2016, 15:49 #
Не не так. Зачем тебе двигать голову? Ты собираешься двигать каждую часть змеи даже когда она будет состоять из 300 сегментов? Я же писал переноси просто хвост и ставь его перед головой. Тебе надо написать функцию, которая бы возвращала бы тебе PictureBox головы или хвоста. Ты получаешь PictureBoxFirst и PictureBoxLast. Кроме того тебе нужна функция, которая определяет есть ли в координатах яблоко. Если SearchApple(PictureBoxFirst.Left +x, PictureBoxFirst.Top +y) тогда это яблоко становиться телом змеи и шаг заканчивается. Если нет то проверяешь что PictureBoxFirst.Left +x, PictureBoxFirst.Top +y не выходят за границу поля и не втыкаются в тело змеи. Если да то конец игры. А дальше просто PictureBoxLast.Left = PictureBoxFirst.Left + x  PictureBoxLast.Top = PictureBoxFirst.Top +y
Вот и все. змея сделала шаг.
ava
WWW123 | 07.10.2016, 16:26 #
Мне сначала нужно сделать чтобы змейка совпадала по уровню с яблоком.

ava
Garmahis | 07.10.2016, 17:45 #
А как она может не совпадать?
ava
WWW123 | 07.10.2016, 17:53 #
Я же загрузил rar файл.
ava
Garmahis | 07.10.2016, 18:00 #
Я не могу запустить проект :) Я на маке...
ava
jsharp36 | 07.10.2016, 23:57 (Отредактирован 07.10.2016 23:58) #
Т.е. если не ясное субмурное описание, такой код, приблизительно, на VB. Куда надо вставить уже разберетесь. d - это текущее направление змеи (0, 1, 2, 3)


If e.KeyCode = Keys.Left Then
   d = d + 1
elseIf e.KeyCode = Keys.Right Then
   d = d - 1
endIf

d = d Mod 4
x = 2 * ((1 - d) Mod 2) * (1 - d)
y = 2 * (d Mod 2) * (d - 2)


Где-то так. Не проверял правда. Если есть ошибки, скажите. На VB не пишу.
ava
jsharp36 | 08.10.2016, 00:07 (Отредактирован 08.10.2016 00:08) #
Цитата

  Garmahis Расскажи про ООП :))) 
  


Это вроде, тут никому не нужна красота и простота? Жаль, конечно, пойду я )))

А про ООП ничего не расскажу. Г редкое, но приходится.

Хотя где-то со змейкой могло бы помочь ООП. Но я бы советовал спрыгивать с VB еще до изучения ООП.
ava
WWW123 | 08.10.2016, 16:53 #
Всё. Сделал.Уровень яблока и змеи совпадают.
ava
WWW123 | 09.10.2016, 06:12 #
Как сделать чтобы змея ела яблоко? Она ест когда разворачиваешься на яблоке. А если просто двигаешься по яблоку, то не ест.
ava
WWW123 | 09.10.2016, 08:55 #
Сделал. Змея ест яблоко.
ava
WWW123 | 09.10.2016, 13:14 #
как сделать чтобы змея удлинялась про поедании яблока?
Зарегистрируйтесь или войдите, чтобы написать.
Фирма дня
Вы также можете добавить свою фирму в каталог IT-фирм, и публиковать статьи, новости, вакансии и другую информацию от имени фирмы.
Подробнее
Участники
advanced
Отправить