#pygame #game-engine #game-physics
#pygame #игровой движок #игра-физика
Вопрос:
Я пытаюсь написать этот учебник на Pygame (Python) и у меня возникают проблемы с удержанием точек между плоскостями.
Мой код:fiz2.py
Векторный класс: vector.py
Если вы наведете курсор мыши на экран Pygame, плоскости будут вращаться. И когда плоскости вращаются, точки проходят через плоскости и выходят наружу.
Я пытался исправить положение точек на каждой итерации, но они все равно проходили мимо плоскостей. Я понятия не имею, где мне следует зафиксировать их положения.
ПРИМЕЧАНИЕ: Я знаю, что мой код немного запутан, это моя первая 2d-программа, и мне было действительно трудно привыкнуть к координатной плоскости и векторам Pygame. Я перепишу, когда решу это.
ПРИМЕЧАНИЕ 2: Да, я написал комментарий о том, как удерживать точки между плоскостями в руководстве, я понимаю, как он фиксирует позиции, но понятия не имею о том, как (и где, в коде) это реализовать.
Спасибо.
Ответ №1:
Я не могу сказать, глядя на код. Я предполагаю, что это переменный временной шаг, вызывающий нестабильность. Но я не могу проверить, верна ли математика. Хотя, у меня есть полезная информация :
Векторы
Вы можете упростить код, используя векторы в качестве класса вместо списка / кортежа. (скорость, ускорение, местоположение) рассматриваются как один объект, стихи разделяют значения .x и .y.
# example:
pos[0] = vel[0]
pos[1] = vel[1]
# vs
pos = vel
Существует реализация только на python: euclid.py Вы можете использовать для сравнения с вашим vector.py.
Или используйте NumPy [используется для 3D-графики в OpenGL. ] Является популярной, зрелой библиотекой.
физика
(Похоже, вы хотите научиться, написав свою собственную физику), но посмотрите на PyMunk
Цвет
Вы можете использовать: pygame.Цвет
import pygame
from pygame import Color
color = Color('white')
color2 = Color('lightgray')
color3 = Color(0,128,128)
столкновения
Посмотрите на pygame.sprite.*collide и pygame.Rect.*collide
цикл игры pygame с использованием numpy-вектора
Шаблон, который я написал
""" Pygame boilerplate. <ninmonkey>2011/04
pygame main Game() loop, and numpy for vector math.
note:
this might not be the most effecient way to use numpy as vectors, but it's an intro.
And this does not force fixed-timesteps. If you want a stable simulation, you need to use a fixed timestep.
see: http://gafferongames.com/game-physics/fix-your-timestep/
Keys:
ESC : exit
Space : game_init()
"""
import pygame
from pygame.locals import *
from pygame import Color, Rect
import numpy as np
def get_screen_size():
"""return screen (width, height) tuple"""
screen = pygame.display.get_surface()
return screen.get_size()
class Actor():
"""basic actor, moves randomly.
members:
loc = position vector
velocity = velocity vector
width, height
"""
def __init__(self, loc=None, velocity=None):
"""optional initial loc and velocity vectors"""
self.width = 50
self.height = 50
# if loc or velocity are not set: use random
if loc is None: self.rand_loc()
else: self.loc = loc
if velocity is None: self.rand_velocity()
else: self.velocity = velocity
def update(self):
"""update movement"""
self.loc = self.velocity
def rand_velocity(self):
"""set a random vector , based on random direction. Using unit circle:
x = cos(deg) * speed
"""
rad = np.radians( np.random.randint(0,360) )
speed = np.random.randint(1,15)
x = np.cos(rad)
y = np.sin(rad)
velocity = np.array( [x,y])
velocity *= speed
self.velocity = velocity
def rand_loc(self):
"""random location onscreen"""
width,height = get_screen_size()
x = np.random.randint(0,width)
y = np.random.randint(0,height)
self.loc = np.array([x,y])
def is_onscreen(self):
"""test is screen.colliderect(actor) true?"""
x,y = self.loc
w,h = get_screen_size()
screen = Rect(0, 0, w, h)
actor = Rect(x, y, self.width, self.height)
if screen.colliderect(actor): return True
else: return False
class GameMain():
"""game Main entry point. handles intialization of game and graphics."""
done = False
debug = False
color_gray = Color('lightgray')
def __init__(self, width=800, height=600, color_bg=None):
"""Initialize PyGame"""
pygame.init()
self.width, self.height = width, height
self.screen = pygame.display.set_mode(( self.width, self.height ))
pygame.display.set_caption( "boilerplate : pygame" )
self.clock = pygame.time.Clock()
self.limit_fps = True
self.limit_fps_max = 60
if color_bg is None: color_bg = Color(50,50,50)
self.color_bg = color_bg
self.game_init()
def game_init(self):
"""new game/round"""
self.actors = [Actor() for x in range(10)]
def loop(self):
"""Game() main loop"""
while not self.done:
self.handle_events()
self.update()
self.draw()
if self.limit_fps: self.clock.tick( self.limit_fps_max )
else: self.clock.tick()
def update(self):
"""update actors, handle physics"""
for a in self.actors:
a.update()
if not a.is_onscreen():
a.rand_loc()
def handle_events(self):
"""handle regular events. """
events = pygame.event.get()
# kmods = pygame.key.get_mods() # key modifiers
for event in events:
if event.type == pygame.QUIT: sys.exit()
elif event.type == KEYDOWN:
if (event.key == K_ESCAPE): self.done = True
elif (event.key == K_SPACE): self.game_init()
def draw(self):
"""render screen"""
# clear screen
self.screen.fill( self.color_bg )
# Actor: draw
for a in self.actors:
x,y = a.loc
w,h = a.width, a.height
r = Rect(x, y, w, h)
self.screen.fill(self.color_gray, r)
# will call update on whole screen Or flip buffer.
pygame.display.flip()
if __name__ == '__main__':
g = GameMain()
g.loop()
Комментарии:
1. спасибо за код, на самом деле проблема не в обнаружении столкновений, проблема в том, что когда вы перемещаете плоскости, когда шары вот-вот врежутся в плоскость, они вылетают за пределы плоскости.. Я понятия не имею, как я могу исправить их положения, когда плоскости движутся..