jueves, 15 de octubre de 2015

Programacion para la Integracion de sistemas

 Autor : René Curín
Competencia : Trabajo autónomo
Asignatura: Programacion para la Integracion de sistemas
Palabras claves: Python, Pygame, Simulación

¿Se han preguntado como funcionan los mapas en los videojuegos 2D?. La verdad no es tan fácil como parece, pero no hay que preocuparse, porque aprender en un lenguaje como python, simple y potente, siempre es divertido.

Descripción de la actividad 
El proyecto que se realizo en esta actividad consistio en la creacion y simulacion de un videojuego, la idea principal es que los movimientos de los personajes sea de ,anera autonoma, es decir, que se mueven de manera aleatoria por todo el mapa, y ademas crear una interfaz que muestre la sonde (personaje) en todo momento.


Enunciado de la actividad:
En este proyecto usted debera programar y simular un sistema de monitoreo y control de sondas robot que se mueven en un planeta desconocido. Existen 4 sondas, las cuales navegan de manera automatica por un mapa 2D. Para el manejo de sondas se propone la siguiente estructura de datos: nld: id de la sonda, nX, nY: Coordenadas de la sonda de el mapa 2D, Cxd, Cyd: Direccion ortogonal (-1,0,+1), nVelo: Velocidad de la sonda [1,2,3], nRango: Numero de pasos a mover, aSensor: Vector de 5 elementos de tipo entero [O,C,N,H], nFig: Sprote animado, nTime y nTime2: Contadores, IFlag1 y IFlag2: Banderas logicas.

Desarrollo de la actividad:
  Estrategia de trabajo; Pensar y encontrar los elementos que necesitariamos para poder emplear el proyecto, tales como posibles funciones, clases, imagenes, movimientos, dimenciones de pantalla etc
  Modelo de solucion; Comenzamos por separar todo los objetos en clases independientes, tales como el personaje, el mapa, las superficies de vista, las baterias, y luego crear un objeto de todo lo que se necesitara.
. 
Codigo Fuente
 import pygame, sys, ctypes, random
from pygame.locals import *

ANCHO = 640
LARGO = 480

Mapa = (2560, 1440)

Panel = (96, 96)

def fuentes(text,size):
    fuente = pygame.font.Font(None, size)
    texto1 = fuente.render(text, 0, (255, 255, 255))
    return texto1

def Load_Image(sFile, transp = False):
    try: image = pygame.image.load(sFile)
    except pygame.error, message:
        raise SystemExit, message
    image = image.convert()
    if transp:
       color = image.get_at((0, 0))
       image.set_colorkey(color, RLEACCEL)
    return image

class eSonda(ctypes.Structure):
    __fields__ = [
                  ("nId", ctypes.c_int), ("nX", ctypes.c_int), ("nY", ctypes.c_int), ("Cxd", ctypes.c_int),
                  ("Cyd", ctypes.c_int), ("nVelo", ctypes.c_int), ("nRango", ctypes.c_int), ("nFig", ctypes.c_char),
                  ("aSensor", ctypes.c_int), ("nTime1", ctypes.c_int), ("nTime2", ctypes.c_int), ("IFlag1", ctypes.c_bool), ("IFlag2", ctypes.c_bool)
                 ]

class eBaldosa(ctypes.Structure):
    __fields__ = [("Fig", ctypes.c_char), ("Oxigeno", ctypes.c_int), ("Carbono", ctypes.c_int), ("Nitrogeno", ctypes.c_int), ("Hidrogeno", ctypes.c_int)]

def load_sonda(sonda):
    for i in range(0,4):
        sonda[i].nId = i + 1                     
        sonda[i].nX = random.randint(0,2528)     
        sonda[i].nY = random.randint(0,1408)        #Coordenada Y en el mapa
        sonda[i].Cxd = 0
        sonda[i].Cyd = 0
        sonda[i].Nvelo = random.randint(1,40)     
        sonda[i].nRago = random.randint(1,10)     
        sonda[i].nFig = "sondas/s"+str(i)+".png"
        sonda[i].aSensor = [0, 0, 0, 0, 0]        
        sonda[i].nTime1 = 0                       
        sonda[i].nTime2 = 0                       
        sonda[i].IFlag1 = False                   
        sonda[i].IFlag2 = False                    

def load_bal(baldosa):
    for i in range(0, 13):
        baldosa[i].Fig = "tiles/"+str(i)+".png"       
        baldosa[i].Oxigeno = random.randint(0, 100)    
        baldosa[i].Carbono = random.randint(0, 100)    
        baldosa[i].Nitrogeno = random.randint(0, 100)  
        baldosa[i].Hidrogeno = random.randint(0, 100)  
    return

class new_mapa(pygame.surface.Surface):
    def __init__(self, baldosas, m_size):  
        self.baldosas = baldosas           
        self.grilla = self.get_malla()     
        self.imagenes = self.load_images() 
        self.s1 = pygame.Surface(m_size)
        self.mapa = self.load_mapa()
        self.rect = self.s1.get_rect()
        self.rect.move_ip(0, 0)

    def load_mapa(self):                   
        x = 0
        y = 0

        malla_img = self.grilla
        img_bal = self.imagenes
        for i in range(45):
            for j in range(80):
                num = malla_img[i][j]
                m = img_bal[num]
                self.s1.blit(m, (x, y))
                x += 32
            y += 32
            x = 0

    def grilla_imagenes_(self):
        malla_img = self.grilla
        bal = self.baldosas
        grilla_images = [0] * 80
        for i in range(45):
            grilla_images[i] = [0] * 80
        for f in range(45):
            for c in range(80):
                bal[malla_img[f][c]]
                grilla_images[f][c] = bal[malla_img[f][c]]
                grilla_images[f][c].Oxigeno = random.randint(0,100)
                grilla_images[f][c].Carbono = random.randint(0,100)
                grilla_images[f][c].Nitrogeno = random.randint(0,100)
                grilla_images[f][c].Hidrogeno = random.randint(0,100)
        return grilla_images


    def get_malla(self):         
        malla = [0] * 80
        for i in range(45):
            malla[i] = [0] * 80

        for f in range(45):
            for c in range(80):
                p = random.randint(0, 12)
                malla[f][c] = p
        return malla

    def load_images(self):        
        images = []
        for p in range(0,13):
            images.append(Load_Image(self.baldosas[p].Fig, True))
        return images

    def scroll(self):
        Mx, My = pygame.mouse.get_pos()

        x = 0
        y = 0
        if Mx < 100:
            x += 8
        if Mx > 540:
            x -= 8
        if My < 100:
            y += 8
        if My > 380:
            y -= 8

        self.rect.move_ip(x, y)

    def update(self, screen):
        if self.rect.x > 0:
            self.rect.x = 0
        if self.rect.x < -1920:
            self.rect.x = -1920
        if self.rect.y > 0:
            self.rect.y = 0
        if self.rect.y < -960:
            self.rect.y = -960
        screen.blit(self.s1, (self.rect.x, self.rect.y))

class Sondas_Automatas(pygame.surface.Surface):
    def __init__(self, mapa, sonda):
        self.sonda = sonda
        self.image = Load_Image(self.sonda.nFig,True)
        self.rect = self.image.get_rect()
        self.mapa = mapa
        self.rect.move_ip(self.sonda.nX, self.sonda.nY)
        self.s_sonda = pygame.Surface((90,90))
        self.cuadros = 0
        self.distancia = 0
        self.bateria = 100
        self.bateria_send = 0
        self.vel()
        self.bateria_S()
        self.carga = 10000

    def bateria_S(self):
        self.cuadros = self.distancia / 32
        if self.cuadros > 2:
            self.bateria -= 1
            self.bateria_send += 1
            self.distancia = 0

    def vel(self):
        self.sonda.Nvelo = random.randint(1,3)
        self.sonda.Cxd = random.randint(-2,2)
        self.sonda.Cyd = random.randint(-2,2)

        self.sonda.nRango =  random.randint(0,5) * 32
        self.cont = 0

        nDir = random.randint(1,5)
        if nDir == 1: # Norte ?
           self.sonda.Cxd = 0 ; self.sonda.Cyd = self.sonda.Cxd
        if nDir == 2: # Este ?
           self.sonda.Cxd = self.sonda.Cxd  ; self.sonda.Cyd = 0
        if nDir == 3: # Sur ?
           self.sonda.Cxd = 0 ; self.sonda.Cyd = self.sonda.Cyd
        if nDir == 4: # Oeste ?
           self.sonda.Cxd = self.sonda.Cxd; self.sonda.Cyd = 0

    def mover(self):
        self.bateria_S()
        self._x = self.sonda.Cxd * self.sonda.Nvelo
        self._y = self.sonda.Cyd * self.sonda.Nvelo
        self.cont += 0.1
        if self.bateria <= 0:
            distancia = 0
            self.cargar_batery()
        if self._x == 0 and self._y > 0:
            self.distancia += 1
        elif self._x > 0 and self._y == 0:
            self.distancia += 1
        elif self._x > 0 and self._y > 0:
            self.distancia += 1
        if self.cont > self.sonda.nRango:
            self.vel()

        self.rect.move_ip(self._x,self._y)

    def cargar_batery(self):
        self._x = 0
        self._y = 0
        self.cuadros = 0
        self.carga -= 1
        if self.carga % 100 == 0:
            self.bateria_send -= 1
        if self.bateria_send == 0:
            self.bateria = 100

    def update(self,screen):
        if self.rect.x < 0:
            self.sonda.Cxd = - self.sonda.Cxd
        if self.rect.x > 2560-32:
            self.sonda.Cxd = - self.sonda.Cxd
        if self.rect.y < 0:
            self.sonda.Cyd = - self.sonda.Cyd
        if self.rect.y > 1440-32:
            self.sonda.Cyd = - self.sonda.Cyd
        screen.blit(self.image,(self.rect.x + self.mapa.rect.x, self.rect.y + self.mapa.rect.y))

class S_panel(pygame.surface.Surface):
    def __init__(self, s_auto,mapa,superficie):
        self.s_auto = s_auto               
        self.super_f = superficie          
        self.mapa = mapa                   
        self.image_sonda = self.s_auto.image
        self.super_bateria = pygame.Surface((58,40)) 
        self.super_nivelesQ = pygame.Surface((58,42))
        self.super_total = pygame.Surface((160,100)) 
        self.super_total.fill((255,255,255))         
        self.super_texto = pygame.Surface((58,13))
        self.text_niveles_Q()                        
        self.superficie = self.super_niveles_Q()     
        self.grilla = self.mapa.grilla
        self.grilla_images = self.mapa.grilla_imagenes_()
        self.batery_image = pygame.transform.scale(Load_Image("images/b2.png",True),(22,35))
        self.super_hide = pygame.Surface((15,26))
        self.super_hide2 = pygame.Surface((22,35))

    def mostrar(self):
        self.super_f.fill((0,0,0))      #Fondo del mini mapa, color negro
        self.super_f.blit(self.mapa.s1,(-self.s_auto.rect.x+32,-self.s_auto.rect.y+32))     #Mapa del minimapa
        self.super_f.blit(self.s_auto.image,(32,32))        #Nave del minimapa
        self.niveles_Q()
        self.batery()

    def text_niveles_Q(self):
        O = fuentes("O", 15)
        C = fuentes("C", 15)
        H = fuentes("H", 15)
        N = fuentes("N", 15)
        self.super_texto.blit(O,(1,2))
        self.super_texto.blit(C,(15,2))
        self.super_texto.blit(H,(30,2))
        self.super_texto.blit(N,(45,2))

    def super_niveles_Q(self):
        return pygame.Surface((8,40))     

    def niveles_Q(self):
        images_G = self.grilla_images     
        x = self.s_auto.rect.x            
        y = self.s_auto.rect.y            
        self.super_nivelesQ.fill((0,0,0))
        if x < 2528 and y < 1408:
            y = (y / 32) + 1
            x = (x / 32) + 1
            O = (float(images_G[y][x].Oxigeno) / 100) * 40
            C = (float(images_G[y][x].Carbono) / 100) * 40
            N = (float(images_G[y][x].Nitrogeno) / 100) * 40
            H = (float(images_G[y][x].Hidrogeno) / 100) * 40
            self.superficie.fill((255,255,255))
            self.super_nivelesQ.blit(self.superficie,(2, O+2))
            self.superficie.fill((255,255,0))
            self.super_nivelesQ.blit(self.superficie,(15,C+2))
            self.superficie.fill((255,255,34))
            self.super_nivelesQ.blit(self.superficie,(30,N+2))
            self.superficie.fill((255,255,90))
            self.super_nivelesQ.blit(self.superficie,(44,H+2))

    def batery(self):
        V = self.s_auto.bateria_send
        bater = (V / 100.0) * 26
        self.super_hide2.fill((0,0,0))
        if V >= 0 and V < 50:
            self.super_hide.fill((26,255,0))
        if V >= 50 and V < 85:
            self.super_hide.fill((247,255,0))
        if V >=85 and  V <= 100:
            self.super_hide.fill((255,0,0))
        self.super_hide2.blit(self.super_hide,(5,bater+6))    #6
        self.super_bateria.blit(self.super_hide2,(34,2))#-25
        self.super_bateria.blit(self.image_sonda,(2,4))
        self.super_bateria.blit(self.batery_image,(34,2))

    def update(self,screen):
        self.super_total.blit(self.super_f,(2,2))
        self.super_total.blit(self.super_bateria,(100,2))
        self.super_total.blit(self.super_nivelesQ,(100,44))
        self.super_total.blit(self.super_texto,(100,85))
        return self.super_total


def main():
    screen = pygame.display.set_mode((ANCHO, LARGO))

    mapa = pygame.Surface(Mapa)

    s1 = pygame.Surface(Panel)

    s2 = pygame.Surface(Panel)

    s3 = pygame.Surface(Panel)

    s4 = pygame.Surface(Panel)


    sonda = [eSonda() for i in range(0, 4)]    
    baldosa = [eBaldosa() for i in range(0,13)] 
    load_bal(baldosa)                         
    load_sonda(sonda)
    map = new_mapa(baldosa, Mapa)

    sonda1 = Sondas_Automatas(map,sonda[0])
    sonda2 = Sondas_Automatas(map,sonda[1])
    sonda3 = Sondas_Automatas(map,sonda[2])
    sonda4 = Sondas_Automatas(map,sonda[3])

    panel1 = S_panel(sonda1,map,s1)
    panel2 = S_panel(sonda2,map,s2)
    panel3 = S_panel(sonda3,map,s3)
    panel4 = S_panel(sonda4,map,s4)

    reloj = pygame.time.Clock()

    while True:

        for event in pygame.event.get():
            if event.type == pygame.QUIT:
                sys.exit()

        map.scroll()
        map.update(screen)

        sonda1.mover()
        sonda2.mover()
        sonda3.mover()
        sonda4.mover()
        sonda1.update(screen)
        sonda2.update(screen)
        sonda3.update(screen)
        sonda4.update(screen)
        panel1.mostrar()
        panel2.mostrar()
        panel3.mostrar()
        panel4.mostrar()
        pantalla1 = panel1.update(screen)
        pantalla2 = panel2.update(screen)
        pantalla3 = panel3.update(screen)
        pantalla4 = panel4.update(screen)

        screen.blit(pantalla1, (0, 2))
        screen.blit(pantalla2, (162, 2))
        screen.blit(pantalla3, (324, 2))
        screen.blit(pantalla4, (486, 2))
        #reloj.tick(60)
        pygame.display.flip()

if __name__ == '__main__':
    pygame.init()
    main()
 Ejemplo: