How to check distance between two objects in PyOpenGL? - python-3.x

I am making a RPG in PyOpenGL and I want to check if the camera is pointing at the object (made by vertices) in a certain distance. How can I do that?
I have tried to use range() on the vertices of an object to check if the camera is in the range. But it didn't work.
import pygame
from pygame.locals import *
from OpenGL.GL import *
from OpenGL.GLU import *
import math,sys
def touched(tar_x,tar_y,tar_z,tar_w,tar_h,tar_d,tar_x1,tar_y1,tar_z1,tar_w1,tar_h1,tar_d1):
for i in range(tar_x1,tar_x1 + tar_w1):
for j in range(tar_y1,tar_y1 + tar_h1):
for k in range(tar_z1,tar_z1 + tar_d1)
if (tar_x < i < tar_x + tar_w) and (tar_y < j < tar_y + tar_h) and (tar_z < k < tar_z + tar_d):
return True
return False
#[...]
while True:
#[...]
if touched(int(person.x),int(person.y),int(person.z),10,5,5,int(camera_pos[0]),int(camera_pos[1]),int(camera_pos[2]),1,1,1): #
print("yes!") #

If you wat to kow if 2 cubes are touching you've to check if the cubes are "overlapping" in all 3 dimensions.
If you've a range [tar_x, tar_x+tar_w] and a 2nd range [tar_x1, tar_x1+tar_w1] then you can check if the ranges are "overlapping" by:
intersect = tar_x < tar_x1+tar_w1 and tar_x1 < tar_x+tar_w
Do this check for all 3 dimensions:
def touched(tar_x,tar_y,tar_z,tar_w,tar_h,tar_d,tar_x1,tar_y1,tar_z1,tar_w1,tar_h1,tar_d1):
intersect_x = tar_x < tar_x1+tar_w1 and tar_x1 < tar_x+tar_w
intersect_y = tar_y < tar_y1+tar_h1 and tar_y1 < tar_y+tar_h
intersect_z = tar_z < tar_z1+tar_d1 and tar_z1 < tar_z+tar_d
return intersect_x and intersect_y and intersect_z
If you want to know, if a point is inside a cuboid volume, then you've to test for each dimension, if the coordinate tar_w1 is in the range [tar_x, tar_x+tar_w]:
is_in = tar_x < tar_x1 < tar_x+tar_w
Again check this for all 3 dimension
def isIn(tar_x,tar_y,tar_z,tar_w,tar_h,tar_d,tar_x1,tar_y1,tar_z1):
is_in_x = tar_x < tar_x1 < tar_x+tar_w
is_in_y = tar_y < tar_y1 < tar_y+tar_h
is_in_z = tar_z < tar_z1 < tar_z+tar_d
return is_in_x and is_in_y and is_in_z
If you want to know the distance of a point ton another point, e.g. the center of the a cuboid volume, then you can use pygame.math.Vector3 and .distance_to():
centerPt = pygame.math.Vector3(tar_x + tar_w/2, tar_y + tar_h/2, tar_z + tar_d/2)
point2 = pygame.math.Vector3(tar_x1, tar_y1, tar_z1)
distance = centerPt.distance_to(point2)

Related

tkinter how do i calculate the normal vector and the conservation of the kinetic energy of all particles in python?

I was trying to calculate the normal vector n formula for normal vector and the tangential vectors t tangential vector n=v of two particles p1 and p2 to find the conservation of kinetic energy conservation of energy
or here's another way to write the formula: formula 2
but i don't really know where and how in the code to implent this?
from tkinter import *
from random import *
from math import *
myHeight=250#400
myWidth=400#800
mySpeed=20#100
col= randint(0,255)
radius = randint(0,50)
print (col)
#x= 60
global particules
particules = []
def initialiseParticule(dx,dy,radius,color):
x, y = randint(0,myWidth), randint(0,myHeight) #100
radius = randint(0,10)
#color = randint(0,255)
#col1=str(color)
k = myCanvas.create_oval(x-radius,y-radius,\
x+radius,y+radius,\
width=2,fill=color)
b = [x, y, dx, dy, radius]
particules.append(b)
#print(k)
def updateParticules():
N = len(particules)
for i in range(N):
# update displacement
particules[i][0] += particules[i][2]
particules[i][1] += particules[i][3]
#xi += vxi
#yi += vyi
# collision with walls
if particules[i][0]<particules[i][4]or particules[i][0]>=myWidth-particules[i][4]:
particules[i][2] *= -1
if particules[i][1]<particules[i][4] or particules[i][1]>=myHeight-particules[i][4]:
particules[i][3] *= -1
# collision with other particles
for j in range(N):
if i != j:
xi, yi = particules[i][0], particules[i][1]
vxi, vyi = particules[i][2], particules[i][3]
xj, yj = particules[j][0], particules[j][1]
vxj, vyj = particules[j][2], particules[j][3]
dij = sqrt((xi-xj)**2 + (yi-yj)**2)
# print(dij)
# # collision !!!
if dij <= particules[i][4]+particules[j][4]:
particules[i][2] *= -1
particules[j][2] *= -1
particules[i][3] *= -1
particules[j][3] *= -1
r = particules[i][4]
myCanvas.coords(i+1, particules[i][0]-r, particules[i][1]-r,
particules[i][0]+r, particules[i][1]+r)
def animation():
miseAJourBalles()
myCanvas.after(mySpeed, animation)
mainWindow=Tk()
mainWindow.title('Pong')
#mainWindow.geometry(str(myWidth)+'x'+str(myHeight+100))
myCanvas=Canvas(mainWindow, bg='dark grey', height=myHeight, width=myWidth)
myCanvas.pack(side=TOP)
N = 3
for n in range(N):
# initialiseParticules( -1, -1, radius,'randint(0,10)')
initialiseParticules( -1, -1, radius,'pink')
animation()
#bou=Button(mainWindow,text="Leave",command=mainWindow.destroy)
#bou.pack()
mainWindow.mainloop()

Solving cars moving in multiple lanes simulation problem

I am trying to simulate cars moving in multiple lanes in python. The problem is like this:
The number of cars, the roadlength, the probability and vmax are all input values.
Rules:
1. If vi < vmax, increase the velocity vi of car i by one unit, that is, vi → vi + 1. This change models the process of acceleration to the maximum velocity.
2. Compute the distance to the next car in the same lane and the distance to the cars in both (if there are 2) lanes next to the car.
If d=max([d1,d2,d3]) and vi ≥ d, then reduce the velocity to vi = d − 1 to prevent crashes and switch lane to the lane where the distance to the next car is d (if there are multiple choose one at random or whichever you want).
Else (meaning there is at least one lane next to the car's lane or it could be the same lane that the car is in where d > vi) go in that lane and don't change the velocity of the car if there is more than one lane, pick one at random.
3. With probability p, reduce the velocity of a moving car by one unit: vi → vi − 1, only do this when v > 0 to avoid negative velocities
4. Update the position xi of car i so that xi(t + 1) = xi(t) + vi
Also the path of the cars is circular, meaning there will be cars in front and behind.
Below is my attempt to solve the problem. Don't get confused over the variables theta and r. theta is just the position and r is the lane.
My attempt:
from matplotlib import pyplot as plt
import random
import math
from matplotlib import animation
import numpy as np
from operator import attrgetter
roadLength = 100
numFrames = 200
nlanes = 3
numCars = 20
posss =[]
theta = []
r = []
color = []
probability = 0.5
vmax = 1
cars=[]
class Car:
def __init__(self, position, velocity, lane):
self.position = position
self.velocity = velocity
self.lane = lane
def pos(car,k):
rand = random.uniform(0,1)
if car[k].velocity < vmax:
car[k].velocity += 1
dist = 0
if car[k].lane == 1:
temp_lanes_between = [0,1]
if car[k].lane == nlanes and nlanes != 1:
temp_lanes_between = [-1 ,0]
if 1 < car[k].lane < nlanes:
temp_lanes_between = [-1 ,0, 1]
iterator = []
for p in range(k+1, numCars):
iterator.append(p)
#if car[k+1].position - car[k].position <= car[k].velocity and car[k].lane == car[k+1].lane:
for p in range(k):
iterator.append(p)
for s in iterator:
if car[s].lane - car[k].lane in temp_lanes_between:
temp_lanes_between.remove(car[s].lane - car[k].lane)
distance = min([abs((car[s].position - car[k].position) % roadLength), roadLength - abs((car[s].position - car[k].position) % roadLength)])
if dist < distance:
dist = distance
l = car[s].lane
if dist <= car[k].velocity:
break
if temp_lanes_between:
j=random.randrange(0, len(temp_lanes_between))
car[k].lane += temp_lanes_between[j]
if temp_lanes_between == [] and dist <= car[k].velocity:
car[k].velocity = dist - 1
car[k].lane = l
if rand < probability and car[k].velocity > 0:
car[k].velocity = car[k].velocity - 1
car[k].position = car[k].position + car[k].velocity
return car[k].position
for i in range(numCars):
cars.append(Car(i, 0, 1))
theta.append(0)
r.append(1)
color.append(i)
posss.append(i)
fig = plt.figure()
ax = fig.add_subplot(111)
point, = ax.plot(posss, r, 'o')
ax.set_xlim(-10, 1.2*numFrames)
ax.set_ylim(-2, nlanes + 3)
def animate(frameNr):
sort_cars = sorted(cars, key=attrgetter("position"))
for i in range(numCars):
pos(sort_cars,i)
for k in range(numCars):
theta[k]=cars[k].position
r[k]=cars[k].lane
print(theta)
print(r)
point.set_data(theta, r)
return point,
def simulate():
anim = animation.FuncAnimation(fig, animate,
frames=numFrames, interval=100, blit=True, repeat=False)
plt.show()
simulate()
I get error saying: "local variable 'l' referenced before assignment" in the line where car[k].lane = l . I know that they mean that l doesn't have any value and therefore I get this error. But I don't see how this is possible. Every time pos() is run it should always go through the line l = car[s].lane and there it gets assigned a value. Maybe there are more errors in the code above but I have really given it my best shot and I don't know what to do.
Thanks in advance!

How to implement quick sort on python?

maybe I’m the next person who asks how to release quick sort on python correctly. But it’s important for me to know if I wrote this algorithm correctly by reading the pseudocode from the textbook Essential Algorithms: A Practical Approach to Computer Algorithms.
When I run the code, I get this message. RecursionError: maximum recursion depth exceeded in comparison
import random
def quickSort(arr, start, end):
if start >= end: # if len(arr) < 2
return arr
else:
divideIndex = partition(arr, start, end)
quickSort(arr, start, divideIndex - 1)
quickSort(arr, divideIndex, end)
def partition(arr, head, tail):
left = head
right = tail
pivot = arr[(head + tail) // 2] # mid
while right >= left:
# looking through the array from the left
while arr[left] <= pivot:
left = left + 1
# looking through the array from the right
while arr[right] > pivot:
right = right - 1
# found a couple of elements that can be exchanged.
if left <= right:
swap(arr[right], arr[left])
# move the left and right wall
left = left + 1
right = right - 1
# return one elements if not found a couple
return left
def swap(arr1, arr2):
temp = arr1
arr1 = arr2
arr2 = temp
# Generator random variables
deck = list(range(50))
random.shuffle(deck)
start = 0
end = len(deck) - 1
print(quickSort(deck, start, end))
Try this:
def partition(arr,low,high):
i = ( low-1 )
pivot = arr[high]
for j in range(low , high):
if arr[j] <= pivot:
i = i+1
arr[i],arr[j] = arr[j],arr[i]
arr[i+1],arr[high] = arr[high],arr[i+1]
return ( i+1 )
def quickSort(arr,low,high):
if low < high:
pi = partition(arr,low,high)
quickSort(arr, low, pi-1)
quickSort(arr, pi+1, high)

Creating a symmetrical grid of random size squares in Python3/Tkinter

I have a question revolving around what would be a viable approach to placing out random-sized squares on a symmetrical, non-visible grid on a tkinter-canvas. I'm going to explain it quite thoroughly as it's a somewhat proprietary problem.
This far I've tried to solve it mostly mathematically. But I've found it to be quite a complex problem, and it seems reasonable that there would be a better approach to take it on than what I've tried.
In its most basic form the code looks like this:
while x_len > canvas_width:
xpos = x_len + margin
squares[i].place(x=xpos, y=ypos)
x_len += square_size + space
i += 1
x_len is the total width of all the squares on a given row, and resets when exiting the while-loop (eg. when x_len > window width), among with xpos (the position on X), as well as altering Y-axis to create a new row.
When placing same-size squares it looks like this:
So far so good.
However when the squares are of random-size it looks like this (at best):
The core problem, beyond that the layout can be quite unpredictable, is that the squares aren't centered to the "invisible grid" - because there is none.
So to solve this I've tried an approach where I use a fixed distance and a relative distance based on every given square. This yields satisficing results for the Y-axis on the first row, but not on the X-axis, nor the following rows on Y.
See example (where first row is centered on Y, but following rows and X is not):
So with this method I'm using a per-square alteration in both Y- and X-axis, based on variables that I fetch from a list that contain widths for all of the generated squares.
In it's entirety it looks like this (though it's work in progress so it's not very well optimized):
square_widths = [60, 75, 75, 45...]
space = square_size*0.5
margin = (square_size+space)/2
xmax = frame_width - margin - square_size
xmin = -1 + margin
def iterate(ypos, xpos, x_len):
y = ypos
x = xpos
z = x_len
i=0
m_ypos = 0
extra_x = 0
while len(squares) <= 100:
n=-1
# row_ypos alters y for every new row
row_ypos += 200-square_widths[n]/2
# this if-statement is not relevant to the question
if x < 0:
n=0
xpos = x
extra_x = x
x_len = z
while x_len < xmax:
ypos = row_ypos
extra_x += 100
ypos = row_ypos + (200-square_widths[n])/2
xpos = extra_x + (200-square_widths[n])/2
squares[i].place(x=xpos, y=ypos)
x_len = extra_x + 200
i += 1
n += 1
What's most relevant here is row_ypos, that alters Y for each row, as well as ypos, that alters Y for each square (I don't have a working calculation for X yet). What I would want to achieve is a similar result that I get for Y-axis on the first row; on all rows and columns (eg. both in X and Y). To create a symmetrical grid with squares of different sizes.
So my questions are:
Is this really best practice to solve this?
If so - Do you have any tips on decent calculations that would do the trick?
If not - How would you approach this?
A sidenote is that it has to be done "manually" and I can not use built-in functions of tkinter to solve it.
Why don't you just use the grid geometry manager?
COLUMNS = 5
ROWS = 5
for i in range(COLUMNS*ROWS):
row, col = divmod(i, COLUMNS)
l = tk.Label(self, text=i, font=('', randint(10,50)))
l.grid(row=row, column=col)
This will line everything up, but the randomness may make the rows and columns different sizes. You can adjust that with the row- and columnconfigure functions:
import tkinter as tk
from random import randint
COLUMNS = 10
ROWS = 5
class GUI(tk.Frame):
def __init__(self, master=None, **kwargs):
tk.Frame.__init__(self, master, **kwargs)
labels = []
for i in range(COLUMNS*ROWS):
row, col = divmod(i, COLUMNS)
l = tk.Label(self, text=i, font=('', randint(10,50)))
l.grid(row=row, column=col)
labels.append(l)
self.update() # draw everything
max_width = max(w.winfo_width() for w in labels)
max_height = max(w.winfo_height() for w in labels)
for column in range(self.grid_size()[0]):
self.columnconfigure(col, minsize=max_width) # set all columns to the max width
for row in range(self.grid_size()[1]):
self.rowconfigure(row, minsize=max_height) # set all rows to the max height
def main():
root = tk.Tk()
win = GUI(root)
win.pack()
root.mainloop()
if __name__ == "__main__":
main()
I found the culprit that made the results not turn out the way expected, and it wasn't due to the calculations. Rather it turned out that the list I created didn't put the squares in correct order (which I should know since before).
And so I fetched the width from the raw data itself, which makes a lot more sense than creating a list.
The function now looks something like this (again, it's still under refinement, but I just wanted to post this, so that people don't waste their time in coming up with solutions to an already solved problem :)):
def iterate(ypos, xpos, x_len):
y = ypos
x = xpos
z = x_len
i=0
while len(squares) <= 100:
n=0
if y > 1:
ypos -= max1 + 10
if y < 0:
if ypos < 0:
ypos=10
else:
ypos += max1 + 10 #+ (max1-min1)/2
if x < 0:
n=0
xc=0
xpos = x
x_len = z
while x_len < xmax:
yc = ypos + (max1-squares[i].winfo_width())/2
if xpos <= 0:
xpos = 10
else:
xpos += max1 + 10
xc = xpos + (max1-squares[i].winfo_width())/2
squares[i].place(x=xc, y=yc)
x_len += max1 + 10
print (x_len)
i += 1
n += 1

Infinite loops for turtle listen

I am running into an infinite loop in this code. It should break out if you click in the desired range, however it goes into an infinite loop displaying the current position of the turtle in the row and column format.
def wait_for_click():
turt.penup()
wn.onclick(turt.goto)
wn.listen()
pos = [-1,-1]
row = -1
column = -1
while row > 8 or row < 0 or column > 8 or column < 0:
row = ((turt.ycor()-turt.ycor()%75)+75)/75 + 4
column = ((turt.xcor()-turt.xcor()%75)+75)/75 + 4
pos[0] = row
pos[1] = column
print(pos)
I think your basic approach is wrong: don't loop waiting for the turtle to show up somewhere interesting, instead use the click handler to test where the turtle showed up:
from math import ceil
from turtle import Turtle, Screen
CELLS = 8
CELL_SIZE = 75
STAMP_SIZE = 20
def click_handler(x, y):
screen.onclick(None)
yertle.goto(x, y)
if 0 < x < CELLS and 0 < y < CELLS:
position = [ceil(x), ceil(y)]
print(position)
screen.onclick(click_handler)
screen = Screen()
screen.setup(CELL_SIZE * (CELLS + 2), CELL_SIZE * (CELLS + 2))
screen.setworldcoordinates(-1, -1, CELLS + 1, CELLS + 1)
screen.onclick(click_handler)
marker = Turtle(shape="square")
marker.penup()
marker.turtlesize(CELL_SIZE / STAMP_SIZE)
marker.color("gray", "white")
for x in range(0, CELLS):
for y in range(0, CELLS):
marker.goto(x + 0.5, y + 0.5)
marker.stamp()
marker.color(*marker.color()[::-1])
marker.color(*marker.color()[::-1])
yertle = Turtle(shape="circle")
yertle.speed("fastest")
yertle.penup()
screen.mainloop()
I've thrown in code to show the grid so you can see that where you click matches the printed output. I used setworldcoordinates() to simplify the problem with the side effect that I've given you a larger border.
The lower left cell is [1, 1] and the upper right is [8, 8] -- you may want to do some math to switch these around.

Resources