Tkinter帆布游戏需要轻微的返工

时间:2017-08-19 01:52:05

标签: python python-3.x tkinter

首先是代码 - 我会在以后遇到问题。虽然我确信你可以发现很多,而不需要向远处滚动。

from tkinter import *
import random
import math
import time

test = random.randint(10,40)
print(test)

class Game():
    global x0,y0,x1,y1,Game,debug, Player, mousex0, mousey0, mousex1,
           mousey1, moveTowardMouse, rayCast, speed, frayCast, fx0, fy0,
           fx1, fy1, Food
    def move(event):
        global x0,y0,x1,y1,mouseX0,mouseY0,mouseX1,mouseY1,fx0, fy0,
              fx1, fy1,Food
        mouseX0 = event.x - 10
        mouseY0 = event.y - 10
        mouseX1 = event.x + 10
        mouseY1 = event.y + 10
        Game.coords(rayCast, x0, y0, mouseX1, mouseY1)
        if x0 != mouseX0 and x0 < mouseX0:
            x0 = x0 + speed
            x1 = x1 + speed
            Game.coords(Player, x0, y0, x1, y1)
        if x0 != mouseX0 and x0 > mouseX0:
            x0 = x0 - speed
            x1 = x1 - speed
            Game.coords(Player, x0, y0, x1, y1)
        if y0 != mouseY0 and y0 < mouseY0:
            y0 = y0 + speed
            y1 = y1 + speed
            Game.coords(Player, x0, y0, x1, y1)
        if y0 != mouseY0 and y0 > mouseY0:
            y0 = y0 - speed
            y1 = y1 - speed
            Game.coords(Player, x0, y0, x1, y1)
        Game.coords(frayCast, x0,y0, fx0,fy0)
        if fx0 > x0 and (fx0 - x0) < 20:
            fx0 = fx0 + 0.5
            fx1 = fx1 + 0.5
            Game.coords(Food, fx0,fy0,fx1,fy1)
        if fx0 < x0 and (fx0 + x0) < 20:
            fx0 = fx0 - 0.5
            fx1 = fx1 - 0.5
            Game.coords(Food, fx0,fy0,fx1,fy1)
        if fy0 > y0 and (fy0 - y0) < 20:
            fy0 = fy0 + 0.5
            fy1 = fy1 + 0.5
            Game.coords(Food, fx0,fy0,fx1,fy1)
        if fy0 < y0 and (fy0 - y0) < 20:
            fy0 = fy0 - 0.5
            fy1 = fy1 - 0.5
            Game.coords(Food, fx0,fy0,fx1,fy1)
        if fx0 > x0 and (fx0 - x0) < 5:
            if fy0 > y0 and (fy0 - y0) <5:
                Game.delete(Food)
                x0 = x0 - fx1
                y0 = y0 - fy1
                Game.coords(Player, x0,y0,x1,y1)

    fx0 = 20
    fy0 = 20
    fx1 = test + 20
    fy1 = test + 20
    x0 = -50
    y0 = -50
    x1 = 50
    y1 = 50
    speed = 1
    mouseX0 = 0
    mouseY0 = 0
    mouseX1 = 0
    mouseY1 = 0
    debug = "DEBUGGED"
    module = Tk()
    Game = Canvas(module, width=1000, height=1000)
    Player = Game.create_oval(x0,y0,x1,y1,fill="blue")
    Food = Game.create_oval(fx0, fy0, fx1, fy1, fill="red")
    rayCast = Game.create_line(x0,y0,mouseX1,mouseY1)
    frayCast = Game.create_line(x0,y0,mouseX1,mouseY1)
    module.bind('<Motion>', move)
    Game.pack()
    module.mainloop()

刚才我意识到我的代码基本上没用了,所以我只是轻微的“哦”。

在我正在创建的游戏中,我希望画布上的Player控制精灵以慢速向鼠标移动。我用Google搜索了如何获取鼠标坐标,它告诉我,我可以使用该事件来获取函数中的坐标。然而,自从获得这些坐标后,我慢慢地将所有主要的精灵运动计算放在同一个函数中,从而产生一个功能性游戏...只有你移动鼠标才能做到这一点。

这个想法是NPC精灵是一个随机大小,并在画布上的随机空间中产生。它以慢速随机方向移动,直到它在玩家控制的精灵的“20”范围内,在这种情况下,它会从玩家控制的精灵中移动(更快)。

除了所有这些只在您移动鼠标时发生(并且我仍然使用光线投射来获取精灵的轨迹),还有一些我需要帮助的问题。

首先,NPC精灵的随机大小效果很好。但它每次都会产生完全相同的地方。

其次,NPC的“避免播放器”代码似乎......不是功能性的。基本上它工作正常,但即使在玩家从精灵移动“20”后它仍然继续工作。

最后,我对精灵本身的坐标有疑问。您会看到光线投射显示精灵的真正坐标不在其圆形画布表示的中心,而是位于围绕所述圆圈的无形正方形的左上角。我需要将它放在精灵的中心而不是其他方面,否则游戏机制会变得有点儿麻烦。

回到最大的问题(使用sprite coords的更新方式)我可以在游戏中设置类似每个Tick的更新并在每个tick中运行我的所有计算,但后来我不知道如何获得使用该事件之外的鼠标坐标。

长话短说一些帮助将不胜感激。

1 个答案:

答案 0 :(得分:0)

这是您改进的代码。我在评论中解释了一切。

from tkinter import *
import random
import math
import time

class Game():

    # This __init__ will run first when you run Game()
    # Learn to always set up your programs this way.
    def __init__(self):

        test = random.randint(10,40)
        print(test)

        # Put self. before the name of every variable you might want to use outside this __init__ function.
        # this way you don't need to define them separately in every function

        # You defined these xs and ys by hand so of course it remains in the same position.
        # define them randomly and you'll be fine.
        self.fx0 = 20 
        self.fy0 = 20 
        self.fx1 = test + 20
        self.fy1 = test + 20
        self.x0 = -50
        self.y0 = -50
        self.x1 = 50
        self.y1 = 50
        self.speed = 1
        self.mouseX0 = 0
        self.mouseY0 = 0
        self.mouseX1 = 0
        self.mouseY1 = 0
        self.debug = "DEBUGGED"

        # Added these two variables
        self.tick_intervals = 10
        self.food_exists = True

        self.module = Tk()

        #Game is the name of your class don't use it here: (use game instead)
        self.game = Canvas(self.module, width=1000, height=1000)
        self.Player = self.game.create_oval(self.x0,self.y0,self.x1,self.y1,fill="blue")
        self.Food = self.game.create_oval(self.fx0, self.fy0, self.fx1, self.fy1, fill="red")
        self.rayCast = self.game.create_line(self.x0,self.y0,self.mouseX1,self.mouseY1)
        self.frayCast = self.game.create_line(self.x0,self.y0,self.mouseX1,self.mouseY1)
        self.game.pack()
        self.move()
        self.module.mainloop()


    def move(self):
        # To get mouse position on your whole screen: .winfo_pointerx() and .winfo_pointery()
        # To get position of widget (self.game) on screen .winfo_rootx()
        # x and y below are the same as mouse event.x and event.y without the need to bind anything to self.module
        x = self.game.winfo_pointerx()-self.game.winfo_rootx()
        y = self.game.winfo_pointery()-self.game.winfo_rooty()

        # If you have a value you use more than 1 time,
        # it's best to define it first then put that here
        # instead of writing it out every time.
        # this way you can change it very easily
        # better define these in __init__ function with self.something = ...
        self.mouseX0 = x - 10 # define var for 10 
        self.mouseY0 = y - 10
        self.mouseX1 = x + 10
        self.mouseY1 = y + 10

        # You should also design a (visible or invisible) wall around the screen
        # so your Player and Food can't run off the screen.
        # Basically it's numbers and some if statements.

        # If you don't put elif here x and y might get resized then resized again.
        # but you only need to resize them once a tick.
        # You don't need != here. < > are enough.
        # Look up += -= *= /= functions.   
        if self.x0 < self.mouseX0:
            self.x0 += self.speed
            self.x1 += self.speed
        elif self.x0 > self.mouseX0:
            self.x0 -= self.speed
            self.x1 -= self.speed
        if self.y0 < self.mouseY0:
            self.y0 += self.speed
            self.y1 += self.speed
        elif self.y0 > self.mouseY0:
            self.y0 -= self.speed
            self.y1 -= self.speed

        # Need to call these once a tick and not every time you change x or y
        self.game.coords(self.rayCast, self.x0, self.y0, self.mouseX1, self.mouseY1)
        self.game.coords(self.Player,self.x0,self.y0,self.x1,self.y1)

        # After you eat food this shouldn't run any more.
        # This is why Player kept getting bigger and bigger
        if self.food_exists:
            if self.fx0 > self.x0 and (self.fx0 - self.x0) < 20: # define var for 20
                self.fx0 += 0.5 # define var for 0.5
                self.fx1 += 0.5
            elif self.fx0 < self.x0 and (self.fx0 + self.x0) < 20:
                self.fx0 -= 0.5
                self.fx1 -= 0.5
            if self.fy0 > self.y0 and (self.fy0 - self.y0) < 20:
                self.fy0 += 0.5
                self.fy1 += 0.5
            elif self.fy0 < self.y0 and (self.fy0 - self.y0) < 20:
                self.fy0 -= 0.5
                self.fy1 -= 0.5
            if self.fx0 > self.x0 and (self.fx0 - self.x0) < 5: # define var for 5
                if self.fy0 > self.y0 and (self.fy0 - self.y0) <5:
                    self.game.delete(self.Food)
                    self.x0 -= self.fx1
                    self.y0 -= self.fy1
                    self.food_exists = False
            self.game.coords(self.Food,self.fx0,self.fy0,self.fx1,self.fy1)
            self.game.coords(self.frayCast, self.x0,self.y0, self.fx0,self.fy0)

        # This automatically runs self.move after (self.tick_intevals) miliseconds
        self.game.after(self.tick_intervals,self.move)

# This IF runs the Game() only if you run the script yourself.
# This way if you imported this script into another program it wouldn't run Game() 
# Learn to always use this if for your programs
if __name__=='__main__':
    Game()