I'm creating a function to draw a office tower:
windows are 20 pixels square
the gap between the windows is 10 pixels
the door is 20 pixels wide, 50 pixels tall, and orange
My code doesn't draw it properly:
from graphics import *
from random import *
def add_window(win, nH, nV):
w, h = win.getWidth(), win.getHeight()
rects = []
for x in range(nH):
rects.append([])
for y in range(nV):
r = Rectangle(Point( x *w//nH, y *h//vV),
Point((x+1)*w//nH, (y+1)*h//nV))
window = [ r,
True,
[ 'red', 'green' ]
]
rects[x].append(window)
rects[x][y][0].draw(win)
rects[x][y][0].setOutline('blue')
color = window[2][randint[0,1]]
rects[x][y][0].setFill(color)
return rects
WIN_W, WIN_H = 500, 400
#Top left coner of the building
BLDG_LEFT, BLDG_TOP = 50, 50
#How many floors, how many windows perfloor, window digit and gap
FLOORS, WIN_FLR, WIN_SZ, GAP = 10, 5, 20, 5
win = None
#Syntax : window[x][y]
# [0] : Rectangle() object
# [1] : True/False
windows = []
#--------------------------------------------------------------------
def draw_window(x, y):
global windows
windows = []
left = BLDG_LEFT + GAP + x* (WIN_SZ+GAP)
top = BLDG_TOP + GAP + y* (WIN_SZ+GAP)
r = Rectangle(Point( x *WIN_SZ+GAP, y *(WIN_SZ+GAP)),
Point((x+1)*WIN_SZ+GAP, (y+1)*(WIN_SZ+GAP)))
windows[x][y].append(r)
bit = randint(0,1)
windows[x][y].append(bool(bit))
windows[x][y][0].setFill(COLORS[bit])
windows[x][y][0].draw(win)
def draw_windows():
for i in range(WIN_FLR):
windows.append([])
for j in range(FLOORS):
windows[i].append([])
draw_window(i, j)
def office_tower():
global win
win = GraphWin("OFFICE TOWER", WIN_W, WIN_H)
draw_window(1, 1)
while True:
pt = win.getmouse()
if pt.x < 10 and pt.y < 10:
break
# windows coordinates
x = int((pt.x - BLDG_LEFT - GAP)/(WIN_SZ + GAP))
y = int((pt.y - BLDG_TOP - GAP)/(WIN_SZ + GAP))
print(str((pt.x, pt.y)) + ' --> ' + str((x, y)))
windows[x][y][1] = netwindows[x][y][1]
windows[x][y][0].setFill(COLORS[windows[x][y][1]])
def draw_building():
global windows
win = GraphWin("OFFICE TOWER", WIN_W, WIN_H)
N_H, N_V = 5, 10
while True:
pt = win.getMouse()
m_x, m_y = pt.getX(), pt.getY()
# Grid coordinates:
g_x = m_x // (WIN_W//N_H)
g_y = m_y // (WIN_H//N_V)
# For development purposes:
if m_x < 10 and m_y < 10:
break
This seems to be the worst virtual high-rise disaster since Irwin Allen's "Towering Inferno". There appear to be at least two different incomplete implementations in the file where most of the functions are never called and the code draws nothing. Here's my salvage job on the ruins:
from random import randint
from graphics import *
GRAPHIC_WINDOW_WIDTH, GRAPHIC_WINDOW_HEIGHT = 500, 400
# Top left coner of the building
BUILDING_LEFT, BUILDING_TOP = 50, 50
COLORS = ['gray25', 'gray85'] # lights off, lights on
# How many BUILDING_FLOORS, how many windows per floor, window size and gap
BUILDING_FLOORS, WINDOWS_PER_FLOOR, WINDOW_SIZE, WINDOW_GAP = 10, 5, 20, 5
WINDOW_FRAME = WINDOW_SIZE + WINDOW_GAP
# Syntax : window[x][y]
# [0] : Rectangle() object
# [1] : True/False
#--------------------------------------------------------------------
def draw_window(row, column, left, top):
r = Rectangle(Point(left + column * WINDOW_FRAME, top + row * WINDOW_FRAME), \
Point(left + (column + 1) * WINDOW_FRAME, top + (row + 1) * WINDOW_FRAME))
bit = bool(randint(0, 1))
r.setFill(COLORS[bit])
r.draw(win)
windows[row][column] = [r, bit]
def draw_windows(left, top):
for row in range(BUILDING_FLOORS):
windows.append([])
for column in range(WINDOWS_PER_FLOOR):
windows[row].append(None)
draw_window(row, column, left, top)
def office_tower():
draw_windows(BUILDING_LEFT, BUILDING_TOP)
while True:
pt = win.getMouse()
if pt.x < BUILDING_LEFT and pt.y < BUILDING_TOP:
break # clean exit stategy
# windows coordinates
column = int((pt.x - BUILDING_LEFT - WINDOW_GAP) / WINDOW_FRAME)
row = int((pt.y - BUILDING_TOP - WINDOW_GAP) / WINDOW_FRAME)
# print((pt.x, pt.y), '-->', (row, column))
windows[row][column][1] = not windows[row][column][1]
windows[row][column][0].setFill(COLORS[windows[row][column][1]])
win = GraphWin('OFFICE TOWER', GRAPHIC_WINDOW_WIDTH, GRAPHIC_WINDOW_HEIGHT)
windows = []
office_tower()
win.close()
This draws the following building:
Where you can click on the windows to toggle their color. (I chose an 'on' / 'off' motif.) Clicking to the upper left of the building exits.
Related
I'm trying to create a program that renders an object in 3D and that you can rotate and control with your mouse's position. I'm trying to display the faces of the object but I don't know how could I display the closer faces first so that there isn't any 'background' face displayed in front of closer faces.
the code I provided is fully reproducable, just copy and paste it if you have tkinter and numpy.
from numpy import *
from tkinter import *
#eulers angles matrixes
def Rx(theta):
return mat(mat([[1, 0 , 0 ],
[0, cos(theta), -sin(theta)],
[0, sin(theta), cos(theta) ]]).round(15))
def Ry(theta):
return mat(mat([[cos(theta), 0, -sin(theta)],
[ 0 , 1, 0 ],
[sin(theta), 0, cos(theta) ]]).round(15))
def Rz(theta):
return mat(mat([[cos(theta), -sin(theta), 0],
[sin(theta), cos(theta) , 0],
[ 0 , 0 , 1]]).round(15))
#returns a 2d projection matrix,
def proj2d(p):
return mat(eye(2,3)*p)
#tuple into vector
def vector(tuple):
return transpose(mat(list(tuple)))
#updates position of the 3D point in function of the x,y,z angles
def position(pts3d,anglex,angley,anglez):
for i in range(len(pts3d)):
pts3d[i] = (float((Rx(anglex) * vector(pts3d[i]))[0]),
float((Rx(anglex) * vector(pts3d[i]))[1]),
float((Rx(anglex) * vector(pts3d[i]))[2]))
pts3d[i] = (float((Ry(angley) * vector(pts3d[i]))[0]),
float((Ry(angley) * vector(pts3d[i]))[1]),
float((Ry(angley) * vector(pts3d[i]))[2]))
pts3d[i] = (float((Rz(anglez) * vector(pts3d[i]))[0]),
float((Rz(anglez) * vector(pts3d[i]))[1]),
float((Rz(anglez) * vector(pts3d[i]))[2]))
#makes a projection of the 3d points on the 2d screen
def projected(pts3d):
pts2d = []
for i in pts3d:
pts2d.append((float((proj2d(30+0.75*i[2]) * vector(i))[0]),
float((proj2d(30+0.75*i[2]) * vector(i))[1])))
return pts2d
#displays dots
def dots(canvas,points):
for i in points:
canvas.create_oval(H/2+5+i[0],H/2+5+i[1],H/2-5+i[0],H/2-5+i[1],fill = 'white')
#displays vertices
def connect(canvas,vertics,points):
for i in vertics:
canvas.create_line(H/2+points[int(i[0])][0],H/2+points[int(i[0])][1],H/2+points[int(i[1])][0],H/2+points[int(i[1])][1],width = 2,fill = 'white')
#what I should modify, I guess: it's the funtion that displays the faces of the object
def face(canvas,faces,points,colors):
for i in range(len(faces)):
coordsface = ()
for j in faces[i]:
coordsface += (H/2+points[int(j)][0],H/2+points[int(j)][1])
canvas.create_polygon(coordsface,fill = colors[i])
#major functions, updates position each time interval(delay)
def updateposition(self,H,canvas,points,vertics,faces,clrfc,delai,domegax,domegay,domegaz):
canvas.delete('all')
y,x = self.winfo_pointerx() - self.winfo_rootx() - H/2, self.winfo_pointery() - self.winfo_rooty() - H/2
if abs(x) >= H/2 or abs(y) >= H/2: x,y = 0,0
domegax -= 0.00001*(x)
domegay -= 0.00001*(y)
position(points,domegax,domegay,domegaz)
if affpts == 'y':
dots(canvas,projected(points))
if affart == 'y':
connect(canvas,vertics,projected(points))
if afffac == 'y':
face(canvas,faces,projected(points),clrfc)
self.after(delai,updateposition,self,H,canvas,points,vertics,faces,clrfc,delai,domegax,domegay,domegaz)
## cube
def pts3Dcube():
#points
a = ( L/2, L/2, L/2)
b = ( L/2, L/2,-L/2)
c = ( L/2,-L/2, L/2)
d = ( L/2,-L/2,-L/2)
e = (-L/2, L/2, L/2)
f = (-L/2, L/2,-L/2)
g = (-L/2,-L/2, L/2)
h = (-L/2,-L/2,-L/2)
pts3d = [a,b,c,d,e,f,g,h]
#vertices
aretes = []
for i in [0,2,4,6]:
aretes.append(str(i)+str(i+1))
for i in [0,1,4,5]:
aretes.append(str(i)+str(i+2))
for i in [0,1,2,3]:
aretes.append(str(i)+str(i+4))
#faces
faces = ['0132','4576','0154','2376','1375','0264']
clrfc = ['green','red','yellow','blue','orange','white']
return pts3d, aretes, faces, clrfc
## initial conditions
L = 5
H = 600
delai = 5
self = Tk()
canvas = Canvas(self,height = H,width = H,bg = 'gray13')
canvas.pack()
objet = pts3Dcube() #object choice
domegax = 0.0
domegay = 0.0
domegaz = 0.0
#initial rotation angles
iomegax = 0
iomegay = 0
iomegaz = 0
#displaying points, vertices, faces or not
affpts = 'y'
affart = 'y'
afffac = 'y'
position(objet[0],iomegax,iomegay,iomegaz) #initial rotation
updateposition(self,H,canvas,objet[0],objet[1],objet[2],objet[3],delai,domegax,domegay,domegaz) # dynamic rotation
if any of you have an idea, please comment it or something, I'm lost.
Thanks!
I'm creating a game by using python and I'm not sure how to implement the next step. The game is about players walking on ice and trying not to fall into the water below.
The players are not supposed to step on water and the ice is supposed to turn into water, but I don't know how to do this. I also don't know how I can make the players move to the ice that is beside them. Is there a way to do this?
I'm using a module called graphics, and here's what I've tried so far before I got stuck:
from graphics import *
COLUMN, ROW = 7, 10
WIN_W, WIN_H = 455, 320
WIN_SZ, GAP = 40, 5
COLORS = ['blue', 'white']
CIRCLE, RECTANGLE, COLOR = range(3)
player = 'X'
ices = []
def draw_ice(x, y):
left = GAP + x * (WIN_SZ + GAP)
top = GAP + y * (WIN_SZ + GAP)
r = Rectangle(Point(left, top), Point(left + WIN_SZ, top + WIN_SZ))
c = Circle(r.getCenter(), WIN_SZ / 4)
bit = 1
c.setFill(COLORS[bit])
c.setOutline('white')
r.draw(win)
c.draw(win)
ices[x][y] = [c, r, bool(bit)]
def draw_ices():
for i in range(ROW):
ices.append([])
for j in range(COLUMN):
ices[i].append(None)
draw_ice(i, j)
def MS1():
x_player = ices[0][3][CIRCLE] # X / Red Player
x_player.setFill('red')
o_player = ices[9][3][CIRCLE] # O / Red Player
o_player.setFill('blue')
while True:
pt = win.getMouse()
x = int((pt.x - GAP) / (WIN_SZ + GAP))
y = int((pt.y - GAP) / (WIN_SZ + GAP))
print((pt.x, pt.y), '-->', (x, y))
ices[x][y][COLOR] = not ices[x][y][COLOR]
ices[x][y][CIRCLE].setFill(COLORS[ices[x][y][COLOR]])
win = GraphWin("Icebreaker", WIN_W, WIN_H)
def MS1():
Here is my code picture:
enter image description here
Here is the game instruction
enter image description here
I am trying to produce an algorithm where multiple agents (blue) work together as a team to capture a slightly faster enemy agent (red) by preforming surrounding and circling tactics in a 2D grid. So I am trying to make a robust multi-agent algorithm that would allow multi-agents would capture an intelligent and faster enemy agent
So I attempted to give the enemy agent navigation and obstacle avoidance abilities by using something known as potential field navigation. Basically, the enemy agent pretends there is an attraction force at the exit and a repulsive force by each blue agent
Click here for more details on potential fields
When I implemented this into the enemy agent, the agent being attracted to the exit is successful (except for the fact it slows down when it is close to it). The main problem I am having is with the repulsion field where the enemy is trying to avoid the blue particles. While it attempts to escape, it does things such as moving in a zig-zag pattern rapidly, run around a blue particle or group or particles in circles.
I would like the enemy agent to smoothly avoid the blue particles in an intelligent way.
Also, is someone knows how to turn repulsive field into a tangential field, that would be great. I would like tangential fields so that the red particle can slip through the blue particles.
Also, although the code is long, the only function that the enemy agent uses is goToExit(), so that function and any function that it calls will be the only ones relevant.
My code:
import numpy as np
from matplotlib import pyplot as plt
from matplotlib import animation
from random import randint
import random
import math
keep = False
keepX = 0
keepY = 0
### Variables that we can play with ###
interestPointVisual = False
huntEnemy = True
numOfAgents = 10
enemyTopSpeed = 0.5
topSpeed = 0.3
secondDoor = False
resultVisual = False
#obstacleAvoidance = False
chargeEnemy = True
maxFrame = 2000
agentRadius = 2
####################################
phaseCount = 0
fig = plt.figure()
fig.set_dpi(100)
fig.set_size_inches(5, 4.5)
# Declaring the enemy and ally agents
ax = plt.axes(xlim=(0, 100), ylim=(0, 100))
enemy = plt.Circle((10, -10), 0.95, fc='r')
agent = plt.Circle((10, -10), 0.95, fc='b')
if interestPointVisual:
interestColor = 'y'
interestSize = 0.55
else:
interestColor = 'w'
interestSize = 0.55
#interestSize = 0.000001
midpoint = plt.Circle((10, -10), interestSize, fc=interestColor)
eastpoint = plt.Circle((10, -10), interestSize, fc=interestColor)
northpoint = plt.Circle((10, -10), interestSize, fc=interestColor)
westpoint = plt.Circle((10, -10), interestSize, fc=interestColor)
northeastpoint = plt.Circle((10, -10), interestSize, fc=interestColor)
mideastpoint = plt.Circle((10, -10), interestSize, fc=interestColor)
midwestpoint = plt.Circle((10, -10), interestSize, fc=interestColor)
northwestpoint = plt.Circle((10, -10), interestSize, fc=interestColor)
# Adding the exits
rect_size = 5
x_se_s = 47
x_se = 50
y_se = 0
southExit = plt.Rectangle([x_se_s - rect_size / 2, y_se - rect_size / 2], rect_size + 3, rect_size -2 , facecolor='black', edgecolor='black')
x_ne = 50
y_ne = 101
if secondDoor:
northExit = plt.Rectangle([x_ne - rect_size / 2, y_ne - rect_size / 2], rect_size + 3, rect_size -2 , facecolor='black', edgecolor='black')
patches_ac = []
if interestPointVisual:
ax.add_patch(midpoint)
ax.add_patch(northpoint)
ax.add_patch(eastpoint)
ax.add_patch(westpoint)
ax.add_patch(mideastpoint)
ax.add_patch(midwestpoint)
ax.add_patch(northeastpoint)
ax.add_patch(northwestpoint)
# enemy, north, east, south, west
# 0 represents unoccupied, 1 represent occupied
global occupied_ar
global victory
global agentID
global timeStep
global agentLocationAR
ax.add_patch(agent)
for x in range(0, numOfAgents - 1):
agent_clone = plt.Circle((10, -10), 0.95, fc='b')
agent_clone.center = (random.randint(1, 100), random.randint(1, 100))
patches_ac.append(agent_clone)
ax.add_patch(agent_clone)
ax.add_patch(enemy)
# Adding exit patches
ax.add_patch(southExit)
if secondDoor:
ax.add_patch(northExit)
def victoryCheck(enemy_patch):
global agentLocationAR
ex, ey = enemy_patch.center
rangeVal = 0.8
for i in range(0, numOfAgents-1):
if abs(float(ex-agentLocationAR[i][0])) < rangeVal and abs(float(ey-agentLocationAR[i][1])) < rangeVal:
return True
return False
def enemyWonCheck(enemy_patch):
x,y = enemy_patch.center
if (x > x_se - 4 and x < x_se + 4) and y <= y_se +4:
return True
return False
def borderCheck(x,y):
if x < 0:
x = 0
elif x > 100:
x = 100
if y < 0:
y = 0
elif y > 100:
y = 100
return x, y
def init():
global occupied_ar
global agentLocationAR
global keep
global keepX
global keepY
keep = False
keepX = 0
keepY = 0
#enemy.center = (50, 50)
enemy.center = (random.randint(1, 100), random.randint(40, 100))
agent.center = (random.randint(1, 100), random.randint(1, 100))
occupied_ar = np.zeros([9])
agentLocationAR = np.zeros((numOfAgents,2))
for ac in patches_ac:
ac.center = (random.randint(1, 100), random.randint(1, 100))
return []
def animationManage(i):
global occupied_ar
global agentLocationAR
global victory
global agentID
global timeStep
global phaseCount
global maxFrame
timeStep = i
agentID = 1
followTarget(i, agent, enemy)
agentLocationAR[agentID-1][0], agentLocationAR[agentID-1][1] = agent.center
for ac in patches_ac:
agentID = agentID + 1
followTarget(i, ac, enemy)
agentLocationAR[agentID-1][0], agentLocationAR[agentID-1][1] = ac.center
goToExit(i, enemy, southExit)
# printing tests
if victoryCheck(enemy):
print 'Phase ', phaseCount
print 'Victory!'
phaseCount += 1
init()
elif enemyWonCheck(enemy):
print 'Phase ', phaseCount
print 'Failure!'
init()
elif i >= maxFrame - 1:
print 'Phase ', phaseCount
phaseCount += 1
return []
def goToExit(i, patch, exit_patch):
global agentLocationAR
global keep
global keepX
global keepY
x, y = patch.center
v_x, v_y = velocity_calc_exit(patch, exit_patch)
mid_x, mid_y, rad_x, rad_y = getMidDistance(patch, exit_patch)
rad_size = math.sqrt(rad_x**2 + rad_y**2)
v_ax, v_ay = attractionFieldExit(patch, x_se, y_se)
v_rx, v_ry = repulsiveFieldEnemy(patch, 5)
v_x = v_ax + v_rx
v_y = v_ay + v_ry
'''
if abs(v_rx) > 1:
v_x = v_x/abs(v_x/10)
if abs(v_ry) > 1:
v_y = v_x/abs(v_x/10)
'''
# Nomalize the magnitude
v_x = v_x*enemyTopSpeed*0.03
v_y = v_y*enemyTopSpeed*0.03
'''
if abs(v_x) > 1 or abs(v_y) > 1:
print '-------------'
print 'Att X: ', v_ax
print 'Att Y: ', v_ay
print 'Rep X: ', v_rx
print 'Rep Y: ', v_ry
print 'Total X: ', v_x
print 'Total Y: ', v_y
'''
# x position
x += v_x*enemyTopSpeed
# y position
y += v_y*enemyTopSpeed
x,y = borderCheck(x,y)
patch.center = (x, y)
return patch,
def dispersalCalc(user_patch):
global agentLocationAR # we need location of agents
for i in range(0,numOfAgents-1):
if(checkSemiRadius(user_patch, agentRadius)):
return True
return False
def attractionFieldExit(user_patch, attr_x, attr_y):
x,y = user_patch.center
netX = (x - attr_x)
netY = (y - attr_y)
# To prevent slow down when enemy is close to exit
if x - attr_x > 20 or y - attr_y > 20:
if x - attr_x > 20:
netX = (x - attr_x)
else:
if x - attr_x == 0:
netX = 0
else:
netX = 5*((x - attr_x)/abs((x - attr_x)))
if y - attr_y > 30:
netY = (y - attr_y)
else:
if y -attr_y == 0:
netY = 0
else:
netY = 50*((y - attr_y)/abs((y - attr_y)))
#print 'something y ', netY
return -netX, -netY
def repulsiveFieldEnemy(user_patch, repulseRadius):
# repulsive field that will be used by the enemy agent
global agentLocationAR
x,y = user_patch.center
totalRepX = 0
totalRepY = 0
scaleConstant = 1**38
for i in range(0, numOfAgents-1):
repX = 0
repY = 0
avoidX = agentLocationAR[i][0]
avoidY = agentLocationAR[i][1]
# To check if one of the agents to avoid are in range
#print getDistanceScalar(x, y, avoidX, avoidY)
if getDistanceScalar(x, y, avoidX, avoidY) <= repulseRadius:
#print 'Enemy agent detected'
netX = int(x - avoidX)
netY = int(y - avoidY)
# To deal with division by zero and normaize magnitude of repX and repY
if netX == 0:
netX = 0.2*((x - avoidX)/abs(x - avoidX))
if netY == 0:
netY = 0.2*((x - avoidX)/abs(x - avoidX))
repX = ((1/abs(netX)) - (1/repulseRadius))*(netX/(abs(netX)**3))
repY = ((1/abs(netY)) - (1/repulseRadius))*(netY/(abs(netY)**3))
totalRepX = totalRepX + repX
totalRepY = totalRepY + repY
totalRepX = totalRepX/scaleConstant
totalRepY = totalRepY/scaleConstant
return -totalRepX, -totalRepY
def followTarget(i, patch, enemy_patch):
x, y = patch.center
# Will try to follow enemy
#v_x, v_y = velocity_calc(patch, enemy_patch)
# Will follow midpoint of enemy & exit
v_x, v_y = velocity_calc_mid(patch, enemy_patch)
#print 'Here:'
#print interest_ar
# x position
x += v_x
# y position
y += v_y
patch.center = (x, y)
return patches_ac
def getInterestPoints(enemy_patch, exit_patch):
# Calculate interest points to attract agents
x, y = enemy_patch.center
# Calculate enemy-to-exit midpoint
mid_x, mid_y, rad_x, rad_y = getMidDistance(enemy_patch, exit_patch)
interest_ar = np.array([[x,y],[0,0],[0,0],[0,0],[0,0],[0,0],[0,0],[0,0],[0,0]])
#north
interest_ar[1][0] = x - rad_x
interest_ar[1][1] = y - rad_y
#east
interest_ar[3][0] = x - rad_y
interest_ar[3][1] = y + rad_x
#south (basically the midpoint)
interest_ar[5][0] = x + rad_x
interest_ar[5][1] = y + rad_y
#west
interest_ar[7][0] = x + rad_y
interest_ar[7][1] = y - rad_x
# northeast
interest_ar[2][0] = (interest_ar[1][0] + interest_ar[3][0])/2
interest_ar[2][1] = (interest_ar[1][1] + interest_ar[3][1])/2
#southeast
interest_ar[4][0] = (interest_ar[3][0] + interest_ar[5][0])/2
interest_ar[4][1] = (interest_ar[3][1] + interest_ar[5][1])/2
#southwest
interest_ar[6][0] = (interest_ar[5][0] + interest_ar[7][0])/2
interest_ar[6][1] = (interest_ar[5][1] + interest_ar[7][1])/2
interest_ar[8][0] = (interest_ar[7][0] + interest_ar[1][0])/2
interest_ar[8][1] = (interest_ar[7][1] + interest_ar[1][1])/2
# Setting up visuals
northpoint.center = (interest_ar[1][0], interest_ar[1][1])
eastpoint.center = (interest_ar[3][0], interest_ar[3][1])
midpoint.center = (interest_ar[5][0], interest_ar[5][1])
westpoint.center = (interest_ar[7][0], interest_ar[7][1])
mideastpoint.center = (interest_ar[2][0], interest_ar[2][1])
midwestpoint.center = (interest_ar[4][0], interest_ar[4][1])
northeastpoint.center = (interest_ar[6][0], interest_ar[6][1])
northwestpoint.center = (interest_ar[8][0], interest_ar[8][1])
return interest_ar
def findClosestInterest(agent_patch, in_ar):
# For some reason, north never gets occupied
# north east is (north/2) + (south/2)
global occupied_ar
global victory
global agentID
global timeStep
global huntEnemy
victory = False
index = -1
smallDis = 999999
tempAr = np.zeros([9])
if huntEnemy:
minDis = 0
else:
minDis = 1
# To check agent's distance of all interest points
for i in range(minDis,9):
dis = abs(int(getDistance(agent_patch, in_ar, i)))
# Add heavy weights to charge at enemy
if chargeEnemy:
if i == 0:
dis = dis*0.5
if occupied_ar[i] != 0:
# we must write a condition so that agent knows it is the
# one that is occupying it
dis = dis*5
# Add heavy weights to avoid the back
if i == 1 or i == 8 or i == 2:
if i == 1:
dis = dis*3
elif i == 2 or i == 8:
dis = dis*4
tempAr[i] = dis
# When we discover unoccupied shorter distance, replace index
if dis < smallDis:
# index is agent_patch.center[0] < 47 and agent_patch.center[0] > 53the index of interest_array of the closest interest point
smallDis = dis
index = i
# If the smallest distance is less than 10, we are currently engaged
if smallDis < 0.5:
# We are near or at the targeted interest point,
# now we should update array as occupied
occupied_ar[index] = agentID
if occupied_ar[0] != 0:
victory = True
#print 'engaged index ', index
else:
# Else we are still far away from the index
if occupied_ar[index] == agentID:
occupied_ar[index] = 0
#print 'lost track of index ', index
#else:
#print 'far away from index ', index
return index
def getBypassInterestPoints(user_patch,avoidX, avoidY, exit_x, exit_y):
# Mainly used by the enemy agent
# User agent will find a point around the blocking agent that is closest to
# the exit.
x,y = user_patch.center
rad_range = 20
tempX = x - avoidX
tempY = y - avoidY
diffR = math.sqrt(tempX**2 + tempY**2)
# Calculating our target x and y length
radX = (rad_range*tempX)/diffR
radY = (rad_range*tempY)/diffR
# Now we calculate the main interest points
# Since we are calculating perpendicular points, we reverse the X and Y
# in the pt calculation process
pt1X = avoidX + radY
pt1Y = avoidY - radX
###
pt2X = avoidX - radY
pt2Y = avoidY + radX
# Then we must determine which interest point is closer to the exit
pt1Dis = int(getDistanceScalar(pt1X, pt1Y,exit_x, exit_y))
pt2Dis = int(getDistanceScalar(pt2X, pt2Y,exit_x, exit_y))
# If point 1 is closer to the exit than point 2
if(int(pt1Dis) <= int(pt2Dis)):
print int(pt1X)
return pt1X, pt1Y
print int(pt2X)
return int(pt2X), int(pt2Y)
def getDistanceScalar(x1, y1, x2, y2):
return math.sqrt((x2 - x1)**2 + (y2 - y1)**2)
def getDistance(agent_patch, in_ar, index):
x_a, y_a = agent_patch.center
x_t = in_ar[index][0]
y_t = in_ar[index][1]
# get distance between two particles
ans = math.sqrt((x_t - x_a)**2 + (y_t - y_a)**2)
if math.isnan(ans):
print 'x_a: ',x_a
print 'y_a: ',y_a
print 'x_t: ',x_t
print 'y_t: ',y_t
init()
return math.sqrt((x_t - x_a)**2 + (y_t - y_a)**2)
def getMidDistance(enemy_patch, exit_patch):
# Get midpoint between enemy agent and exit
x, y = enemy_patch.center
x_e = x_se
y_e = y_se
# Get midpoint values
mid_x = (x + x_e)/2
mid_y = (y + y_e)/2
# Get radius values
rad_x = mid_x - x
rad_y = mid_y - y
# Returns (midpoint x and y) values and (radius x and y) values
return mid_x, mid_y, rad_x, rad_y
def top_speed_regulate(curr_speed, top_speed):
if curr_speed > top_speed:
return top_speed
elif curr_speed < -top_speed:
return -top_speed
else:
return curr_speed
def velocityCalcScalar(x1, y1, x2, y2):
veloX = top_speed_regulate( (x2 - x1) ,enemyTopSpeed)
veloY = top_speed_regulate( (y2 - y1) ,enemyTopSpeed)
return veloX, veloY
# Calculate velocity to rush to exit
def velocity_calc_exit(agent_patch, exit_patch):
x, y = agent_patch.center
#x_e, y_e = exit_patch.center
x_e = x_se
y_e = y_se
velo_vect = np.array([0.0, 0.0], dtype='f')
dis_limit_thresh = 1
velo_vect[0] = top_speed_regulate( (x_e - x)* dis_limit_thresh ,enemyTopSpeed)
velo_vect[1] = top_speed_regulate( (y_e - y)* dis_limit_thresh ,enemyTopSpeed)
return velo_vect[0], velo_vect[1]
# Calculate velocity to chase down enemy
def velocity_calc(agent_patch, enemy_patch):
x, y = agent_patch.center
x_e, y_e = enemy_patch.center
velo_vect = np.array([0.0, 0.0], dtype='f')
dis_limit_thresh = 1
velo_vect[0] = top_speed_regulate( (x_e - x)* dis_limit_thresh ,topSpeed)
velo_vect[1] = top_speed_regulate( (y_e - y)* dis_limit_thresh ,topSpeed)
return velo_vect[0], velo_vect[1]
# Calculate velocity to arrive at midpoint between enemy and exit
def velocity_calc_mid(agent_patch, enemy_patch):
x, y = agent_patch.center
x_e, y_e, _, _ = getMidDistance(enemy_patch, southExit)
# We get location of interest points as well as animate the interest points
interest_ar = getInterestPoints(enemy_patch, southExit)
interest_index = findClosestInterest(agent_patch, interest_ar)
x_e = interest_ar[interest_index][0]
y_e = interest_ar[interest_index][1]
velo_vect = np.array([0.0, 0.0], dtype='f')
dis_limit_thresh = 1
topSpeed = 0.3
velo_vect[0] = top_speed_regulate( (x_e - x)* dis_limit_thresh , topSpeed)
velo_vect[1] = top_speed_regulate( (y_e - y)* dis_limit_thresh , topSpeed)
'''
if dispersalCalc(agent_patch):
velo_vect[0] = 0
velo_vect[1] = 0
'''
return velo_vect[0], velo_vect[1]
def checkRadius(user_patch, r):
global agentLocationAR
r = 1
for i in range(0,numOfAgents-1):
x = int(agentLocationAR[i][0])
y = int(agentLocationAR[i][1])
if(inRadius(user_patch, x, y, r)):
# if an agent is in the user's radius
#print 'Nearby agent detected'
return True
return False
def checkSemiRadius(user_patch, r):
global agentLocationAR
r = 0.001
for i in range(0,numOfAgents-1):
x = int(agentLocationAR[i][0])
y = int(agentLocationAR[i][1])
if(inSemiRadius(user_patch, x, y, r)):
# if an agent is in the user's radius
#print 'Nearby agent detected'
return True
return False
def inRadius(self_patch, pointX, pointY, r):
# Helps determine if there is something near the using agent
x, y = self_patch.center # agent emitting the radius
# agent we are trying to avoid
h = pointX
k = pointY
# Equation of circle
# (x-h)^2 + (y-k)^2 <= r^2
tempX = (x - h)**2
tempY = (y - k)**2
r_2 = r**2
if tempX + tempY <= r_2:
# It is within the radius
return True
else:
return False
def inSemiRadius(self_patch, pointX, pointY, r):
# Helps determine if there is something near the using agent
h, k = self_patch.center # agent emitting the radius
# agent we are trying to avoid
x = pointX
y = pointY
# Equation of semicircle
tempTerm = r**2 - (x-h)**2
if tempTerm < 0:
# if this term is negative, that means agent to avoid is out of range
return False
tempEq = k - math.sqrt(tempTerm)
if y <= tempEq:
# It is within the radius
return True
else:
return False
def animateCos(i, patch):
x, y = patch.center
x += 0.1
y = 50 + 30 * np.cos(np.radians(i))
patch.center = (x, y)
return patch,
anim = animation.FuncAnimation(fig, animationManage,
init_func=init,
frames=maxFrame,
interval=1,
blit=True,
repeat=True)
plt.show()
I would like to make random mouse movements in specified rectangle area (limited with coordinates x1, y1, x2, y2, x3, y3, x4, y4).
Movements should be smooth, random, not just straight lines, go randomly up/down/left/right/etc for specified time duration.
Could you give me a hand or working example I can learn from?
many thanks
This code works on Windows only. You can experiment with the parameters inside the random_movement function to get better results. Good luck!
import ctypes
import random
import time
import math
def move_mouse(pos):
x_pos, y_pos = pos
screen_size = ctypes.windll.user32.GetSystemMetrics(0), ctypes.windll.user32.GetSystemMetrics(1)
x = 65536L * x_pos / screen_size[0] + 1
y = 65536L * y_pos / screen_size[1] + 1
return ctypes.windll.user32.mouse_event(32769, x, y, 0, 0)
def random_movement(top_left_corner, bottom_right_corner, min_speed=100, max_speed=200):
'''speed is in pixels per second'''
x_bound = top_left_corner[0], bottom_right_corner[0]
y_bound = top_left_corner[1], bottom_right_corner[1]
pos = (random.randrange(*x_bound),
random.randrange(*y_bound))
speed = min_speed + random.random()*(max_speed-min_speed)
direction = 2*math.pi*random.random()
def get_new_val(min_val, max_val, val, delta=0.01):
new_val = val + random.randrange(-1,2)*(max_val-min_val)*delta
if new_val<min_val or new_val>max_val:
return get_new_val(min_val, max_val, val, delta)
return new_val
steps_per_second = 35.0
while True:
move_mouse(pos)
time.sleep(1.0/steps_per_second)
speed = get_new_val(min_speed, max_speed, speed)
direction+=random.randrange(-1,2)*math.pi/5.0*random.random()
new_pos = (int(round(pos[0]+speed*math.cos(direction)/steps_per_second)),
int(round(pos[1]+speed*math.sin(direction)/steps_per_second)))
while new_pos[0] not in xrange(*x_bound) or new_pos[1] not in xrange(*y_bound):
direction = 2*math.pi*random.random()
new_pos = (int(round(pos[0]+speed*math.cos(direction)/steps_per_second)),
int(round(pos[1]+speed*math.sin(direction)/steps_per_second)))
pos=new_pos
Example:
random_movement((300,300),(600,600))
For random smooth movements constrained to a rectangle I'd try to use Lissajous curves with randomly changing coefficients.
Here is a demo of random X,Y positions you can play as your requirements:
from time import sleep
import pyautogui
import numpy as np
# Check your screen size
print(pyautogui.size())
count=0
while count<1000:
x=np.random.randint(1,1792)
y=np.random.randint(1,1120)
pyautogui.moveTo(x, y)
print(x)
print(y)
sleep(20)
count+=1
Note: install first
pip3 install pyautogui
I made this based on Piotr Dabkowski's code, with some extra features (taking random breaks, random scrolls, and users can end early by right clicking). This works for Python 3, and again, for Windows only.
import ctypes
import random
import time
import math
import win32gui
xmax = ctypes.windll.user32.GetSystemMetrics(0)
ymax = ctypes.windll.user32.GetSystemMetrics(1)
def get_position():
_, _, (x,y) = win32gui.GetCursorInfo()
return (x,y)
def move_mouse(pos):
x_pos, y_pos = pos
x = int(65536 * x_pos / xmax + 1)
y = int(65536 * y_pos / ymax + 1)
return ctypes.windll.user32.mouse_event(32769, x, y, 0, 0)
def start(t=30, min_speed=10, max_speed=500, x_bound=[0,xmax], y_bound=[0,ymax],
p_break = 0.005, break_range = (10, 60), p_scroll = 0.01, scroll_range = (100, 1000)):
def get_new_speed(min_val, max_val, val, delta=0.01):
new_val = val + random.randrange(-1,2)*(max_val-min_val)*delta
if new_val<min_val or new_val>max_val:
return get_new_speed(min_val, max_val, val, delta)
return new_val
steps_per_second = 35.0
print('Started.')
endtime = time.time() + int(t*60)
# Initialize position, speed and direction
pos = get_position()
speed = min_speed + random.random()*(max_speed-min_speed)
direction = 2*math.pi*random.random()
inside_boundary = False
right_clicked = False
# Keep moving mouse until end time, or until right click
while (not right_clicked) and (time.time() < endtime):
if ctypes.windll.user32.GetKeyState(0x02) not in [0,1]:
right_clicked = True
time.sleep(1.0/steps_per_second)
# Taking a break of random duration
duration = random.randint(*break_range) # in unit of seconds
break_endtime = time.time() + duration
r = random.random()
if (1-p_break) <= r < 1:
# Keep checking for right click to exit loop
while (not right_clicked) and (time.time() < break_endtime):
if ctypes.windll.user32.GetKeyState(0x02) not in [0,1]:
right_clicked = True
time.sleep(1.0/steps_per_second)
time_left = break_endtime - time.time()
print('Paused %d / %ds' % (time_left,duration) + ' '*50, end='\r')
pos = get_position()
print(' '*50, end='\r')
# Random scroll
r = random.random()
lines = random.randint(*scroll_range)
sign = random.random()
sign = -1 if sign < 0.5 else 1
if (1-p_scroll) <= r < 1:
time.sleep(random.random())
ctypes.windll.user32.mouse_event(2048, 0, 0, sign*lines, 0)
time.sleep(random.random())
pos = get_position()
# Random move
move_mouse(pos)
time_left = endtime - time.time()
print('Running (time left: %ds)' % time_left + ' '*50, end='\r')
if (pos[0] in range(*x_bound)) and (pos[1] in range(*y_bound)):
inside_boundary = True
# Update position, speed and direction
speed = get_new_speed(min_speed, max_speed, speed)
direction+=random.randrange(-1,2)*math.pi/5.0*random.random()
new_pos = (int(round(pos[0]+speed*math.cos(direction)/steps_per_second)),
int(round(pos[1]+speed*math.sin(direction)/steps_per_second)))
# Once mouse position is inside boundary, new position must also be inside
if inside_boundary:
while new_pos[0] not in range(*x_bound) or new_pos[1] not in range(*y_bound):
direction = 2*math.pi*random.random()
new_pos = (int(round(pos[0]+speed*math.cos(direction)/steps_per_second)),
int(round(pos[1]+speed*math.sin(direction)/steps_per_second)))
pos=new_pos
print('Stopped.' + ' ' * 50)
For performing the movements there is a third-party package call PyUserInput that will allow you to control mouse or keyboard, and it is cross-platform. Install it using pip:
$ pip install PyUserInput
For doing smooth movements you can try what 9000 proposes in his answer.
I'm looking at creating map tiles based on a 3D model made in blender,
The map is 16 x 16 in blender.
I've got 4 different zoom levels and each tile is 100 x 100 pixels. The entire map at the most zoomed out level is 4 x 4 tiles constructing an image of 400 x 400.
The most zoomed in level is 256 x 256 obviously constructing an image of 25600 x 25600
What I need is a script for blender that can create the tiles from the model.
I've never written in python before so I've been trying to adapt a couple of the scripts which are already there.
So far I've come up with a script, but it doesn't work very well. I'm having real difficulties getting the tiles to line up seamlessly. I'm not too concerned about changing the height of the camera as I can always create the same zoomed out tiles at 6400 x 6400 images and split the resulting images into the correct tiles.
Here is what I've got so far...
#!BPY
"""
Name: 'Export Map Tiles'
Blender: '242'
Group: 'Export'
Tip: 'Export to Map'
"""
import Blender
from Blender import Scene,sys
from Blender.Scene import Render
def init():
thumbsize = 200
CameraHeight = 4.4
YStart = -8
YMove = 4
XStart = -8
XMove = 4
ZoomLevel = 1
Path = "/Images/Map/"
Blender.drawmap = [thumbsize,CameraHeight,YStart,YMove,XStart,XMove,ZoomLevel,Path]
def show_prefs():
buttonthumbsize = Blender.Draw.Create(Blender.drawmap[0]);
buttonCameraHeight = Blender.Draw.Create(Blender.drawmap[1])
buttonYStart = Blender.Draw.Create(Blender.drawmap[2])
buttonYMove = Blender.Draw.Create(Blender.drawmap[3])
buttonXStart = Blender.Draw.Create(Blender.drawmap[4])
buttonXMove = Blender.Draw.Create(Blender.drawmap[5])
buttonZoomLevel = Blender.Draw.Create(Blender.drawmap[6])
buttonPath = Blender.Draw.Create(Blender.drawmap[7])
block = []
block.append(("Image Size", buttonthumbsize, 0, 500))
block.append(("Camera Height", buttonCameraHeight, -0, 10))
block.append(("Y Start", buttonYStart, -10, 10))
block.append(("Y Move", buttonYMove, 0, 5))
block.append(("X Start", buttonXStart,-10, 10))
block.append(("X Move", buttonXMove, 0, 5))
block.append(("Zoom Level", buttonZoomLevel, 1, 10))
block.append(("Export Path", buttonPath,0,200,"The Path to save the tiles"))
retval = Blender.Draw.PupBlock("Draw Map: Preferences" , block)
if retval:
Blender.drawmap[0] = buttonthumbsize.val
Blender.drawmap[1] = buttonCameraHeight.val
Blender.drawmap[2] = buttonYStart.val
Blender.drawmap[3] = buttonYMove.val
Blender.drawmap[4] = buttonXStart.val
Blender.drawmap[5] = buttonXMove.val
Blender.drawmap[6] = buttonZoomLevel.val
Blender.drawmap[7] = buttonPath.val
Export()
def Export():
scn = Scene.GetCurrent()
context = scn.getRenderingContext()
def cutStr(str): #cut off path leaving name
c = str.find("\\")
while c != -1:
c = c + 1
str = str[c:]
c = str.find("\\")
str = str[:-6]
return str
#variables from gui:
thumbsize,CameraHeight,YStart,YMove,XStart,XMove,ZoomLevel,Path = Blender.drawmap
XMove = XMove / ZoomLevel
YMove = YMove / ZoomLevel
Camera = Scene.GetCurrent().getCurrentCamera()
Camera.LocZ = CameraHeight / ZoomLevel
YStart = YStart + (YMove / 2)
XStart = XStart + (XMove / 2)
#Point it straight down
Camera.RotX = 0
Camera.RotY = 0
Camera.RotZ = 0
TileCount = 4**ZoomLevel
#Because the first thing we do is move the camera, start it off the map
Camera.LocY = YStart - YMove
for i in range(0,TileCount):
Camera.LocY = Camera.LocY + YMove
Camera.LocX = XStart - XMove
for j in range(0,TileCount):
Camera.LocX = Camera.LocX + XMove
Render.EnableDispWin()
context.extensions = True
context.renderPath = Path
#setting thumbsize
context.imageSizeX(thumbsize)
context.imageSizeY(thumbsize)
#could be put into a gui.
context.imageType = Render.PNG
context.enableOversampling(0)
#render
context.render()
#save image
ZasString = '%s' %(int(ZoomLevel))
XasString = '%s' %(int(j+1))
YasString = '%s' %(int((3-i)+1))
context.saveRenderedImage("Z" + ZasString + "X" + XasString + "Y" + YasString)
#close the windows
Render.CloseRenderWindow()
try:
type(Blender.drawmap)
except:
#print 'initialize extern variables'
init()
show_prefs()
This was relatively simple in the end.
I scaled up the model so that 1 tile on the map was 1 grid in blender.
Set the camera to be orthographic.
Set the scale on the camera to 1 for the highest zoom, 4 for the next one, 16 for the next one and so on.
Updated the start coordinates and move values accordingly.