I have a simple test program with a Spaceship which is supposed to point toward a planet, but it points in odd directions instead.
The purpose of the program is to test whether my test program can get the angle from the spaceship to the planet, so an alternate method won't work, since I need the angle to determine which direction to apply "gravity" in (which is what this test is for).
This is also why the script repeats multiple times but only the final angle will be graphically displayed.
My program uses code gotten from SO question Calculate angle (clockwise) between two points
The answer by "Chris St Pierre" just gave me an error for attempting to divide a float by zero (?).
The answer by "ali_m" just gave me a problem like this one.
I'm using the answer by "Colin Basnett", which doesn't work for me either, but it's my favorite method so far because it doesn't require plugins (and because it's short and doesn't just straight-away throw an error at me).
I adapted it into the function below:
class Vector:
def __init__(self, x, y):
self.x = x
self.y = y
def get_angle_between(x0,y0,x1,y1):
v1 = Vector(x0, y0)
v2 = Vector(x1, y1)
v1_theta = math.atan2(v1.y, v1.x)
v2_theta = math.atan2(v2.y, v2.x)
r = (v2_theta - v1_theta) * (180.0 / math.pi)
return r
It is called by this script in the Spaceship sprite's "move" function:
if gravityJsonQ:
for item in planets:
centreOfGravityX = planets[item]["x"] + (planets[item]["s"] / 2)
centreOfGravityY = planets[item]["y"] + (planets[item]["s"] / 2)
centreOfGravityGravity = float(planets[item]["g"])
pendingUtil = get_points(prevSubPositionX,prevSubPositionY,subPositionX,subPositionY)
for item2 in pendingUtil:
cfx,cfy = item2
circular_percentage = get_angle_between(cfx,cfy,centreOfGravityX,centreOfGravityY) / 3.6
circular_percentage (cp) is essentially degrees / 3.6 (anticlockwise, which, although the link is for clockwise angles, I tried subtracting it from 100cp (360deg) to no avail, so I doubt that's the problem)
get_points() is "Bresenham's line algorithm", and it works fine.
planets is the following dictionary:
{"Earthlike": {"x": 375, "y": 375, "s": 200, "i": "earthlike_1_beveled.png", "g": 11}}
I've tried fiddling with it a bit to see if it would start working, but the main problem is I don't understand any of the math involved, so the linked Wikipedia article(s) went right over my head. I have (frankly) not a clue to what's causing the problem or how to solve it.
Here's a link to download all 194KB (it's actually 10KB smaller when unzipped) of the program and it's textures. (Use WASD/arrow keys to move, the problem is in either lines 49 to 63 or 100 to 108 (the first line is #1 not #0)):
https://www.filehosting.org/file/details/920907/SOQ.zip
There might be some unnecessary code since I just got my main program and cut out most of the bits that weren't needed.
Just in case, here's the code (it's in the zip, but I figured I'm probably supposed to put it here anyway even though it is unrunable (real word?) without the textures):
#See lines (this line is #1) - 49 to 63 - and - 100 to 108
import json, math, os, pygame, sys, time
from pygame.locals import *
pygame.init()
baseFolder = __file__[:-10]
FPS = 30
FramePerSec = pygame.time.Clock()
xVelocity = yVelocity = rVelocity = float(0)
def get_points(x0,y0,x1,y1):
pointlist = []
x0,y0 = int(x0),int(y0)
x1,y1 = int(x1),int(y1)
dx = abs(x1-x0)
dy = abs(y1-y0)
if x0 < x1: sx = 1
else: sx = -1
if y0 < y1: sy = 1
else: sy = -1
err = dx-dy
while True:
pointlist.append((x0,y0))
if x0 == x1 and y0 == y1: return pointlist
e2 = 2 * err
if e2 > -dy:
err = err - dy
x0 += sx
if e2 < dx:
err = err + dx
y0 += sy
screen_size = 750
spaceship_texture = "spaceship.png"
spaceship_texture = spaceship_texture.replace("\n","")
spaceship_size = 60
gravityJsonQ = True
planets = {"Earthlike": {"x": 375, "y": 375, "s": 200, "i": "earthlike_1_beveled.png", "g": 11}}
displaySurf = pygame.display.set_mode((screen_size,screen_size))
displaySurf.fill((0,0,0))
subPositionX = subPositionY = float(screen_size / 2)
circular_percentage = 0
#Problem:
class Vector:
def __init__(self, x, y):
self.x = x
self.y = y
def get_angle_between(x0,y0,x1,y1):
v1 = Vector(x0, y0)
v2 = Vector(x1, y1)
v1_theta = math.atan2(v1.y, v1.x)
v2_theta = math.atan2(v2.y, v2.x)
r = (v2_theta - v1_theta) * (180.0 / math.pi)
return r
#or mabye...
class Spaceship(pygame.sprite.Sprite):
def __init__(self):
global baseFolder, screen_size, spaceship_images, spaceship_size, spaceship_texture
super().__init__()
spaceship_images = {}
for pendingUtil in range(0,100): spaceship_images[str(pendingUtil)] = pygame.image.load(baseFolder + "\\" + spaceship_texture + ".texture_map\\" + str(pendingUtil) + ".png")
self.image = spaceship_images["0"]
self.surf = pygame.Surface((int(spaceship_size), int(spaceship_size)))
self.rect = self.surf.get_rect(center = (int(screen_size / 2),int(screen_size / 2)))
self.image = pygame.transform.scale(self.image,(spaceship_size,spaceship_size))
def move(self):
global circular_percentage, rVelocity, prevSubPositionX, prevSubPositionY, subPositionX, subPositionY, xVelocity, yVelocity
pressed_keys = pygame.key.get_pressed()
if pressed_keys[K_UP] or pressed_keys[K_w]:
yVelocity -= 0.1
if pressed_keys[K_DOWN] or pressed_keys[K_s]:
yVelocity += 0.1
if pressed_keys[K_LEFT] or pressed_keys[K_a]:
xVelocity -= 0.1
if pressed_keys[K_RIGHT] or pressed_keys[K_d]:
xVelocity += 0.1
prevSubPositionX,prevSubPositionY = subPositionX,subPositionY
subPositionX += xVelocity
subPositionY += yVelocity
#Problem:
if gravityJsonQ:
for item in planets:
centreOfGravityX = planets[item]["x"] + (planets[item]["s"] / 2)
centreOfGravityY = planets[item]["y"] + (planets[item]["s"] / 2)
centreOfGravityGravity = float(planets[item]["g"])
pendingUtil = get_points(prevSubPositionX,prevSubPositionY,subPositionX,subPositionY)
for item2 in pendingUtil:
cfx,cfy = item2
circular_percentage = get_angle_between(cfx,cfy,centreOfGravityX,centreOfGravityY) / 3.6
#Problem will (very likely) be either here or noted area above
while circular_percentage < 0: circular_percentage += 100
while circular_percentage > 99: circular_percentage -= 100
self.rect = self.surf.get_rect(center = (int(subPositionX),int(subPositionY)))
self.image = spaceship_images[str(int(circular_percentage))]
self.image = pygame.transform.scale(self.image,(spaceship_size,spaceship_size))
Player = Spaceship()
all_sprites = pygame.sprite.Group()
all_sprites.add(Player)
while True:
for event in pygame.event.get():
if event.type == QUIT:
pygame.quit()
sys.exit()
displaySurf.fill((0,0,0))
for item in planets:
current_planet_image = pygame.image.load(planets[item]["i"])
current_planet_image = pygame.transform.scale(current_planet_image,(planets[item]["s"],planets[item]["s"]))
displaySurf.blit(current_planet_image,(planets[item]["x"],planets[item]["y"]))
for entity in all_sprites:
displaySurf.blit(entity.image,entity.rect)
entity.move()
pygame.display.update()
FramePerSec.tick(FPS)