用Python Turtle创建的Pong

时间:2018-08-01 22:39:54

标签: python turtle-graphics pong

我是Python的新手,但是我已经用其他语言编码,主要用于硬件。我用乌龟在Python中制作了Pong,但是有点毛病。我想知道是否有人可以检查一下并提供建议。我也想添加开始屏幕和结束屏幕,但是有点不确定如何。另外,如果您对如何改进碰撞检测有任何建议,请告诉我。

我在下面粘贴代码


private async void StartClient()
    {
        String sName = "<server ip>";
        int port = <server port>;

        WaveOut waveout = new WaveOut(); 

        TcpClient conn = new TcpClient();

        try
        {

            int counter = 0;

            conn.Connect(sName, port);
            stream = conn.GetStream();               

            by = new byte[2560];  // new byte array to store received data

            var bufferedWaveProvider = new BufferedWaveProvider(new WaveFormat(16000, 16, 2));
            bufferedWaveProvider.BufferLength = 2560 * 16;      //16 is pretty good
            bufferedWaveProvider.DiscardOnBufferOverflow = true;

            while (true)
            {
                //wait until buffer has data, then returns buffer length
                int bytesAvailable = await stream.ReadAsync(by, 0, 2560);

                if (counter == 0)
                {
                    msg = Encoding.UTF8.GetString(by, 0, bytesAvailable);
                    devicehash = msg.TrimEnd();
                    DispatchMethod(by[0].ToString());
                    counter++;                        
                }
                else
                {
                    //send to speakers

                    bufferedWaveProvider.AddSamples(by, 0, 2560);

                    if (counter == 1)
                    {
                        waveout.Init(bufferedWaveProvider);
                        waveout.Play();
                        counter++;
                    }                     
                }
            }
        }
        catch (Exception e)
        { 
        }
    }

2 个答案:

答案 0 :(得分:1)

我看到一些问题:

  • 您已经将20 x 20平方拉伸为10 x 80:

    AIplayer.shapesize(0.5,4)

    但是您的碰撞距离中心只有20,所以您的球可以 越过桨叶的底部或顶部而没有实际 碰撞。

  • 您的isCollision()函数对于乌龟自己的函数几乎是多余的 .collision()方法。

  • 在像乌龟这样的事件驱动世界中,您不应该拥有while True: 因为它有可能阻止某些事件的触发。更好地 将其替换为计时器事件。

  • 您的某些碰撞在应该改变x和y增量的同时 只需更改其中之一即可。

  • 您应该避免在主循环中重复查询乌龟,并避免检查其他逻辑子句所否定的条件。即在主循环中尽力而为。

以下是我根据上述内容对您的游戏进行的重做,以及许多其他样式和逻辑更改:

from turtle import Turtle, Screen

FONT = ("Arial", 16, "normal")

def isCollision(t1, t2):
    return t1.distance(t2) < 15

# set up screen
screen = Screen()
screen.bgcolor("darkgreen")
screen.title("Pong")

# set up border
border_pen = Turtle(visible=False)
border_pen.speed('fastest')
border_pen.color('white')
border_pen.pensize(3)

border_pen.penup()
border_pen.setposition(-300, -300)
border_pen.pendown()

for _ in range(4):
    border_pen.forward(600)
    border_pen.left(90)

# set score to 0
score = 0

# set time to zero
seconds = 0

# Draw score
score_pen = Turtle(visible=False)
score_pen.color("white")
score_pen.penup()
score_pen.setposition(-290, 310)

score_pen.write("Score {}".format(score), False, align="left", font=FONT)

# Draw timer
time_pen = Turtle(visible=False)
time_pen.color("white")
time_pen.penup()
time_pen.setposition(260, 310)

time_pen.write("Time {}".format(int(seconds)), False, align="left", font=FONT)

# create the player turtle
player = Turtle("square", visible=False)
player.shapesize(0.5, 3)
player.speed('fastest')
player.setheading(90)
player.color("blue")
player.penup()

player.setposition(-280, -250)  # (x,y)
player.showturtle()

playerspeed = 15

# create the AIplayer turtle
AIplayer = Turtle("square", visible=False)
AIplayer.shapesize(0.5, 3)
AIplayer.speed('fastest')
AIplayer.setheading(90)
AIplayer.color("black")
AIplayer.penup()

AIplayer.setposition(280, 250)  # (x,y)
AIplayer.showturtle()

AIplayerspeed = 15

# create the pong
pong = Turtle("circle", visible=False)
pong.shapesize(0.5, 0.5)
pong.speed('fast')
pong.color("red")
pong.penup()

pong.sety(265)
pong.showturtle()

pongspeed = 15
pong_dx, pong_dy = 5, -5

# Move player up and down
def move_up():
    player.forward(playerspeed)

    y = player.ycor()

    if y > 265:
        y = 260
        player.sety(y)

    screen.update()

def move_down():
    player.backward(playerspeed)

    y = player.ycor()

    if y < -265:
        y = -260
        player.sety(y)

    screen.update()

# keyboard bindings
screen.onkey(move_up, "Up")
screen.onkey(move_down, "Down")

screen.listen()

# main game loop
def move():
    global pong_dx, pong_dy, AIplayerspeed, seconds, score

    # move pong ball
    x, y = pong.position()
    x += pong_dx
    y += pong_dy
    pong.setposition(x, y)

    if isCollision(pong, player): # collision pong and player
        pong_dx *= -1
        # Update the score
        score += 10
        score_pen.undo()
        score_pen.write("Score: {}".format(score), align="left", font=FONT)
    elif isCollision(pong, AIplayer):  # collision pong and AIplayer
        pong_dx *= -1
    elif y < -300 or y > 300:  # check for bounce and redirect it
        pong_dy *= -1
    elif x > 300:
        pong_dx *= -1
    elif x < -300:
        print("Game Over")
        screen.bye()
        return

    # move AI paddle (might speed up pong movement)
    AIplayer.forward(AIplayerspeed)

    y = AIplayer.ycor()

    if y < -250 or y > 250:
        AIplayerspeed *= -1

    # display timer
    seconds += 0.05
    time_pen.undo()
    time_pen.write("Time: {}".format(int(seconds)), False, align="Left", font=FONT)
    screen.ontimer(move, 50)

    screen.update()

screen.tracer(False)
move()
screen.mainloop()

我无法理解您的“提高球速”逻辑,因此我将其遗漏了。我使用了较深的背景颜色,因为难以在屏幕上查看原始图像。

答案 1 :(得分:0)

乒乓球/球速相关的问题可能是由于您的CPU引起的。每次屏幕更新时,球都在(x和y)两个方向上移动5个像素,并且更新速率取决于CPU速度。 CPU执行的进程不是恒定的,因此CPU速度会波动。另外,因为我们将screen.tracer()设置为False,所以它不显示动画。 因此,由于缺乏动画效果和CPU速度不一致,我们看到乒乓/球的速度在增加/减少。

有关screen.tracer()的解释,请参见https://youtu.be/LH8WgrUWG_I?t=123

有关“增加速度”的说明,请参见https://youtu.be/Hw1H3rG3POM?t=40

要获得更一致的行为,可以在循环中添加足够长的暂停时间,以抵消计算时间的可变性并避免绘制无用的帧。您可以使用time

import time

# Initialization
...

while True:
     time.sleep(1 / 60)

    # The rest of your game logic
...