O TEMA DO FÓRUM ESTÁ EM MANUTENÇÃO. FEEDBACKS AQUI: ACESSAR

Gab MySQL Highscore

Iniciado por Raizen, 18/12/2012 às 20:06

18/12/2012 às 20:06 Última edição: 18/12/2012 às 20:44 por Raizen
[box class=titlebg2]
Gab MySQL Highscores
[/box]

[box class=catbg]Introdução:[/box]
[box class=randomquote]Script funciona também no RMXP e no RMVX

     Sabe aquele mini-game que você queria saber como os jogadores realmente se saem? Ou mesmo quer comparar os pontos? Que tal usar para dar um toque a mais de profissionalidade no seu jogo? Fiz esse script para que o jogador possa enviar a sua pontuação para um banco de dados online, e que outros jogadores possam verificar quanto é que esse jogador pontuou. Tudo através do próprio RPG Maker!
[/box]

[box class=catbg]Características:[/box]
[box class=randomquote]- Rápido e Simples
- Possui uma cena própria para verificar as pontuações
- Customização máxima
- Compatível com os três makers
[/box]

[box class=catbg]Screenshots:[/box]
[box class=randomquote]
Sistema em funcionamento:
Spoiler
[close]

Quando o conteúdo ultrapassa a janela, cria-se uma barra de rolagem:
Spoiler
[close]
[/box]

[box class=catbg]Como usar:[/box]
[box class=randomquote]
Para enviar uma pontuação:
Spoiler

Highscores.send(a,b)


a - Nick (entre aspas).
Exemplo: "Nick"

b - Pontuação.
Exemplo: 200
[close]

Para enviar a pontuação a partir de variáveis, chame:
Spoiler

Highscores.send_variables(a,b)


a - ID de um herói (da database). O nome será enviado.
Exemplo: 1

b - ID de uma variável, que corresponde a pontuação.
Exemplo: 2
[close]

Chamar a cena para visualizar os recordes:
Spoiler

Highscores.scene

[close]

Criação da tabela MySQL:
Spoiler

Basta rodar a seguinte query SQL, que irá criar a tabela "Recordes", já com as configurações necessárias.
-- phpMyAdmin SQL Dump
-- version 3.4.5
-- http://www.phpmyadmin.net
--
-- Servidor: 127.0.0.1
-- Tempo de Geração: 24/03/2012 às 23h13min
-- Versão do Servidor: 5.5.16
-- Versão do PHP: 5.3.8

SET SQL_MODE="NO_AUTO_VALUE_ON_ZERO";
SET time_zone = "-02:00";

/*!40101 SET @OLD_CHARACTER_SET_CLIENT=@@CHARACTER_SET_CLIENT */;
/*!40101 SET @OLD_CHARACTER_SET_RESULTS=@@CHARACTER_SET_RESULTS */;
/*!40101 SET @OLD_COLLATION_CONNECTION=@@COLLATION_CONNECTION */;
/*!40101 SET NAMES utf8 */;

--
-- Estrutura da tabela `recordes`
--

CREATE TABLE IF NOT EXISTS `recordes` (
  `Nick` varchar(255) NOT NULL COMMENT 'Nick do utilizador',
  `Pontos` int(20) NOT NULL DEFAULT '0' COMMENT 'Pontuação',
  `Hora` int(11) NOT NULL DEFAULT '0' COMMENT 'Hora do envio'
) ENGINE=InnoDB DEFAULT CHARSET=latin1;

/*!40101 SET CHARACTER_SET_CLIENT=@OLD_CHARACTER_SET_CLIENT */;
/*!40101 SET CHARACTER_SET_RESULTS=@OLD_CHARACTER_SET_RESULTS */;
/*!40101 SET COLLATION_CONNECTION=@OLD_COLLATION_CONNECTION */;

[close]

Sites para criar sua database:
Spoiler

http://www.freemysql.net/
http://www.db4free.net/
http://www.mysqlforfree.com/
http://www.freesql.org/

Em alguns hosts para sites, você pode receber o recurso da database sql 'de presente'.
[close]

Download da libmysql.dll (Necessária para o funcionamento do script), que você deve deixar na pasta principal (root) do seu projeto:
Spoiler
[/box]

[box class=catbg]Script:[/box]
[box class=randomquote]
#==============================================================================#
# Gab MySQL Highscores                                                         #
# Autor: Gab!                                                                  #
# Data:  24/03/12                                                              #
#------------------------------------------------------------------------------#
# Script que permite ao usuário enviar sua pontuação para uma database online  #
# e ver, também, a pontuação de outros jogadores.                              #
#                                                                              #
# - Requerimentos:                                                             #
#   * libmysql.dll                                                             #
#   * Uma database online                                                      #
#                                                                              #
# - Aviso:                                                                     #
#   Os dados não são protegidos, logo, se alguém desencriptar seu jogo, terá   #
#   acesso ao seu servidor, usuário e senha. O autor não se responsabiliza por #
#   perda de informações e/ou quaisquer danos.                                 #
#                                                                              #
# - Como usar:                                                                 #
#   Para enviar uma pontuação, chame o script:                                 #
#                                                                              #
#   Highscores.send(a,b)                                                       #
#   a = Nick (entre aspas). Exemplo: "Nick".                                   #
#   b = Pontuação.          Exemplo: 200                                       #
#                                                                              #
#   Para enviar a pontuação a partir de variáveis, chame:                      #
#                                                                              #
#   Highscores.send_variables(a,b)                                             #
#   a = ID de um herói (da database). O nome será enviado. Exemplo: 1          #
#   b = ID de uma variável, que corresponde a pontuação.   Exemplo: 2          #
#==============================================================================#

module Gab
  # CONFIGURAÇÕES DA DATABASE
  module Mysql
    Host = "localhost"     # Servidor MySQL (local : 127.0.0.1)
    Port = 3306            # Porta (padrão: 3306)
    
    User = "root"          # Usuário
    Pass = ""              # Senha
    
    Base = "GabHighscores" # Nome da database
    Tabl = "recordes"      # Nome da tabela
    
    # Erros
    Err_Con = "Mysql:\nNão foi possível conectar à database"
    Err_Req = "Mysql:\nNão foi possível enviar o pedido à database"
  end
  
  # CONFIGURAÇÕES DA SCENE
  module SceneHighscores
    Back = "HighscoresBG"      # Imagem de fundo
    
    # Janela de título
    Title = { 
      :x  =>              5, # Posição x
      :y  =>              0, # Posição y
      :w  =>            300, # Largura
      :h  =>             64, # Altura
      :fn => "Trebuchet MS", # Nome da fonte
      :fs =>             30, # Tamanho da fonte
      :fc =>      "#00CCFF", # Cor da fonte em hexadecimal
      :tx =>     "Recordes", # Texto na janela
      :al =>              1, # Alinhamento do texto 
                             # (0 = Esquerda | 1 = Centro | 2 = Direita)
    }
    
    # Janela de recordes
    Recorde = { 
      :x   =>              5, # Posição x
      :y   =>             64, # Posição y
      :w   =>            300, # Largura
      :h   =>            352, # Altura
      
      :fn1 => "Trebuchet MS", # Nome da fonte dos nomes
      :fs1 =>             25, # Tamanho da fonte dos nomes
      :fc1 =>      "#00CCFF", # Cor da fonte dos nomes em hexadecimal
      
      :rnx =>              0, # Posição relativa x dos nomes
      :rny =>              0, # Posição relativa y dos nomes
      
      :fn2 => "Trebuchet MS", # Nome da fonte dos pontos
      :fs2 =>             17, # Tamanho da fonte dos pontos
      :fc2 =>      "#CCFF00", # Cor da fonte dos pontos em hexadecimal
      
      :rpx =>              5, # Posição relativa x dos pontos
      :rpy =>             25, # Posição relativa y dos pontos
      
      :fn3 => "Trebuchet MS", # Nome da fonte da data
      :fs3 =>             17, # Tamanho da fonte da data
      :fc3 =>      "#CCFF00", # Cor da fonte da data em hexadecimal
      
      :rdx =>              5, # Posição relativa x da data
      :rdy =>             37, # Posição relativa y da data
      
      :max =>             20, # Máximo de recordes exibidos
      :pdd =>              5, # Espaço vertical entre os recordes
      
      # Formato de hora
      :tfm => "%d/%m/%y às %H:%M:%S",
      # Ocorrem as seguintes substituições:
      # %d -> Dia
      # %m -> Mês
      # %y -> Ano
      # %I -> Hora (1~12)
      # %H -> Hora (0~24)
      # %M -> Minuto
      # %S -> Segundos
      # %P -> Indicador de meridiano (AM/PM)
      # %p -> Indicador de meridiano (am/pm)
      # %% -> "%" literal
      
      
      :bar1 =>      "#FFFFFF", # Cor de fundo da barra de rolagem
      :bar2 =>      "#00DD00", # Cor da barra de rolagem
    }
    
  end
end

#===============================================================================
# Não modificar a partir daqui
#===============================================================================

# COMPATIBILIDADE - RMXP
if defined?(RPG::Cache)
  class Scene_Base
    def main
      start                    
      Graphics.transition(10)
      Input.update             
      loop do
        update                 
        break if $scene != self
      end
      Graphics.update
      Graphics.freeze   
      terminate         
    end  
    
    def update
      Graphics.update
      Input.update
    end
  end
  
  class Bitmap
    def clear_rect(x, y, w, h)
      fill_rect(x,y,w,h,BLANK)
    end
    BLANK = Color.new(0,0,0,0)
  end
  
  Cache = RPG::Cache
end

class Numeric
  def copymem(len)
    buf = 0.chr * len
    Win32API.new("kernel32", "RtlMoveMemory", "pll", "").call(buf, self, len)
    return buf
  end
end

class Mysql
  include Gab::Mysql
  DLL     = "libmysql.dll"  
  
  MI   = Win32API.new(DLL, "mysql_init",               "l",        "l")
  MQ   = Win32API.new(DLL, "mysql_query",              "lp",       "l")
  MFR  = Win32API.new(DLL, "mysql_fetch_row",          "p",        "l")
  MFL  = Win32API.new(DLL, "mysql_fetch_lengths",      "p",        "l")
  MNF  = Win32API.new(DLL, "mysql_num_fields",         "p",        "l")
  MSR  = Win32API.new(DLL, "mysql_store_result",       "l",        "l")
  MRC  = Win32API.new(DLL, "mysql_real_connect",       "lpppplpl", "l")
  MNR  = Win32API.new(DLL, "mysql_num_rows",           "p",        "l")
  MFRE = Win32API.new(DLL, "mysql_free_result",        "p",        "l")
  
  def initialize(h, u, p, b, po)
    @handle = MI.call(0)
    alert(Err_Con) if MRC.call(@handle, h, u, p, b, po, nil, 0) == 0
  end

  def query(req, ret = true)
    return alert(Err_Req + req) unless MQ.call(@handle,req)
    
    MFRE.call(@result) if @result
    @result = MSR.call(@handle)
    
    return @result unless ret
    
    r = @result
    nr, nf, en = MNR.call(r), MNF.call(r), []
    
    nr.times{|i|
      c  = MFR.call(r).copymem(4).unpack("i").first
      tf = MFL.call(r).copymem(4*nf).unpack("i*")
      sf = tf.inject(0){|n,i| n + i}
      en << c.copymem(sf + nf).split("\0")
    }
    
    return en
  end
  
  if RUBY_VERSION =~ /1\.9/
    alias alert msgbox 
  else
    alias alert print
  end
  
  private :alert
  
end

module Highscores
  INST = Mysql.new(Gab::Mysql::Host, Gab::Mysql::User, Gab::Mysql::Pass, Gab::Mysql::Base, Gab::Mysql::Port)
  
  module_function
  def send(nome, pontos)
    INST.query("INSERT INTO `#{Gab::Mysql::Tabl}` (Nick, Pontos, Hora) VALUES ('#{nome}', #{pontos}, #{Time.now.to_i})", false)
  end
  
  def send_variables(id1, id2)
    send($game_actors[id1].name, $game_variables[id2])
  end
  
  def get(max = 10)
    INST.query("SELECT * FROM `#{Gab::Mysql::Tabl}` ORDER BY Pontos DESC")[0, max]
  end
  
  def scene
    SceneManager.call(Scene_Highscores)
  end
end

class Window_Title < Window_Base
  include Gab::SceneHighscores
  
  def initialize
    super(Title[:x], Title[:y], Title[:w], Title[:h])
    self.contents = Bitmap.new(self.width - 32, self.height - 32)
    
    hex = Title[:fc].delete("#").scan(/../).map{|i| i.to_i(16)}[0,4].compact
    
    self.contents.font.name  = Title[:fn]
    self.contents.font.size  = Title[:fs]
    self.contents.font.color = Color.new(*hex)
    
    refresh
  end
  
  def refresh
    self.contents.clear
    self.contents.draw_text(self.contents.rect, Title[:tx], Title[:al])
  end
end

class Window_Highscores < Window_Base
  include Gab::SceneHighscores
  
  def initialize
    super(Recorde[:x], Recorde[:y], Recorde[:w], Recorde[:h])
    
    @color = [:fc1, :fc2, :fc3, :bar1, :bar2].map{|i|
      h = Recorde[i].delete("#").scan(/../).map{|i| i.to_i(16)}[0,4].compact
      Color.new(*h)
    }
    
    @total = Recorde[:rny] + Recorde[:rpy] + Recorde[:rdy] + Recorde[:pdd]
    @gets = Highscores.get(Recorde[:max])
    
    self.contents.dispose if self.contents
    self.contents = Bitmap.new(self.width - 32, @total * @gets.size - Recorde[:pdd] * 2)
    
    refresh
    refresh_bar if contents.height > self.height - 32
  end
  
  def refresh
    self.contents.clear
    
    w, h = contents.width, contents.font.size
    
    self.contents.font.name  = Recorde[:fn1]
    self.contents.font.size  = Recorde[:fs1]
    self.contents.font.color = @color[0]
    @gets.each_with_index{|(nick, points, date), index|
      self.contents.draw_text(Recorde[:rnx], @total * index + Recorde[:rny], w, h, nick)
    }
    
    self.contents.font.name  = Recorde[:fn2]
    self.contents.font.size  = Recorde[:fs2]
    self.contents.font.color = @color[1]
    @gets.each_with_index{|(nick, points, date), index|
      self.contents.draw_text(Recorde[:rpx], @total * index + Recorde[:rpy], w, h, points)
    }
    
    self.contents.font.name  = Recorde[:fn3]
    self.contents.font.size  = Recorde[:fs3]
    self.contents.font.color = @color[2]
    @gets.each_with_index{|(nick, points, date), index|
      date = Time.at(date.to_i).strftime(Recorde[:tfm])
      self.contents.draw_text(Recorde[:rpx], @total * index + Recorde[:rdy], w, h, date)
    }
    
  end

  def refresh_bar
    self.contents.clear_rect(contents.width - 2, 0, 2, contents.height)
    self.contents.fill_rect(contents.width - 2, self.oy, 2, self.height - 32, @color[3])
    h = ((self.height - 32) ** 2) / contents.height
    y = ((h + 1) * self.oy / (self.height - 32))
    self.contents.fill_rect(contents.width - 2, self.oy + y, 2, h, @color[4])
  end
  
  def update
    super()
    if Input.press?(Input::DOWN)
      self.oy += 1 if (contents.height - self.oy > self.height - 32)
      refresh_bar
    elsif Input.press?(Input::UP) && self.oy != 0
      self.oy -= 1 
      refresh_bar
    end
  end

end

class Scene_Highscores < Scene_Base
  def start
    @title = Window_Title.new
    @high  = Window_Highscores.new
    @back  = Sprite.new
    @back.bitmap = Cache.picture(Gab::SceneHighscores::Back)
  end
  
  def update
    super()
    @title.update
    @high.update
    return_scene if Input.trigger?(Input::B)
  end
  
  def terminate
    Graphics.freeze
    @title.dispose
    @high.dispose
    @back.bitmap.dispose
    @back.dispose
  end
end


# COMPATIBILIDADE - RMVX / RMXP
if RUBY_VERSION !~ /1\.9/
  class Scene_Highscores
    def initialize(ret = nil)
      super()
      @return = ret.class
    end
    
    def return_scene
      $scene = @return.new
    end
  end
  
  class << Highscores
    undef scene
    def scene
      $scene = Scene_Highscores.new($scene)
    end
  end
end

[/box]

[box class=catbg]Créditos e Considerações finais:[/box]
[box class=randomquote][user]Gab![/user] - Criação do script
Qualquer dúvida de como usar, procurem ele no msn (gab.teles@hotmail.com) ou por PM.
[/box]

Òtimo script, muito bom para jogos onde tem pontuações!

Uma dúvida, precisa ter o MySql para ele funcionar?
...

Sim :3, mas tem sites que o BD MySQL podem serem feitas gratuitamente :D, tem no tópico alguns sites para isso ^^, o MySQL é online para caso nunca tenha usado, então não precisa "ter", mas precisa ter algum acesso a ele se me entende :P