2010-08-04 6 views
7

나는 파이썬과 Tkinter를 사용하여 소행성의 버전을 만들려고 노력 중이다. 왼쪽 또는 오른쪽 화살표 키를 누르면 우주선이 회전해야합니다. 배는 Tkinter 캔버스에있는 삼각형입니다. 삼각형의 좌표를 조정하는 수식 문제가 있습니다. 나는 그것이 확실하지 않지만 죄와 사면과 관련이 있다고 믿습니다. 지금까지 나는 배를위한 것과 배틀을위한 두 개의 클래스를 가지고 있습니다. ship 클래스에는 키 누르기를위한 콜백 메소드가 있습니다. 어떤 도움이라도 대단히 감사하겠습니다. 감사.Tkinter Canvas에서 파이썬으로 폴리곤을 회전하는 방법은 무엇입니까?

선박 클래스

import math 
class Ship: 
    def __init__(self,canvas,x,y,width,height): 
     self.canvas = canvas 
     self.x = x - width/2 
     self.y = y + height/2 
     self.width = width 
     self.height = height 

     self.x0 = self.x 
     self.y0 = self.y 

     self.x1 = self.x0 + self.width/2 
     self.y1 = self.y0-self.height 

     self.x2 = self.x0 + self.width 
     self.y2 = self.y0 

     self.ship = self.canvas.create_polygon((self.x0, self.y0, self.x1, self.y1, self.x2, self.y2), outline="white", width=3) 
    def changeCoords(self): 
     self.canvas.coords(self.ship,self.x0, self.y0, self.x1, self.y1, self.x2, self.y2) 
    def rotateLeft(self, event=None): 
     # Should rotate one degree left. 
     pass 
    def rotateRight(self, event=None): 
     # Should rotate one degree right. 
     self.x0 = self.x0 -1 
     self.y0 = self.y0 - 1 

     self.x1 = self.x1 + 1 
     self.y1 = self.y1 + 1 

     self.x2 = self.x2 - 1 
     self.y2 = self.y2 + 1 
     self.changeCoords() 

게임 클래스 모두의

from Tkinter import * 
from ship import * 


class Game: 
    def __init__(self, gameWidth, gameHeight): 
     self.root = Tk() 
     self.gameWidth = gameWidth 
     self.gameHeight = gameHeight 
     self.gameWindow() 

     self.ship = Ship(self.canvas, x=self.gameWidth/2,y=self.gameHeight/2, width=50, height=50) 
     self.root.bind('<Left>', self.ship.rotateLeft) 
     self.root.bind('<Right>', self.ship.rotateRight) 

     self.root.mainloop() 

    def gameWindow(self): 
     self.frame = Frame(self.root) 
     self.frame.pack(fill=BOTH, expand=YES) 

     self.canvas = Canvas(self.frame,width=self.gameWidth, height=self.gameHeight, bg="black", takefocus=1) 
     self.canvas.pack(fill=BOTH, expand=YES)  

asteroids = Game(600,600) 

답변

9

첫째, 당신은 삼각형의 중심 주위를 회전해야합니다. centroid가 아마도 가장 잘 작동 할 것입니다. 그것을 찾으려면 수식 C = (1/3*(x0 + x1 + x2), 1/3*(y0 + y1 + y2))을 삼각형의 모든 점의 평균으로 사용할 수 있습니다. 그런 다음 그 점을 중심으로 회전을 적용해야합니다. 그래서

import math 

class Ship: 
    def centroid(self): 
     return 1/3 * (self.x0 + self.x1 + self.x2), 1/3 * (self.y0 + self.y1 + self.y2) 

    def __init__(self, canvas, x, y, width, height, turnspeed, acceleration=1): 
     self._d = {'Up':1, 'Down':-1, 'Left':1, 'Right':-1} 

     self.canvas = canvas 
     self.width = width 
     self.height = height 
     self.speed = 0 
     self.turnspeed = turnspeed 
     self.acceleration = acceleration 

     self.x0, self.y0 = x, y 

     self.bearing = -math.pi/2 

     self.x1 = self.x0 + self.width/2 
     self.y1 = self.y0 - self.height 

     self.x2 = self.x0 + self.width 
     self.y2 = self.y0 

     self.x, self.y = self.centroid() 

     self.ship = self.canvas.create_polygon((self.x0, self.y0, self.x1, self.y1, self.x2, self.y2), outline="white", width=3) 

    def changeCoords(self): 
     self.canvas.coords(self.ship,self.x0, self.y0, self.x1, self.y1, self.x2, self.y2) 

    def rotate(self, event=None): 
     t = self._d[event.keysym] * self.turnspeed * math.pi/180 # the trig functions generally take radians as their arguments rather than degrees; pi/180 radians is equal to 1 degree 

     self.bearing -= t 

     def _rot(x, y): 
      #note: the rotation is done in the opposite fashion from for a right-handed coordinate system due to the left-handedness of computer coordinates 
      x -= self.x 
      y -= self.y 
      _x = x * math.cos(t) + y * math.sin(t) 
      _y = -x * math.sin(t) + y * math.cos(t) 
      return _x + self.x, _y + self.y 

     self.x0, self.y0 = _rot(self.x0, self.y0) 
     self.x1, self.y1 = _rot(self.x1, self.y1) 
     self.x2, self.y2 = _rot(self.x2, self.y2) 
     self.x, self.y = self.centroid() 

     self.changeCoords() 

    def accel(self, event=None): 
     mh = int(self.canvas['height']) 
     mw = int(self.canvas['width']) 
     self.speed += self.acceleration * self._d[event.keysym] 

     self.x0 += self.speed * math.cos(self.bearing) 
     self.x1 += self.speed * math.cos(self.bearing) 
     self.x2 += self.speed * math.cos(self.bearing) 

     self.y0 += self.speed * math.sin(self.bearing) 
     self.y1 += self.speed * math.sin(self.bearing) 
     self.y2 += self.speed * math.sin(self.bearing) 

     self.x, self.y = self.centroid() 

     if self.y < - self.height/2: 
      self.y0 += mh 
      self.y1 += mh 
      self.y2 += mh 
     elif self.y > mh + self.height/2: 
      self.y0 += mh 
      self.y1 += mh 
      self.y2 += mh 

     if self.x < -self.width/2: 
      self.x0 += mw 
      self.x1 += mw 
      self.x2 += mw 
     elif self.x > mw + self.width/2: 
      self.x0 -= mw 
      self.x1 -= mw 
      self.x2 -= mw 

     self.x, self.y = self.centroid() 

     self.changeCoords() 

나는 그런데, 소행성처럼 좀 더 게임을 컨트롤을 일부 변경했다 ... 이런 일이 될 것입니다. (그러나 발사를 구현하지 않았다. 내가 예상했던 것보다 더 많은 것을 얻었지만 모든 것을하지는 않을 것이다. 또한 한 번에 여러 개의 이동 키를 사용할 때 약간의 문제가있다. 당신은 TK에/Tkinter를 제대로 작동 것을 얻기 위해 공정한 조금 주위에 바이올린해야 할 것 그래서, TK에 이벤트가. 그것은 게임을 위해 설계되지 않은 핸들링 않는 방식 때문입니다.) 여담으로

from tkinter import * 
from ship import * 

class Game: 
    def __init__(self, gameWidth, gameHeight): 
     self.root = Tk() 
     self.gameWidth = gameWidth 
     self.gameHeight = gameHeight 
     self.gameWindow() 

     self.ship = Ship(self.canvas, x=self.gameWidth/2,y=self.gameHeight/2, width=50, height=50, turnspeed=10, acceleration=5) 
     self.root.bind('<Left>', self.ship.rotate) 
     self.root.bind('<Right>', self.ship.rotate) 
     self.root.bind('<Up>', self.ship.accel) 
     self.root.bind('<Down>', self.ship.accel) 

     self.root.mainloop() 

    def gameWindow(self): 
     self.frame = Frame(self.root) 
     self.frame.pack(fill=BOTH, expand=YES) 

     self.canvas = Canvas(self.frame,width=self.gameWidth, height=self.gameHeight, bg="black", takefocus=1) 
     self.canvas.pack(fill=BOTH, expand=YES)  

asteroids = Game(600,600) 

, 속성을 사용하여 포인트 등을보다 쉽게 ​​처리 할 수 ​​있습니다.

+2

도움을 주셔서 대단히 감사합니다. 당신은 학자이고 신사입니다. 이것은 내가 찾고 있었던 바로 그 것이다. – Sam

+1

대단히 반갑습니다. – JAB

관련 문제