이번에는 오일러 방법으로 지난번에 만든 게임에 이동을 추가함
사실 지난번에 만든 게임에는 우주선 이동을 안넣엇지 운석 이동을 시키면서 이미 오일러 방법을 사용했었다.
변화 거리 = 속도 * 소요시간(밀리세컨드) / 1000
기존 위치 = 이전 위치 + 변화 거리
그래도 게임을 개선한건 맞으니 그냥 쭉 정리하면
오일러 방법으로 무브는 하는데
벽을 넘어가면 반대편에 나오도록 수정
class PolygonModel():
def __init__(self, points):
self.points = points
self.rotation_angle = 0
self.x = 0
self.y = 0
self.vx = 0
self.vy = 0
self.angular_velocity = 0
self.draw_center = True
def transformed(self):
rotated = [vectors.rotate2d(self.rotation_angle, v) for v in self.points]
return [vectors.add((self.x, self.y), v) for v in rotated]
def move(self, milliseconds):
dx, dy = self.vx * milliseconds / 1000.0, self.vy * milliseconds / 1000
self.x, self.y = vectors.add((self.x, self.y), (dx, dy))
if self.x < -10:
self.x += 20
if self.y < -10:
self.y += 20
if self.x > 10:
self.x -= 20
if self.y > 10:
self.y -= 20
self.rotation_angle += self.angular_velocity * milliseconds / 1000
def segments(self):
point_count = len(self.points)
points = self.transformed()
return [(points[i], points[(i+1)%point_count]) for i in range(0, point_count)]
def does_collide(self, other_poly):
for other_segment in other_poly.segments():
if self.does_intersect(other_segment):
return True
return False
def does_intersect(self, other_segment):
for segment in self.segments():
if do_segments_intersect(other_segment, segment):
return True
return False
우주선, 운석도 변경사항은 없음
class Ship(PolygonModel):
def __init__(self):
super().__init__([(0.5, 0), (-0.25, 0.25), (-0.25, -0.25)])
def laser_segment(self):
dist = 20 * sqrt(2)
x, y = self.transformed()[0]
return (x, y), (x+dist*cos(self.rotation_angle), y + dist * sin(self.rotation_angle))
class Asteroid(PolygonModel):
def __init__(self):
sides = randint(5, 9)
vs = [vectors.to_cartesian((uniform(0.5, 1.0), 2 * pi * i / sides))
for i in range(0, sides)]
super().__init__(vs)
self.vx = uniform(-1, 1)
self.vy = uniform(-1, 1)
self.angular_velocity = uniform(-pi/2, pi/2)
폴리 그리기 함수에서 중심점 파트랑
그리드 그리기 함수가 추가
BLACK = (0, 0, 0)
WHITE = (255, 255, 255)
BLUE = (0, 0, 255)
GREEN = (0, 255, 0)
RED = (255, 0, 0)
LIGHT_GRAY = (240, 240, 240)
DARK_GRAY = (128, 128, 128)
width, height = 400, 400
def to_pixel(x, y):
return (width / 2 + width * x / 20, height/2 - height * y / 20)
def draw_poly(screen, polygon_model, color=BLACK):
pixel_points = [to_pixel(x, y) for x, y in polygon_model.transformed()]
pygame.draw.lines(screen, color, True, pixel_points, 2)
if polygon_model.draw_center:
cx, cy = to_pixel(polygon_model.x, polygon_model.y)
pygame.draw.circle(screen, BLACK, (int(cx), int(cy)), 4, 4)
def draw_segment(screen, v1, v2, color=RED):
pygame.draw.line(screen, color, to_pixel(*v1), to_pixel(*v2), 2)
def draw_grid(screen):
for x in range(-9, 10):
draw_segment(screen, (x, -10), (x, 10), color=LIGHT_GRAY)
for y in range(-9, 10):
draw_segment(screen, (-10, y), (10, y), color=LIGHT_GRAY)
draw_segment(screen, (-10, 0), (10, 0), color=DARK_GRAY)
draw_segment(screen, (0, -10), (0, 10), color=DARK_GRAY)
메인 함수 진입 전에
우주선이랑, 운석, 가속도 변수 초기화
메인함수가 지난번이랑 다른건
우주선 좌우전후, 그리드 그리기가 추가된게 다다
ship = Ship()
asteroid_count = 10
default_asteroids = [Asteroid() for _ in range(0, asteroid_count)]
for ast in default_asteroids:
ast.x = randint(-9, 9)
ast.y = randint(-9, 9)
acceleration = 3
def main(asteroids=default_asteroids):
pygame.init()
screen = pygame.display.set_mode([width, height])
done = False
clock = pygame.time.Clock()
while not done:
clock.tick()
for event in pygame.event.get():
if event.type == pygame.QUIT:
done = True
milliseconds = clock.get_time()
keys = pygame.key.get_pressed()
for ast in asteroids:
ast.move(milliseconds)
if keys[pygame.K_LEFT]:
ship.rotation_angle += milliseconds * (2 * pi / 1000)
if keys[pygame.K_RIGHT]:
ship.rotation_angle -= milliseconds * (2 * pi / 1000)
if keys[pygame.K_UP]:
ax = acceleration * cos(ship.rotation_angle)
ay = acceleration * sin(ship.rotation_angle)
ship.vx += ax * milliseconds/1000
ship.vy += ay * milliseconds/1000
if keys[pygame.K_DOWN]:
ax = acceleration * cos(ship.rotation_angle)
ay = acceleration * sin(ship.rotation_angle)
ship.vx -= ax * milliseconds/1000
ship.vy -= ay * milliseconds/1000
ship.move(milliseconds)
laser = ship.laser_segment()
screen.fill(WHITE)
draw_grid(screen)
if keys[pygame.K_SPACE]:
draw_segment(screen, *laser)
draw_poly(screen, ship)
for ast in asteroids:
if keys[pygame.K_SPACE] and ast.does_intersect(laser):
asteroids.remove(ast)
else:
draw_poly(screen, ast, color=GREEN)
pygame.display.flip()
pygame.quit()
동작 결과는 이럼
우주선도 움직이니까 이젠 게임같긴하다
import pygame
import vectors
from math import pi, sqrt, cos, sin, atan2
from random import randint, uniform
from linear_solver import do_segments_intersect
import numpy as np
import sys
class PolygonModel():
def __init__(self, points):
self.points = points
self.rotation_angle = 0
self.x = 0
self.y = 0
self.vx = 0
self.vy = 0
self.angular_velocity = 0
self.draw_center = True
def transformed(self):
rotated = [vectors.rotate2d(self.rotation_angle, v) for v in self.points]
return [vectors.add((self.x, self.y), v) for v in rotated]
def move(self, milliseconds):
dx, dy = self.vx * milliseconds / 1000.0, self.vy * milliseconds / 1000
self.x, self.y = vectors.add((self.x, self.y), (dx, dy))
if self.x < -10:
self.x += 20
if self.y < -10:
self.y += 20
if self.x > 10:
self.x -= 20
if self.y > 10:
self.y -= 20
self.rotation_angle += self.angular_velocity * milliseconds / 1000
def segments(self):
point_count = len(self.points)
points = self.transformed()
return [(points[i], points[(i+1)%point_count]) for i in range(0, point_count)]
def does_collide(self, other_poly):
for other_segment in other_poly.segments():
if self.does_intersect(other_segment):
return True
return False
def does_intersect(self, other_segment):
for segment in self.segments():
if do_segments_intersect(other_segment, segment):
return True
return False
class Ship(PolygonModel):
def __init__(self):
super().__init__([(0.5, 0), (-0.25, 0.25), (-0.25, -0.25)])
def laser_segment(self):
dist = 20 * sqrt(2)
x, y = self.transformed()[0]
return (x, y), (x+dist*cos(self.rotation_angle), y + dist * sin(self.rotation_angle))
class Asteroid(PolygonModel):
def __init__(self):
sides = randint(5, 9)
vs = [vectors.to_cartesian((uniform(0.5, 1.0), 2 * pi * i / sides))
for i in range(0, sides)]
super().__init__(vs)
self.vx = uniform(-1, 1)
self.vy = uniform(-1, 1)
self.angular_velocity = uniform(-pi/2, pi/2)
BLACK = (0, 0, 0)
WHITE = (255, 255, 255)
BLUE = (0, 0, 255)
GREEN = (0, 255, 0)
RED = (255, 0, 0)
LIGHT_GRAY = (240, 240, 240)
DARK_GRAY = (128, 128, 128)
width, height = 400, 400
def to_pixel(x, y):
return (width / 2 + width * x / 20, height/2 - height * y / 20)
def draw_poly(screen, polygon_model, color=BLACK):
pixel_points = [to_pixel(x, y) for x, y in polygon_model.transformed()]
pygame.draw.lines(screen, color, True, pixel_points, 2)
if polygon_model.draw_center:
cx, cy = to_pixel(polygon_model.x, polygon_model.y)
pygame.draw.circle(screen, BLACK, (int(cx), int(cy)), 4, 4)
def draw_segment(screen, v1, v2, color=RED):
pygame.draw.line(screen, color, to_pixel(*v1), to_pixel(*v2), 2)
def draw_grid(screen):
for x in range(-9, 10):
draw_segment(screen, (x, -10), (x, 10), color=LIGHT_GRAY)
for y in range(-9, 10):
draw_segment(screen, (-10, y), (10, y), color=LIGHT_GRAY)
draw_segment(screen, (-10, 0), (10, 0), color=DARK_GRAY)
draw_segment(screen, (0, -10), (0, 10), color=DARK_GRAY)
ship = Ship()
asteroid_count = 10
default_asteroids = [Asteroid() for _ in range(0, asteroid_count)]
for ast in default_asteroids:
ast.x = randint(-9, 9)
ast.y = randint(-9, 9)
acceleration = 3
def main(asteroids=default_asteroids):
pygame.init()
screen = pygame.display.set_mode([width, height])
done = False
clock = pygame.time.Clock()
while not done:
clock.tick()
for event in pygame.event.get():
if event.type == pygame.QUIT:
done = True
milliseconds = clock.get_time()
keys = pygame.key.get_pressed()
for ast in asteroids:
ast.move(milliseconds)
if keys[pygame.K_LEFT]:
ship.rotation_angle += milliseconds * (2 * pi / 1000)
if keys[pygame.K_RIGHT]:
ship.rotation_angle -= milliseconds * (2 * pi / 1000)
if keys[pygame.K_UP]:
ax = acceleration * cos(ship.rotation_angle)
ay = acceleration * sin(ship.rotation_angle)
ship.vx += ax * milliseconds/1000
ship.vy += ay * milliseconds/1000
if keys[pygame.K_DOWN]:
ax = acceleration * cos(ship.rotation_angle)
ay = acceleration * sin(ship.rotation_angle)
ship.vx -= ax * milliseconds/1000
ship.vy -= ay * milliseconds/1000
ship.move(milliseconds)
laser = ship.laser_segment()
screen.fill(WHITE)
draw_grid(screen)
if keys[pygame.K_SPACE]:
draw_segment(screen, *laser)
draw_poly(screen, ship)
for ast in asteroids:
if keys[pygame.K_SPACE] and ast.does_intersect(laser):
asteroids.remove(ast)
else:
draw_poly(screen, ast, color=GREEN)
pygame.display.flip()
pygame.quit()
if __name__ == "__main__":
main()
'컴퓨터과학 > 응용수학' 카테고리의 다른 글
파이썬 수학 - 9. 장 시뮬레이션 (0) | 2023.10.01 |
---|---|
파이썬 수학 - 8. 심볼릭 프로그래밍으로 대수 방정식 풀기 (0) | 2023.09.30 |
파이썬수학 - 6. 변화율기초 (0) | 2023.09.29 |
파이썬수학 - 5.게임과 연립일차식 풀기 (0) | 2023.09.25 |
파이썬수학 - 4. 벡터 깊게 다루기 (0) | 2023.09.25 |