Sobre como guardar los puntajes

Agrupa todas las consultas sobre los lenguajes de programacion como C, C++, Python, Java ...

Sobre como guardar los puntajes

Notapor Barajas » Mar Nov 16, 2010 2:18 am

Bueno, soy nuevo en este foro, y no sabia donde publicarlo, espero que este sea el lugar indicado.

Cuando creamos un juego, nos topamos con una curiosa problemática si mas de una persona decide jugarlo, y es con el guardar los puntajes.

Imaginemos un hipotético juego donde han logrado 1000 puntos, ¿Donde los guardamos?
Código: Seleccionar todo
#!/usr/bin/python
# -*- coding: utf-8 -*-
import os
import sys
import pygame
from pygame import *

def load_image(name, colorkey=False):
    #crea una ruta a la carpeta de datos
    #al escribirlo de esa forma, nos aseguramos
    #de que pueda abrir en todos los S.O.
    #donde este instalado python
    fullname = os.path.join(name)
    #comprobamos si existe la imagen
    try:
        image = pygame.image.load(fullname)
    except pygame.error, message:
        print 'No se puede cargar la imagen: ', fullname
        raise SystemExit, message
    #combierte la imagen para que pygame la pueda usar
    image = image.convert()
    #En este punto asignamos el colorkey
    #es decir, un color de base al que se
    #borrara dejando solo el canal alfa (transparencia)
    if colorkey:
        colorkey = image.get_at((0, 0))
        image.set_colorkey(colorkey, RLEACCEL)
    #devuelve la imagen y la recta de la imagen
    return (image, image.get_rect())

"""Mira, el objeto con el que se remplaza el "ratón"..."""
class Mira(pygame.sprite.Sprite):
    def __init__(self):
        pygame.sprite.Sprite.__init__(self)
        (self.image, self.rect) = load_image('mira.png', True)
    def update(self):
        posicion = pygame.mouse.get_pos()
        self.rect.center = posicion
        # Evita que la mira salga del rango permitido.
        if self.rect.left < 0:
            self.rect.left = 0
        elif self.rect.right > 450:
            self.rect.right = 450
        if self.rect.top <= 0:
            self.rect.top = 0
        elif self.rect.bottom >= 450:
            self.rect.bottom = 450
           
""" Creamos una clase para el botton"""
class OKButton(pygame.sprite.Sprite):
    def __init__(self, initialpos):
        (self.initialx, self.initialy)=initialpos
        pygame.sprite.Sprite.__init__(self)
        (self.image, self.rect) = load_image('Ok.png', True)
    def update(self):
        posicion= self.initialx, self.initialy
        self.rect.center = posicion

"""Clase para guardar"""
class SaveGame():
    def __init__(self):
        pass
    """ Esta seción es una reutilización de código
    def Abrir(self, nombre):
        self.nombre = nombre
        self.archivo = open((self.nombre), "r")
        self.lectura = (self.archivo).readline()
        self.diccionario = ast.literal_eval((self.lectura))
        (self.archivo).close()
        return self.diccionario
    """
    def Guardar(self, nombre, diccionario):
        self.nombre = nombre
        self.diccionario = diccionario
        self.texto =  str(self.diccionario)
        self.archivo = open((self.nombre), "w")
        self.escribir = (self.archivo).write((self.texto))
        (self.archivo).close()
        print "Puntaje salvado"
    def Info(self):
        print """
Este es el modulo encargado de leer y guardar los archivos durante el juego,
"Abrir" se defie como nombre_clase.Abrir("nombredel.archivo")
"Guardar" se define como nombre_clase.Guardar("Nombre del archivo", diccionario_de_datos)
supongo que no tengo que decir que si se guardara otro tipo de dato seria...desastroso"""

class Escritura():
    def __init__(self):
        self.line = 0
        self.strings = ['',]
        #self.font = pygame.font.Font('dejavu.ttf', 12) #(*1)
        self.font = pygame.font.Font(None, 28)
        self.dist = 20
        self.ipos_x = 50
        self.ipos_y = 50
       
    def update(self, events):
        for event in events:
            if event.type == KEYDOWN:
                if event.key == K_RETURN:
                    self.strings.append('')
                    self.line += 1
                    print self.line
                elif event.key == K_ESCAPE:
                    sys.exit()
                elif event.key == K_BACKSPACE:
                    if self.strings[self.line] == '' and self.line > 0:
                        self.strings = self.strings[0:-1]
                        self.line -= 1
                    else:
                        self.strings[self.line] = self.strings[self.line][0:-1]
                else:
                    self.strings[self.line] = str(self.strings[self.line] + event.unicode)
                   
    def draw(self, screen):
        #print self.strings, self.line
        screen.fill((0, 0, 0))
        for line in range(len(self.strings)):
            img_line = self.font.render(self.strings[line], 1, (255, 255, 255))
            screen.blit(img_line, (self.ipos_x, self.ipos_y + self.dist * line))
    def que_escribio(self):
        return self.strings[0]#Esto es para salvar solo la primera linea del nombre
           
def main():
    pygame.init()
    screen = pygame.display.set_mode((450, 450))
    pygame.display.set_caption("Guardar Puntos; Escribe tu nombre")
    #pygame.mouse.set_visible(False)
    sprites = pygame.sprite.RenderClear()
    boton = OKButton((400,400))
    pygame.init()
    mira=Mira()
    sprites.add(mira)
    sprites.add(boton)
    salvar = SaveGame()
    escritura = Escritura()
    salir = False
    while salir == False:
        events = pygame.event.get()
        for event in events:
            if event.type == QUIT:
                salir = True
        if event.type == MOUSEBUTTONDOWN:
            if event.button == 1:
                if pygame.sprite.collide_rect(mira, boton):
                                #Aqui es donde guardamos y salimos
                                salvar.Guardar("Arch.txt",{"Nombre":escritura.que_escribio(),"Puntaje" :1000})
                                salir = True
        escritura.draw(screen)
        sprites.draw(screen)
        escritura.update(events)
        display.update()
        sprites.update()
        pygame.display.flip()

if __name__ == '__main__':
    main()

Pantallazo.png

Bueno, lo que hace es escribir un archivo llamado Arch.txt una linea con
{"Nombre":Barajas,"Puntaje" :1000}


Se que esta muy "verde", pero creo que puede mejorarse.
Subo el archivo con todo y las imágenes que utilice.

Mi duda es:
¿Si puede mejorarse, como?
¿Hay forma de poder incluir la ñ?
¿Existe una mejor forma de mostrar los puntajes y guardarlos?
Si existe, ¿Cual es?
¿Dejare de hacer preguntas :) ?
Gracias de antemano :)

P.D. Utilice como base el código de endaramis en esta misma pagina=
viewtopic.php?t=353
Vi veri universum vivus vici
Avatar de Usuario
Barajas
 
Mensajes: 209
Registrado: Mar Nov 16, 2010 12:06 am

Re: Sobre como guardar los puntajes

Notapor hugoruscitti » Mié Nov 17, 2010 3:09 pm

Buenas, antetodo muchas gracias por compartir tu ejemplo, yo creo
que está muy bien.

Lo único que le cambiaría es la forma en la que se graba el registro, porque
he visto que python tiene un módulo para eso, se llama pickle.

Lo interesante de pickle, es que te permite tomar un objeto (casi cualquiera
que quieras) y lo puede escribir en un archivo, luego, también puede recuperarlo.

Imagina este este ejemplo, tenemos un diccionario cualquiera con
los puntajes de nuestros usuarios:

Código: Seleccionar todo
mis_puntajes = {
        'pepe': 1000,   
        'otro': 600,   
        'principiante': 100,
        }


Para volcarlos en un archivo de disco
solamente tienes que ejecutar esto:

Código: Seleccionar todo
import cPickle

archivo = open("puntajes.txt", 'w')
cPickle.dump(mis_puntajes, archivo)
archivo.close()


y listo, ahora el archivo puntajes tiene
todo el dicciónario almacenado en un formato
semi-binario.

Luego, para cargar los puntajes del archivo, por
ejemplo cuando inicia el juego, hay que escribir algo
así:

Código: Seleccionar todo
archivo = open("puntajes.txt", 'r')
mis_puntajes_recuperados = cPickle.load(archivo)
archivo.close()


Es decir, cpickle opera siempre con un archivo, y tiene dos
funciones, una para volcar contenido a un archivo (dump) y
otra para recuperar datos de un archivo y llevarlo a
memoria (load).

Sobre la consulta de la ñ, no he llegado a probar, pero creo
que si al string lo escribes como unicode, debería funcionar:

Código: Seleccionar todo
# -*- conding: utf-8 -*-
cadena = u'niño'


las cadenas unicode en python se pueden declarar
usando el prefijo "u".
Avatar de Usuario
hugoruscitti
Site Admin
 
Mensajes: 1242
Registrado: Dom Jul 30, 2006 3:57 am
Ubicación: Buenos Aires, Argentina

Re: Sobre como guardar los puntajes

Notapor Barajas » Vie Nov 19, 2010 6:00 am

No conocía el modulo cPickle, pero me facilitara las cosas :).

Modifique el código para que funcionara con el modulo, y a parte, después de presionar el botón mostrara los 3 mejores puntajes del juego, pensé en hacerlo con una serie de listas anidadas ya que -corrijanme si me equivoco- los diccionarios no tienen "orden" :!:
Código: Seleccionar todo
#!/usr/bin/python
# vim: set fileencoding=utf-8 :
import os
import sys
import pygame
import cPickle
from pygame import *
"niño" #codificación
def Guardar(loescrito):
    archivo = open("puntajes.txt", 'w')
    cPickle.dump(loescrito, archivo)
    archivo.close()

def abrir():
    archivo = open("puntajes.txt", 'r')
    puntaje_recuperado=cPickle.load(archivo)
    archivo.close()
    return puntaje_recuperado

puntajes = abrir()
#En esta parte podriamos comparar el
#puntaje obtenido en el juego
#y si es mayor que el menor de la lista

Ancho = 450
Alto = 500
DSM = None
Black = (0,0,0)
White = (250,250,250)

def load_image(name, colorkey=False):
    #crea una ruta a la carpeta de datos
    #al escribirlo de esa forma, nos aseguramos
    #de que pueda abrir en todos los S.O.
    #donde este instalado python
    fullname = os.path.join(name)
    #comprobamos si existe la imagen
    try:
        image = pygame.image.load(fullname)
    except pygame.error, message:
        print 'No se puede cargar la imagen: ', fullname
        raise SystemExit, message
    #combierte la imagen para que pygame la pueda usar
    image = image.convert()
    #En este punto asignamos el colorkey
    #es decir, un color de base al que se
    #borrara dejando solo el canal alfa (transparencia)
    if colorkey:
        colorkey = image.get_at((0, 0))
        image.set_colorkey(colorkey, RLEACCEL)
    #devuelve la imagen y la recta de la imagen
    return (image, image.get_rect())

"""Mira, el objeto con el que se remplaza el "ratón"..."""
class Mira(pygame.sprite.Sprite):
    def __init__(self):
        pygame.sprite.Sprite.__init__(self)
        (self.image, self.rect) = load_image('mira.png', True)
    def update(self):
        posicion = pygame.mouse.get_pos()
        self.rect.center = posicion
        # Evita que la mira salga del rango permitido.
        if self.rect.left < 0:
            self.rect.left = 0
        elif self.rect.right > 450:
            self.rect.right = 450
        if self.rect.top <= 0:
            self.rect.top = 0
        elif self.rect.bottom >= 450:
            self.rect.bottom = 450
           
""" Creamos una clase para el botton"""
class OKButton(pygame.sprite.Sprite):
    def __init__(self, initialpos):
        (self.initialx, self.initialy)=initialpos
        pygame.sprite.Sprite.__init__(self)
        (self.image, self.rect) = load_image('Ok.png', True)
    def update(self):
        posicion= self.initialx, self.initialy
        self.rect.center = posicion

"""La clase que se encarga de resivir el texto"""
class Escritura():
    def __init__(self):
        self.line = 0
        self.strings = ['',]
        #self.font = pygame.font.Font('dejavu.ttf', 12) #(*1)
        self.font = pygame.font.Font(DSM, 28)
        self.dist = 20
        self.ipos_x = 50
        self.ipos_y = 50
       
    def update(self, events):
        for event in events:
            if event.type == KEYDOWN:
                if event.key == K_RETURN:
                    self.strings.append('')
                    self.line += 1
                    print self.line
                elif event.key == K_ESCAPE:
                    sys.exit()
                elif event.key == K_BACKSPACE:
                    if self.strings[self.line] == '' and self.line > 0:
                        self.strings = self.strings[0:-1]
                        self.line -= 1
                    else:
                        self.strings[self.line] = self.strings[self.line][0:-1]
                else:
                    self.strings[self.line] = (str(self.strings[self.line] + event.unicode))
                   
    def draw(self, screen):
        #print self.strings, self.line
        screen.fill((0, 0, 0))
        for line in range(len(self.strings)):
            img_line = self.font.render(self.strings[line], 1, (255, 255, 255))
            screen.blit(img_line, (self.ipos_x, self.ipos_y + self.dist * line))
    def que_escribio(self):
        return self.strings[0]#Esto es para salvar solo la primera linea del nombre

"""Esta muestra los puntajes"""
def Lospuntajes():
    pygame.init()
    size = (Ancho,Alto)
    screen = pygame.display.set_mode(size)
    pygame.display.set_caption("Puntajes más altos")
    # creamos la ventana y le indicamos un titulo:
    posx = Ancho
    posy = Alto
    #definimos la fuente
    fuente1 = pygame.font.Font(DSM, 25)
    pygame.mouse.set_visible(False)
    sprites = pygame.sprite.RenderClear()
    boton = OKButton((400,400))
    pygame.init()
    mira=Mira()
    sprites.add(mira)
    sprites.add(boton)
    #Reordenamos los elementos de la lista
    puntajes.sort() #Ordena los elementos de menor a mayor
    puntajes.reverse() #Los colocamos de mayor a menor
    cuantos_hay = len(puntajes)
    puntajes.remove(puntajes[cuantos_hay-1])#asi elimina el ultimo de la lista
    i=0
    j=0
    Ejemplo = True
    while Ejemplo:
        events = pygame.event.get()
        for event in events:
            if event.type == QUIT:
                Ejemplo = False
            elif event.type == KEYDOWN and event.key == K_ESCAPE:
                Ejemplo = False
        screen.fill(Black)
        puntos1 = str(puntajes[0][0])
        puntos2 = str(puntajes[1][0])
        puntos3 = str(puntajes[2][0])
        nombre1 = puntajes[0][1]
        nombre2 = puntajes[1][1]
        nombre3 = puntajes[2][1]
        #Les asignamos la fuente
        _1 = fuente1.render(u"1°", 1, White)
        _2 = fuente1.render(u"2°", 1, White)
        _3 = fuente1.render(u"3°", 1, White)
        ###########################
        a1 = fuente1.render(puntos1, 1, White)
        a2 = fuente1.render(nombre1, 1, White)
        b1 = fuente1.render(puntos2, 1, White)
        ###########################
        b2 = fuente1.render(nombre2, 1, White)
        c1 = fuente1.render(puntos3, 1, White)
        c2 = fuente1.render(nombre3, 1, White)
        #pasamos a dibujarlos
        screen.blit(_1,(5,(Alto*1/8)))
        screen.blit(a1,((Ancho*3/4),(Alto*1/8)))
        screen.blit(a2,((Ancho/4),(Alto*1/8)))
        #############################
        screen.blit(_2,(5,(Alto*2/8)))
        screen.blit(b1,((Ancho*3/4),(Alto*2/8)))
        screen.blit(b2,((Ancho/4),(Alto*2/8)))
        ##############################
        screen.blit(_3,(5,(Alto*3/8)))
        screen.blit(c1,((Ancho*3/4),(Alto*3/8)))
        screen.blit(c2,((Ancho/4),(Alto*3/8)))
        #####################
        pygame.display.flip()

def main():
    pygame.init()
    screen = pygame.display.set_mode((Ancho, Alto))
    pygame.display.set_caption("Guardar Puntos; Escribe tu nombre")
    pygame.mouse.set_visible(False)
    sprites = pygame.sprite.RenderClear()
    boton = OKButton((400,400))
    pygame.init()
    mira=Mira()
    sprites.add(mira)
    sprites.add(boton)
    escritura = Escritura()
    salir = False
    while salir == False:
        events = pygame.event.get()
        for event in events:
            if event.type == QUIT:
                salir = True
        if event.type == MOUSEBUTTONDOWN:
            if event.button == 1 and pygame.sprite.collide_rect(mira, boton):
                print "\n!!!!!!!!!!!!Contanto contacto!!!!!!!!!!!!\n"
                puntajes.insert(0,[3000,escritura.que_escribio()])
                puntajes.sort() #Ordena los elementos de menor a mayor
                puntajes.reverse() #Los colocamos de mayor a menor
                cuantos_hay = len(puntajes)
                puntajes.remove(puntajes[cuantos_hay-1])#asi elimina el ultimo de la lista
                Guardar(puntajes)
                Lospuntajes()
        escritura.update(events)
        display.update()
        sprites.update()
        escritura.draw(screen)
        sprites.draw(screen)
        pygame.display.flip()

if __name__ == '__main__':
    main()

Se que hay una parte muy impractica.

hugoruscitti escribió:Sobre la consulta de la ñ, no he llegado a probar, pero creo
que si al string lo escribes como unicode, debería funcionar


En realidad dentro del codigo no hay problea, el problema es si piensa guardarlo como "Niñoálgó" :)

¿Alguien conoce una forma más practica de hacerlo? :)
Vi veri universum vivus vici
Avatar de Usuario
Barajas
 
Mensajes: 209
Registrado: Mar Nov 16, 2010 12:06 am


Volver a Sobre lenguajes de programación

¿Quién está conectado?

Usuarios navegando por este Foro: No hay usuarios registrados visitando el Foro y 1 invitado

cron