蛇永远死了 [英] The snake always dies

查看:81
本文介绍了蛇永远死了的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

所以当我开始游戏并按下按钮1时,蛇立即死亡,为什么会这样?



Ps:我想在图片框上做到br />

So when i start the game and press the button 1, the snake dies immediately, why is that so?

Ps: ive to do it on picturebox

Public Class Form1

#Region "Snake"
    Dim snake(1000) As PictureBox
    Dim comp_cobra As Integer = -1
    Dim esquerda_direita As Integer = 0
    Dim cima_baixo As Integer = 0


    Private Sub cabeça()
        comp_cobra += 1
        snake(comp_cobra) = New PictureBox
        With snake(comp_cobra)
            .Height = 10
            .Width = 10
            .BackColor = Color.Black
            .Top = (pb1.Top + pb1.Bottom) / 2
            .Left = (pb1.Left + pb1.Right) / 2
        End With
        Me.Controls.Add(snake(comp_cobra))
        snake(comp_cobra).BringToFront()

        compi_cobra()
    End Sub

    Private Sub Form1_KeyPress(sender As Object, e As KeyPressEventArgs) Handles Me.KeyPress

        Select Case e.KeyChar
            Case "d"
                esquerda_direita = 10
                cima_baixo = 0
            Case "a"
                esquerda_direita = -10
                cima_baixo = 0
            Case "w"
                esquerda_direita = 0
                cima_baixo = -10
            Case "s"
                esquerda_direita = 0
                cima_baixo = 10

        End Select
    End Sub

    Private Sub Form1_Load(sender As Object, e As EventArgs) Handles Me.Load
        
    End Sub

    Private Sub compi_cobra()
        comp_cobra += 1
        snake(comp_cobra) = New PictureBox
        With snake(comp_cobra)
            .Height = 10
            .Width = 10
            .BackColor = Color.Black
            .Top = snake(comp_cobra - 1).Top
            .Left = snake(comp_cobra - 1).Left + 10
        End With
        Me.Controls.Add(snake(comp_cobra))
        snake(comp_cobra).BringToFront()
    End Sub
    Private Sub tsnake_Tick(sender As Object, e As EventArgs) Handles Timer1.Tick
        For i = comp_cobra To 1 Step -1
            snake(i).Top = snake(i - 1).Top
            snake(i).Left = snake(i - 1).Left
        Next
        snake(0).Top += cima_baixo
        snake(0).Left += esquerda_direita
        colide_parede()
        comer_comida()
        colide_cobra()
    End Sub
#End Region

#Region "Colisão"
    Private Sub colide_parede()
        If snake(0).Left < pb1.Left Then
            Timer1.Stop()
            MsgBox("Perdeste Fagg")
        End If
        If snake(0).Right > pb1.Right Then
            Timer1.Stop()
            MsgBox("Perdeste Fagg")
        End If
        If snake(0).Bottom > pb1.Bottom Then
            Timer1.Stop()
            MsgBox("Perdeste Fagg")
        End If
        If snake(0).Top < pb1.Top Then
            Timer1.Stop()
            MsgBox("Perdeste Fagg")
        End If
    End Sub
    Private Sub colide_cobra()
        For i = 1 To comp_cobra
            If snake(0).Bounds.IntersectsWith(snake(i).Bounds) Then
                Timer1.Stop()
                MsgBox("Perdeste")
            End If
        Next
    End Sub
#End Region

#Region "comida"
    Dim mouse As PictureBox
    Dim r As Random = New Random
    Private Sub create_mouse()
        mouse = New PictureBox
        With mouse
            .Width = 10
            .Height = 10
            .BackColor = Color.Red
            .Top = r.Next(pb1.Top, pb1.Left)
            .Left = r.Next(pb1.Left, pb1.Right)
        End With
        Me.Controls.Add(mouse)
        mouse.BringToFront()


    End Sub
    Private Sub comer_comida()
        If snake(0).Bounds.IntersectsWith(mouse.Bounds) Then
            compi_cobra()
            mouse.Top = r.Next(pb1.Top, pb1.Bottom - 10)
            mouse.Left = r.Next(pb1.Left, pb1.Right - 10)
            Label2.Text = Label2.Text + 10


        End If

    End Sub
#End Region

    Private Sub Button1_Click(sender As Object, e As EventArgs)


    End Sub

    Private Sub pb1_Click(sender As Object, e As EventArgs) Handles pb1.Click

    End Sub

    Private Sub Button2_Click(sender As Object, e As EventArgs)

    End Sub

    Private Sub Button1_Click_1(sender As Object, e As EventArgs) Handles Button1.Click
        cabeça()
        Timer1.Start()
        create_mouse()
    End Sub

    Private Sub Label2_Click(sender As Object, e As EventArgs) Handles Label2.Click
        Label2.Text = 0
    End Sub
End Class

解决方案

请参阅我对该问题的评论。你需要使用一些设施。 1)在演员的行为中表达并行性,例如用户/玩家和像蛇这样的人物,2)计算表达游戏场景的状态的变化,3)计算物理,例如碰撞,4)计算图形场景, 5)渲染它。



在大多数或所有方面,你选择了错误或不恰当的设施,或者错过了一些。下面,我将尝试覆盖一些。



使用 PictureBox 不会给你任何帮助,只是添加问题,使用一些您不需要使用的资源并浪费您的开发时间。每次尝试将此纯冗余控件用于除渲染静态图像之外的任何操作时,都会发生这种情况。通过从头开始渲染图形可以轻松解决问题。我在过去的答案中解释了这一切:

附加图片框内的图片 [ ^ ],

如何从旧图纸中清除面板 [ ^ ],

在C#中绘制一个矩形 [ ^ ],

渲染:

什么样的俏皮方法是Paint? (DataGridViewImageCell.Paint(...)) [ ^ ],

在面板上捕获绘图 [ ^ ],

mdi子表单之间的绘制线 [ ^ ],
带有线程的
如何加快我的vb.net应用程序? [ ^ ]。



参见:

如何避免DatagridView C#中的红十字会 [ ^ ],

在运行时更改图片的任何方法动画 [ ^ ],

如何根据e.graphics的内容制作文件 [ ^ ]。



上面的一些链接已经解释了如何使用线程,但在这里你需要后退一步并使用它们。首先,避免计时器。您是否已经面临过上次事件尚未处理时触发计时器事件的情况?有了计时器,迟早,你会。等等......对于线程,没有这样的问题。重要的是你不应该依赖任何固定的时间段。您应该从 System.DateTime.Now 中获取实时值,或者以更准确的方式获取 System.Diagnostics.Stopwatch

https:/ /msdn.microsoft.com/en-us/library/system.datetime%28v=vs.110%29.aspx [ ^ ],

https://msdn.microsoft.com/en-us/library/system.diagnostics .stopwatch%28v = vs.110%29.aspx [ ^ ]。



您无法从非UI调用与UI相关的任何内容线。相反,您需要使用 Invoke System.Windows.Threading的方法。 Dispatcher (对于Forms或WPF)或 System.Windows.Forms.Control (仅限表单)。



您将在我过去的答案中找到有关其工作原理和代码示例的详细说明:

Control.Invoke()与Control.BeginInvoke()

使用Treeview扫描仪和MD5的问题



另请参阅有关线程的更多参考资料:

主要的.NET事件线程

如何让keydown事件在不同的线程上运行i n vb.net

在启用禁用+多线程后控制事件没有触发



另外,请看这个答案我在哪里解释你如何顺利交换数据线程之间以线程安全的方式封装它:

如何将ref参数传递给线程 [ ^ ],

更改线程(生产者)启动后的参数 [ ^ ],

C#中的MultiThreading [ ^ ],

将参数传递给线程化LongRunningProcess [ ^ ],

< a href =http://www.codeproject.com/Answers/182898/Running-exactly-one-job-thread-process-in-webservi#answer1>在webservice中运行一个永远不会的作业/线程/进程终止(asp.net) [ ^ ],

使代码线程安全 [ ^ ]。



万岁蛇!



-SA
Please see my comment to the question. You need to use some set of facilities. 1) to express parallelism in behavior of actors, such as the user/player and characters like snakes, 2) calculate change in states expressing the scenario of game, 3) calculate "physics", such as collisions, 4) calculate graphical scene, 5) render it.

In most or all of the aspects, you are choosing wrong or inappropriate facility, or miss some. Below, I'll try to cover just some.

Using PictureBox does not give you any help, only adds problems, uses some resources you don't need to use and wastes your development time. It happens each time you try to use this purely redundant control to anything except rendering static images. The problem is easily solved by rendering graphics from scratch. I explained it all in my past answers:
Append a picture within picturebox[^],
How do I clear a panel from old drawing[^],
draw a rectangle in C#[^],
rendering:
What kind of playful method is Paint? (DataGridViewImageCell.Paint(...))[^],
capture the drawing on a panel[^],
Drawing Lines between mdi child forms[^],
with threads: How to speed up my vb.net application?[^].

See also:
How to avoid Red Cross in DatagridView C#[^],
any way to change a picture at run time with animation[^],
how to make a file from the content of e.graphics[^].

Some of the links above already explain how to work with threads, but here you need to take a step back and get to using them in general. First of all, avoid timers. Haven't you already face such situation where you have a timer event triggered when the previous event is not yet handled? With timers, sooner or later, you will. And so on… With threads, there are no such problems. It's important that you should not rely on any fixed period of time. You should take real time value from System.DateTime.Now or, with better accuracy, relative timing with System.Diagnostics.Stopwatch:
https://msdn.microsoft.com/en-us/library/system.datetime%28v=vs.110%29.aspx[^],
https://msdn.microsoft.com/en-us/library/system.diagnostics.stopwatch%28v=vs.110%29.aspx[^].

You cannot call anything related to UI from non-UI thread. Instead, you need to use the method Invoke or BeginInvoke of System.Windows.Threading.Dispatcher (for both Forms or WPF) or System.Windows.Forms.Control (Forms only).

You will find detailed explanation of how it works and code samples in my past answers:
Control.Invoke() vs. Control.BeginInvoke(),
Problem with Treeview Scanner And MD5.

See also more references on threading:
.NET event on main thread,
How to get a keydown event to operate on a different thread in vb.net,
Control events not firing after enable disable + multithreading.

Also, please see this answer where I explain how can you smoothly exchange data between threads and encapsulate it in a thread-safe way:
How to pass ref parameter to the thread[^],
Change parameters of thread (producer) after it is started[^],
MultiThreading in C#[^],
Passing arguments to a threaded LongRunningProcess[^],
Running exactly one job/thread/process in webservice that will never get terminated (asp.net)[^],
Making Code Thread Safe[^].

Long live snakes!

—SA


这篇关于蛇永远死了的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆