我正在尝试让gluUnProject
在pyglet中工作,以获取鼠标相对于背景的位置(通过glTranslatef
和glScalef
移动鼠标)。这是我所拥有的,虽然它给了我一个位置,但它不是正确的位置:
def mouse_unproject(x,y):
pmat = (pyglet.gl.GLdouble * 16)()
mvmat = (pyglet.gl.GLdouble * 16)()
view = (pyglet.gl.GLint * 4)()
px = (pyglet.gl.GLdouble)()
py = (pyglet.gl.GLdouble)()
pz = (pyglet.gl.GLdouble)()
pyglet.gl.glGetDoublev(pyglet.gl.GL_MODELVIEW_MATRIX, mvmat)
pyglet.gl.glGetDoublev(pyglet.gl.GL_PROJECTION_MATRIX, pmat)
pyglet.gl.glGetIntegerv(pyglet.gl.GL_VIEWPORT, view)
pyglet.gl.gluUnProject(x, y, 0, mvmat, pmat, view, px, py, pz)
return (px.value,py.value)
整个源代码:
from pyglet.image.codecs.png import PNGImageDecoder
from pyglet.window import key, mouse
from ship import Ships
import pyglet
import numpy as np
import csv
def mouse_unproject(x,y):
pmat = (pyglet.gl.GLdouble * 16)()
mvmat = (pyglet.gl.GLdouble * 16)()
view = (pyglet.gl.GLint * 4)()
px = (pyglet.gl.GLdouble)()
py = (pyglet.gl.GLdouble)()
pz = (pyglet.gl.GLdouble)()
pyglet.gl.glGetDoublev(pyglet.gl.GL_MODELVIEW_MATRIX, mvmat)
pyglet.gl.glGetDoublev(pyglet.gl.GL_PROJECTION_MATRIX, pmat)
pyglet.gl.glGetIntegerv(pyglet.gl.GL_VIEWPORT, view)
pyglet.gl.gluUnProject(x, y, 0, mvmat, pmat, view, px, py, pz)
return (px.value,py.value)
class Game:
def __init__(self):
self.pause = False
self.ships = []
class Overlay:
def __init__(self):
self.radar = pyglet.sprite.Sprite(img=pyglet.image.load('pictures/radar.png',decoder=PNGImageDecoder()))
self.radar_indicator = pyglet.sprite.Sprite(img=pyglet.image.load('pictures/radar_indicator.png',decoder=PNGImageDecoder()))
self.radar.update(x=1014,y=630)
self.radar.opacity = 200
self.indicator_scale = 1
def draw(self,ships,scale):
d = 25 * scale
self.radar.draw()
for s in ships:
x = (((s.icon.x)//d)+1019)
y = (((s.icon.y)//d)+635)
pyglet.graphics.draw(4,pyglet.gl.GL_QUADS,('v2f',(x-1,y-1,x+2,y-1,x+2,y+2,x-1,y+2)),('c3B',(0,255,0,0,255,0,0,255,0,0,255,0)))
class Background:
def __init__(self):
self.image = pyglet.image.load('pictures/star_background.png',decoder=PNGImageDecoder())
self.scale = 1
self.up = False
self.down = False
self.right = False
self.left = False
self.speed = 15
self.translation= [0,0]
self.total_scale = 1
window = pyglet.window.Window(1280,800)
ship_classes = {}
with open('shipclasses.csv',mode='r') as csv_file:
line_counter = 0
csv_reader = csv.reader(csv_file)
for row in csv_reader:
if not line_counter == 0:
index = 0
class_dic = {}
for atr in row:
class_dic[headers[index]] = atr
index += 1
ship_classes[row[0]] = class_dic
else:
headers = row
line_counter += 1
print(ship_classes)
stars = Background()
player = Ships(True,(640,400),False,ship_classes['Valkyrie'])
keys = key.KeyStateHandler()
window.push_handlers(keys)
game = Game()
game.ships.append(player)
overlay = Overlay()
pause_text = pyglet.text.Label('PAUSE',font_name='Times New Roman',font_size=30,x=window.width//2, y=(window.height * 2)//3,anchor_x='center', anchor_y='center')
@window.event
def update(dt):
for s in game.ships:
s.update(dt)
pyglet.clock.schedule_interval(update, 0.02)
@window.event
def background_motion(dt):
if stars.left:
pyglet.gl.glTranslatef(stars.speed, 0, 0)
stars.translation[0] += stars.speed
if stars.right:
pyglet.gl.glTranslatef(-stars.speed, 0, 0)
stars.translation[0] -= stars.speed
if stars.up:
pyglet.gl.glTranslatef(0, -stars.speed, 0)
stars.translation[1] -= stars.speed
if stars.down:
pyglet.gl.glTranslatef(0, stars.speed, 0)
stars.translation[1] += stars.speed
pyglet.clock.schedule_interval(background_motion, 0.05)
@window.event
def on_mouse_scroll(x, y, scroll_x, scroll_y):
if scroll_y > 0:
stars.scale += 0.01
stars.total_scale += 0.01
elif scroll_y < 0:
stars.scale -= 0.01
stars.total_scale -= 0.01
@window.event
def on_mouse_press(x, y, button, modifiers):
if button == mouse.RIGHT and player.course_setting:
player.heading = (x,y)
player.course_setting = False
player.course = True
player.update(0)
@window.event
def on_mouse_motion(x, y, dx, dy):
if player.course_setting:
player.projected_heading = mouse_unproject(x,y)
@window.event
def on_key_press(symbol, modifiers):
if symbol == key.SPACE:
if game.pause:
game.pause = False
else:
game.pause = True
elif symbol == key.W:
stars.up = True
elif symbol == key.S:
stars.down = True
elif symbol == key.D:
stars.right = True
elif symbol == key.A:
stars.left = True
elif symbol == key.C:
if player.course_setting:
player.course_setting = False
else:
player.course_setting = True
player.update_projected()
elif symbol == key.V:
if player.course_setting:
if player.max_v:
player.max_v = False
else:
player.max_v = True
elif player.course:
if player.course_max_v:
player.course_max_v = False
else:
player.course_max_v = True
@window.event
def on_key_release(symbol, modifiers):
if symbol == key.W:
stars.up = False
elif symbol == key.S:
stars.down = False
elif symbol == key.D:
stars.right = False
elif symbol == key.A:
stars.left = False
@window.event
def on_draw():
window.clear()
pyglet.gl.glScalef(stars.scale,stars.scale, 1, 1)
stars.image.blit(0,0)
for s in game.ships:
s.draw()
pyglet.gl.glPushMatrix()
pyglet.gl.glLoadIdentity()
#HUD Start
overlay.draw(game.ships,stars.scale)
if game.pause:
pause_text.draw()
#HUD End
pyglet.gl.glPopMatrix()
stars.scale = 1
if __name__ == '__main__':
pyglet.app.run()
运送文件:
from pyglet.image.codecs.png import PNGImageDecoder
import pyglet
import numpy as np
class Ships:
def __init__(self,player_ship,position,hostile,Class):
self.velocity_vector = [0,0]
self.Class = Class['Class Name']
self.type = Class['Type']
self.health = int(Class['Health'])
self.shield = int(Class['Shield'])
self.acelleration_magnitude = (float(Class['Acceleration(g)']) * 9.8) / 20000
self.acelleration_angle = 0
self.acelleration_vector = [0,0]
self.alive = True
self.player_ship = player_ship
self.hostile = hostile
self.velocity_magnitude = 0
self.course = False
self.heading = position
self.course_setting = False
self.target_velocity = 25
self.velocity_angle = 0
self.projected_heading = position
self.displacement_vector = list(position)
self.max_v = False
self.course_max_v = False
self.scale_factor = 1
if not self.hostile:
course_icon = pyglet.image.load('pictures/friendly_course_icon.png',decoder=PNGImageDecoder())
course_icon.anchor_x = course_icon.width // 2
course_icon.anchor_y = course_icon.height // 2
ship_icon = pyglet.image.load('pictures/friendly_ship.png', decoder=PNGImageDecoder())
ship_icon.anchor_x = ship_icon.width // 2
ship_icon.anchor_y = ship_icon.height // 2
self.icon = pyglet.sprite.Sprite(img=ship_icon)
self.projected_acelleration_icon = pyglet.sprite.Sprite(img=course_icon )
self.projected_deceleration_icon = pyglet.sprite.Sprite(img=course_icon)
self.projected_heading_icon = pyglet.sprite.Sprite(img=course_icon)
self.course_acelleration_icon = pyglet.sprite.Sprite(img=course_icon)
self.course_deceleration_icon = pyglet.sprite.Sprite(img=course_icon)
self.heading_icon = pyglet.sprite.Sprite(img=course_icon)
else:
self.color = (255, 100, 0)
self.icon.x = position[0]
self.icon.y = position[1]
def update_projected(self):
if self.course_setting and self.player_ship:
self.projected_course_x = self.projected_heading[0] - self.icon.x
self.projected_course_y = self.projected_heading[1] - self.icon.x
if self.max_v:
self.projected_deceleration = (np.sqrt(((self.projected_course_x ** 2) + (self.projected_course_y ** 2))) / 2)
else:
self.projected_deceleration =np.sqrt(((self.projected_course_x ** 2) + (self.projected_course_y ** 2))) - ((self.target_velocity ** 2) / (2 * self.acelleration_magnitude))
self.projected_acelleration = (((self.target_velocity ** 2) - (self.velocity_magnitude ** 2)) / (2 * self.acelleration_magnitude)) / 1000
def update(self,update_time):
if self.health <= 0:
self.alive = False
if not self.alive:
return
self.update_projected()
if self.velocity_vector[1] != 0:
self.velocity_angle = np.arctan2(self.velocity_vector[0],self.velocity_vector[1])
self.velocity_magnitude = np.sqrt((self.velocity_vector[0] ** 2) + (self.velocity_vector[1] ** 2))
if self.course:
if (self.icon.y - self.heading[1]) != 0:
self.acelleration_angle = np.arctan2((self.heading[0] - self.icon.x), (self.heading[1] - self.icon.y))
self.sina = np.sin(self.acelleration_angle)
self.cosa = np.cos(self.acelleration_angle)
self.course_x = self.heading[0] - self.icon.x
self.course_y = self.icon.y - self.heading[1]
self.course_displacement = np.sqrt(((self.course_x ** 2) + (self.course_y ** 2)))
self.acelleration_vector[0] = (self.acelleration_magnitude * self.sina)
self.acelleration_vector[1] = (self.acelleration_magnitude * self.cosa)
if self.course_displacement <= ((self.velocity_magnitude ** 2) / (2 * self.acelleration_magnitude)) or (not self.course_max_v and self.velocity_magnitude > self.target_velocity):
self.velocity_vector[0] -= self.acelleration_vector[0] * update_time
self.velocity_vector[1] -= self.acelleration_vector[1] * update_time
elif self.course_max_v or self.velocity_magnitude < self.target_velocity:
self.velocity_vector[0] += self.acelleration_vector[0] * update_time
self.velocity_vector[1] += self.acelleration_vector[1] * update_time
if self.course_max_v:
self.course_deceleration = (np.sqrt(((self.projected_course_x ** 2) + (self.projected_course_y ** 2))) / 2)
else:
self.course_deceleration = self.course_displacement - ((self.target_velocity ** 2) / (2 * self.acelleration_magnitude))
self.course_acelleration = ((self.target_velocity ** 2) - (self.velocity_magnitude ** 2)) / (2 * self.acelleration_magnitude)
if -1 <= self.course_displacement <= 1:
self.course = False
self.displacement_vector[0] += (self.velocity_vector[0] * update_time)
self.displacement_vector[1] += (self.velocity_vector[1] * update_time)
def draw(self):
self.icon.update(x=int(round(self.displacement_vector[0])) ,y=int(round(self.displacement_vector[1])))
if self.course_setting and self.player_ship:
self.projected_angle = np.arctan2(((self.projected_heading[0]) - (self.icon.x)), ((self.projected_heading[1]) - (self.icon.y)))
self.projected_heading_icon.update(x=self.projected_heading[0],y=self.projected_heading[1])
self.projected_heading_icon.draw()
pyglet.graphics.draw(2,pyglet.gl.GL_LINES,('v2f',(self.icon.x,self.icon.y,self.projected_heading_icon.x,self.projected_heading_icon.y)),('c3B',(0, 70, 0,0, 70, 0)))
self.projected_deceleration_icon.x = int(round((self.projected_deceleration * np.sin(self.projected_angle)))) + self.icon.x
self.projected_deceleration_icon.y = int(round((self.projected_deceleration * np.cos(self.projected_angle)))) + self.icon.y
self.projected_deceleration_icon.draw()
if not self.max_v:
self.projected_acelleration_icon.x = int(round(((self.projected_acelleration * np.sin(self.projected_angle))))) + self.icon.x
self.projected_acelleration_icon.y = int(round(((self.projected_acelleration * np.cos(self.projected_angle))))) + self.icon.y
self.projected_acelleration_icon.draw()
if self.course:
self.heading_icon.update(x=int(round(self.heading[0])) ,y=int(round(self.heading[1])))
self.heading_icon.draw()
pyglet.graphics.draw(2, pyglet.gl.GL_LINES, ('v2f', (self.icon.x, self.icon.y, self.heading_icon.x, self.heading_icon.y)), ('c3B', (0, 70, 0, 0, 70, 0)))
self.course_deceleration_icon.x = int(round(self.course_deceleration * np.sin(self.acelleration_angle))) + self.icon.x
self.course_deceleration_icon.y = int(round(self.course_deceleration * np.cos(self.acelleration_angle))) + self.icon.y
self.course_deceleration_icon.draw()
if not self.course_max_v:
self.course_acelleration_icon.x = int(round(self.course_acelleration * np.sin(self.acelleration_angle)))
self.course_acelleration_icon.y = int(round(self.course_acelleration * np.cos(self.acelleration_angle)))
self.course_acelleration_icon.draw()
self.icon.draw()
if False:
pygame.draw.line(surface, self.color, tuple(self.position), tuple((self.position[0] + int(15 * np.sin(self.velocity_angle)), self.position[1] + int(15 * np.cos(self.velocity_angle)))), 2)
答案 0 :(得分:2)
就像我推测您正在遇到OpenGL矩阵堆栈的状态性问题一样,并且您正在查询的不是用于绘图的矩阵。在您的绘图功能中
@window.event
def on_draw():
window.clear()
pyglet.gl.glScalef(stars.scale,stars.scale, 1, 1)
…
您正在进行“无目标”矩阵操作调用。毫无疑问,除非您非常小心地在调用on_draw
事件处理程序之间使矩阵处于众所周知的状态,否则您将不知道会发生什么。
就您的程序而言,就我所知,您从未接触过投影矩阵,因此投影矩阵处于身份状态。并且在每次on_draw
调用之后,您进一步缩放了模型视图矩阵。
然后您要进行glPushMatrix
设置身份并绘制船只,这会为您提供已知状态。
我建议您直接在绘图函数内部查询矩阵,而不要查询mouse_unproject
,因为这是矩阵处于已知状态的唯一位置。