Skip to content

Instantly share code, notes, and snippets.

@SaulG
Created May 24, 2013 17:02
from random import randint, random
from threading import Thread
from time import sleep
from sys import argv
from math import cos, sin, fabs
import pygame
#Metodo que retorna un color en RGB dado un numero
def asignColor(grupo):
return ((grupo * 5 + 7) % 256, (grupo * 13 + 41) % 256, (grupo * 29 + 13) % 256)
#Metodo que nos regresa un color verde en RGB
def verde():
return (0,255,0)
#Metodo que nos regresa un color rojo en RGB
def rojo():
return (255,0,0)
#Metodo que nos regresa un color amarillo en RGB
def amarillo():
return (255,255,0)
#clase del enemigo
class Enemigo:
#En el constructor tomamos como parametro
# coordenadas (x, y), el color, el radio, una id que se genera de manera incremental y una vida
def __init__(self, ( x,y, z), color, radio, id, vida):
self.x = x
self.y = y
self.z = z
self.color = color
self.radio = radio
self.id = id
self.vida = vida
self.visible = True #Nos sirve para determinar si el nodo esta por ser removido
return
#Nos sirve para desplegar el enemigo en el canvas
def display(self):
#Dibuja el enemigo
pygame.draw.circle(WIN, self.color, (self.x, self.y), self.radio, 1)
#Dibuja un estatus del enemigo
WIN.blit( pygame.font.SysFont("Arial",10 ).render("ENEMIGO %s A: %s VIDA %s"%(self.id, self.z, self.vida),True,(0, 0, 0), (255, 255, 255) ), (self.x, self.y))
#Barra de vida
pygame.draw.rect( WIN, (0, 0, 0), ( (self.x, self.y+10), (self.radio *2, self.radio * 0.5) ) )
pygame.draw.rect( WIN, obtenerColorVida(self.vida), ( (self.x, self.y+10), ( ( (self.radio * 2 ) * ( ( self.vida ) * 1.0 / 100) ) , ( self.radio * 0.5 ) ) ) )
return
#clase del nodo
class Nodo:
#En el constructor tomamos como parametro
# coordenadas (x, y), el color, el radio, una id que se genera de manera incremental y una vida
def __init__(self, (x, y, z), color, radio, id, vida):
self.x = x
self.y = y
self.z = z
self.color = color
self.radio = radio
self.id = id
self.vida = vida
self.mensaje = ''
self.estado = verde()
self.visible = True #Nos sirve para determinar si el nodo esta por ser removido
return
#Metodo que dado una lista de nodos verifica que se encuentren
#dentro del rango de transmision en caso de ser asi les pasa el mensaje
#y se le resta el costo de energia segun su tamanio y radio
def transmite(self, nodos):
for nodo in nodos:
if radioDeTransmision(self.radio, self.x, self.y, self.z, (nodo.x, nodo.y, nodo.z) ):
nodo.mensaje = self.mensaje
nodo.estado = nodo.cambiaAmarillo()
self.vida -= obtenerCostoEnergia(self.radio, self.mensaje)
#En caso quese obtenga vida de menos se le asigna un 0 para evitar confusiones
if self.vida < 0:
self.vida = 0
return nodos
#Nos sirve para desplegar el nodo en el canvas
def display(self):
#Se dibuja el nodo (circulo) dado su radio y color
pygame.draw.circle(WIN, self.color, (self.x, self.y), self.radio, 1)
#Hardcoded Tuve unos problemas con la asignacion de color en lugar del color RGB deberian ir self.estado
if self.mensaje != '':
pygame.draw.circle(WIN, (255,0,0), (self.x, self.y), 5, 0)
else:
pygame.draw.circle(WIN, (0,255,0), (self.x, self.y), 5, 0)
#Se pinta el estatus del nodo
WIN.blit( pygame.font.SysFont("Arial",10 ).render("ID %s A %s VIDA %s MSG %s "%(self.id, self.z, self.vida, self.mensaje),True,(0, 0, 0), (255, 255, 255) ), (self.x, self.y))
#Barra de vida del nodo
pygame.draw.rect( WIN, (0, 0, 0), ( (self.x, self.y+10), (self.radio*0.5, self.radio * 0.1) ) )
pygame.draw.rect( WIN, obtenerColorVida(self.vida), ( (self.x, self.y+10), ( ( (self.radio * 0.5 ) * ( ( self.vida ) * 1.0 / 100) ) , ( self.radio * 0.1 ) ) ) )
return
#Metodo que regresa el estado del nodo
def getEstado(self):
return self.estado
#Metodo que cambia de color el estado por rojo
def cambiaRojo(self):
self.estado = (255,0,0)#rojo()
return
#Metodo que cambia de color el estado a amarillo
def cambiaAmarillo(self):
self.estado = amarillo()
return
#Metodo que cambia de color el estado a verdde
def cambiaVerde(self):
self.estado = verde()
return
#Dada una coordenada se verifica que esten dentro de un radio
# y ademas de que se encuentre con una diferencia de altitud(z) dentro
#del porcentaj establecido regresa un True en otro caso sera un False
def radioDeTransmision(radio, xc, yc, zc, coordenada):
global porcentaje
x, y, z = coordenada
if ( ( ( x - xc ) ** 2 ) + ( ( y - yc ) ** 2 ) ) < ( radio ** 2 ) and (fabs(zc - z) < ( zc * porcentaje)):
return True
return False
#Segun la cantidad de vida dado nos regresara
#un color determinado en RGB
def obtenerColorVida(vida):
if vida >= 66:
color = ( 0, 255, 0 )
elif vida < 66 and vida > 33:
color = ( 255, 245, 0 )
else:
color = ( 255, 0, 0 )
return color
#Tomando el radio y el largo del mensaje se obtendra
#el costo de transmision
def obtenerCostoEnergia(radio, mensaje):
return ( len(mensaje) * ( radio / 100 ) )
#clase de Simulacion que hereda de la clase Thread
class Simulacion(Thread):
def __init__(self):
Thread.__init__(self)
self.nodos = list()
self.enemigos = list()
self.contador_enemigos = 0
self.contador_nodos = 0
self.altitudes = {}
return
def run(self):
#Toma el canvas (WIN), tiempo de retraso, el color de FONDO y la propabilodad de que a paresca un nodo
global WIN, tiempo, FONDO, p, pe
run = True
self.creaGrid()
#Se crea un nodo
self.creaNodo()
#Se despliega el nodo
self.nodos[0].display()
#Se actualiza el canvas
pygame.display.update()
#Se coloca un tiempo de retraso configurado
sleep(tiempo)
#Se crea una lista para enemigos por eliminar del canvas
enemigosEliminar = list()
#Se crea una lista para nodos por eliminar del canvas
nodosEliminar = list()
#Mientras run siga siendo True corre
while run:
#Itera cada evento seleccionado
for event in pygame.event.get():
#En caso de usar QUIT cambiamos run a False
if event.type == pygame.QUIT:
run = False
#Limpieza del canvas
WIN.fill(FONDO)
self.creaGrid()
#Se iteran los enemigos
for e in xrange(len(self.enemigos)):
#En caso de que el enemigo no sea visible
#brinca el enemigo
if not self.enemigos[e].visible:
continue
#Se iteran los nodos
for n in xrange(len(self.nodos)):
#En caso de que los nodos no sea visible
#brinca el nodo
if not self.nodos[n].visible:
continue
#En caso de que el enemigo se encuentre en el radio del nodo se coloca
# como mensaje al nodo en el que se encuentra el enemigo
if radioDeTransmision(self.nodos[n].radio, \
self.nodos[n].x, \
self.nodos[n].y, \
self.nodos[n].z,
(self.enemigos[e].x, self.enemigos[e].y, self.enemigos[e].z)):
# Se cambio de estado a rojo
self.nodos[n].cambiaRojo()
#DEBUG
print self.nodos[n].estado
#Cambia mensaje
self.nodos[n].mensaje = 'Enemigo en zona de %s '%(self.nodos[n].id)
#Mientras el random nos de un numero menor a la probabilidad de nodo
#este generara un nuevo nodo
if random() < p:
self.creaNodo()
#Mientras el random nos de un numero menor a la probabilidad de enemigo
#este generara un nuevo enemigo
if random() < pe:
self.creaEnemigo()
#Por cada enemigo se le quita cierta vida
#en caso que tenga vida menor a 0 se le coloca
# en su propiedad de que ya no sera visible
#despues se pintan los enemigos visibles
for e in xrange(len(self.enemigos)):
if self.enemigos[e].vida > 5:
self.enemigos[e].vida -= 5
else:
enemigosEliminar.append(self.enemigos[e])
self.enemigos[e].visible = False
if not self.enemigos[e].visible:
continue
self.enemigos[e].display()
#Se iteran todos los nodos se le quita cierta vida
#en caso que tenga vida menor a 0 se le coloca
#en su propiedad de que ya no sera visible
#despues se pintan los nodos visibles
for n in xrange(len(self.nodos)):
print self.nodos[n].id, self.nodos[n].vida
if self.nodos[n].vida > 0:
self.nodos[n].vida -= 5
if self.nodos[n].mensaje != '':
self.nodos[n].transmite(self.nodos)
else:
nodosEliminar.append(self.nodos[n])
self.nodos[n].visible = False
if not self.nodos[n].visible:
continue
self.nodos[n].display()
#Se actualiza el canvas
pygame.display.update()
#Se crea un retraso
sleep(tiempo)
#Se remueven los enemigos en la lista de enemigosEliminar
for e in enemigosEliminar:
try:
self.enemigos.remove(e)
except:
pass
#Se remueven los nodos en la lista de nodosEliminar
for n in nodosEliminar:
try:
self.nodos.remove(n)
except:
pass
return
#Pinta los nodos que se han comunicado
def pintaRedComunicacion(self, comunicacion):
global WIN
if len(comunicacion) >= 3:
print comunicacion
for i in xrange(len(comunicacion)):
if len(comunicacion) != i+1:
x1, y1 = comunicacion[i]
x2, y2 = comunicacion[i+1]
pygame.draw.line(WIN , (255, 0, 0), (x1, y1), (x2, y2), 1 )
return
#Se crea un nodo enemigo
def creaEnemigo(self):
#Se toma la configuracion de su radio (re), vida (vidaEnemigo), porcentaje (margen)
global re, vidaEnemigo, porcentaje
#Contador de los enemigos creados
self.contador_enemigos += 1
#Se le da una posicion al enemigo de manera aleatoria con un color rojo en RGB, una id con numero de enemigos y una vida propia
enemigo = Enemigo( ( randint( DIM * 0.10 , DIM * porcentaje ), randint( DIM * 0.10, DIM * porcentaje ), randint(0, altitude ) ), (255, 0, 0), re, self.contador_enemigos, vidaEnemigo)
#Se agrega a la lista de enemigos los enemigos
self.enemigos.append( enemigo )
return
def creaNodo(self):
#Se toma la configuracion de su radio (re), vida (vidaEnemigo), porcentaje (margen)
global r, vidaNodo, porcentaje, altitude
#Contador de los nodos creados
self.contador_nodos+=1
#Se le da una posicion al nodo de manera aleatoria con un color en RGB obtenido a partir del contador de nodos , una id osea el numero de nodos y una vida propia
nodo = Nodo( ( randint( DIM * 0.10 , DIM * porcentaje ), randint( DIM * 0.10, DIM * porcentaje ), randint(0, altitude ) ), asignColor( self.contador_nodos ), r, self.contador_nodos , vidaNodo)
#Se agrega el nodo a la lista de nodos
self.nodos.append( nodo )
return
#Metodo que crea una red de cuadro en el que cada cuadro tiene una altitud establecida
def creaGrid(self):
#Se toman las variables de ventana, dimensiones, pedasos en que se partira la ventana y la altitude maxima
global WIN, DIM, CHUNKS, altitude
#Se obtienen las partes de la ventana
CHUNK = DIM/CHUNKS
print len(self.altitudes)
#En caso de ser la primera vez en dibujar la matriz se guardan en un dictionary las altitudes
# que se guardaran de manera aleatoria
if len(self.altitudes) == 0:
for y in xrange(CHUNKS):
for x in xrange(CHUNKS):
print ( (x * CHUNK, y), (x * CHUNK, y * CHUNK) )
self.altitudes[( (x * CHUNK, y), (CHUNK, CHUNK) )] = ((randint(0, altitude)),( ( (x * CHUNK, y * CHUNK), (CHUNK * y, (x+1) * CHUNK) ) ))
#for c in xrange(CHUNKS):
# pygame.draw.line(WIN, (255, 0, 0), (CHUNK * c, 0), (CHUNK * c, CHUNK * CHUNKS))
# pygame.draw.line(WIN, (255, 0, 0), (0, CHUNK * c), (CHUNK * CHUNKS, CHUNK * c))
altiud, tam, aux, c = None, None, None, None
#Aqui se colocan los colores de los cuadros
for y in xrange(CHUNKS):
for x in xrange(CHUNKS):
altitud, tam = self.altitudes[( (x * CHUNK, y), (CHUNK,CHUNK) )]
print 'Creando rectangulos: ',altitud, tam
pygame.draw.rect(WIN, asignColor(altitud), tam, 100)
#Aqui se colocan los textos, se colocaron de esta manera porque si los iteraba en el
#for se iban a empalmar
for y in xrange(CHUNKS):
for x in xrange(CHUNKS):
altitud, tam = self.altitudes[( (x * CHUNK, y), (CHUNK,CHUNK) )]
c, aux = tam
cx, cy = c
cx = cx+CHUNKS/2.0
cy = cy+CHUNKS/2.0
# c = cx +10, cy +10
WIN.blit( pygame.font.SysFont("Arial",10 ).render("%s"%(altitud), True, (0, 0, 0), (255, 255, 255) ), (cx, cy) )
return
#Dimensiones del canvas
DIM = 1000
#porcentaje del canvas
porcentaje = 0.6
#color de fondo(blanco)
FONDO = ( 255, 255, 255)
#inicia pygame
pygame.init()
#se crea el canvas
WIN = pygame.display.set_mode((DIM, DIM))
#Se coloca un titulo al canvas
pygame.display.set_caption('Simulacion de redes sensoras')
#Se rellena de un color al canvas
WIN.fill(FONDO)
#Parametro de tiempo
try:
tiempo = float(argv[1])
except:
tiempo = 3
#Parametro de probabilidad de nodo
try:
p = float(argv[2])
except:
p = 0.6
#Parametro de radio del nodo
try:
r = float(argv[3])
except:
r = 200
#Parametro de probabilidad de enemigo
try:
pe = float(argv[4])
except:
pe = 0.4
#Parametro de radio de enemigo
try:
re = float(argv[5])
except:
re = 10
#Parametro de vida del nodo
try:
vidaNodo = int(argv[6])
except:
vidaNodo = 100
#Parametro de vida del enemigo
try:
vidaEnemigo = int(argv[7])
except:
vidaEnemigo = 20
#Parametro de velocidad
try:
velocidad = int(argv[8])
except:
velocidad = 10
#Parametro de pedasos a partir la ventana
try:
CHUNKS = int(argv[9])
except:
CHUNKS = 20
#Parametro para la altitude maxima
try:
altitude = int(argv[10])
except:
altitude = 200
def main():
#Crea una simulacion
s = Simulacion()
#corre simulacion
s.run()
main()
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment