Show posts

This section allows you to view all posts made by this member. Note that you can only see posts made in areas you currently have access to.

Topics - orochii

1
RMXP Script Database / [XP][VX][VXA] Particle Emissor
August 14, 2018, 05:28:10 pm
Particle Emissor
Authors: Orochii Zouveleki
Version: 0.5a
Type: Visual Object Class
Key Term: Misc Add-on



Introduction

Sometimes referred to as particle system, this is more like an utility for now but it's a class to be used in order to add particle effects to your game. It includes a lot of properties for your particles and I think it's pretty capable of doing some stuff. Might be kind of hard to use though, especially since I haven't made a proper easy integration with, say, maps and battles. But a capable scripter should be able to gie this thing a good use.


Features


  • Make a particle emitter

  • Customize particle emitter shape and emission properties (interval, particles per second, etc).

  • Support for both constant emission and particle bursts (bursts can also use additional images).

  • Properties for particles, such as size, speed, acceleration, rotation, color... Each of these can vary through the particle lifespan.




Screenshots




Demo

Particles.7z (~200Kb)
Particles.rb


Script

Spoiler: ShowHide

=begin
================================================================================
''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''
OZ Particle Emitter - Versión 0.5a
''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''
Testeado en RGSS1
Autor: Orochii Zouveleki

Documentación:
''''''''''''''
module OZMath
  Este módulo incluye algunas operaciones comunes.

  def self.deg2rad(degrees) - Convierte grados a radianes.
Retorno: Numeric.
  def self.lerp(v,a,b) - Interpolación lineal entre números a y b
de acuerdo a v (0..1).
Retorno: Numeric.
  def self.clamp(v,min,max) - Restringe un valor v a un intérvalo [min,max]
Retorno: Numeric.
  def self.rand_range(a,b) - Número aleatorio entre a y b.
Retorno: Numeric.
  def self.rand_range_i(a,b) - Número aleatorio entero entre a y b.
Retorno: Numeric.
  def self.lerp_col(v, c1, c2) - Interpolación lineal entre Color c1 y c2
de acuerdo a v.
  Retorno: Color.

class FreeRange
Esta clase es una versión inútil de Range, con el objeto de soportar
valores de punto flotante.
Simplemente necesitaba algo que lo guardara, y no fuera Array. ¯\_(ツ)_/¯

  def initialize(first,last) -Inicializa objeto
  attr_reader :first -Valor inicial
  attr_reader :last -Valor final

class Particle < Sprite
  attr_reader :dead
  def initialize(bitmap,emissor,x,y,viewport=nil)
-Inicialización partícula
  def update -Lógica de partícula
  def get_property(p,modifier=nil,k=:number)
-Obtiene valor real de propiedad
  Retorno: Numeric, Array de Numeric o Color
  def get_max(p, k=:number) -
  Retorno: Numeric o Array de Numeric
  def get_modifier(mod)
    Retorno: Numeric 0..1
  # Métodos de utilidad internos
  def iter_modifiers(m, lm, sm)
  def get_property_color(p,modifier)
  def get_property_array(p,modifier)
  def get_property_number(p,modifier)
  def get_max_array(p)
  def get_max_number(p)

class ParticleEmissorProperties
 
  # Global attributes
  attr_accessor :viewport -Viewport usado por todos los sprites
  attr_accessor :simulation_space -:local para mover partícula con emisor
  attr_accessor :max_particles -Numeric, límite de sprites
  attr_accessor :duration -frames antes de reinicio de emisión
  attr_accessor :looping -si se repite el efecto
  attr_accessor :autoplay -emitir al iniciar
  attr_accessor :bitmaps -imágenes usadas por partículas (al azar)
 
  # Emission attributes
  attr_accessor :pps -Partículas por segundo
  attr_accessor :bursts -Array de ráfagas. Usa un tiempo t de
acuerdo al temporizador interno del emisor
y un número n de partículas a emitir en
el momento. bmp es usado para determinar
un bitmap personalizado (nil para usar
los otros al azar).
[[t1,n1,bmp],[t2,n2,bmp], (...)]
  attr_accessor :shape -Forma del emisor. :circle o :square
  attr_accessor :shape_a -Radio mínimo para :circle. Ancho para :square
  attr_accessor :shape_b -Radio máximo para :circle. Alto para :square
  attr_accessor :shape_angle -En círculos, delimita el arco de efecto.
[anguloInicio,anguloFin,angleStep]
 
  # Particle attributes
Los atributos de partícula suelen poseer un atributo modificador que modifica su
comportamiento de acuerdo a otro valor.
Ej. Si speed_modifier==:lifetime, la velocidad cambiará a lo largo de
la vida de la partícula.
Los atributos además pueden recibir valores en arrays o sueltos, así como rangos.
Los rangos pueden ser clase Range o FreeRange (clase hecha como parte de este script).
Ejs.
color = Color.new(0,0,0,0)
color = [Color.new(0,0,0,255),Color.new(32,128,196,160)]
speed = [1,0]
speed = [[-1,5,7],FreeRange.new(-3,3)]
Algunos atributos requieren ser encapsulados en un array siempre de un tamaño específico,
pero sus miembros internos pueden encapsularse en otro array o ser Range/FreeRange.

  attr_accessor :lifetime -Tiempo de vida de partículas (en frames)
  attr_accessor :speed -Velocidad [X,Y].
  attr_accessor :speed_modifier # :none AZAR :speed VELOCIDAD :lifetime VIDA RESTANTE
  attr_accessor :acceleration -
  attr_accessor :acceleration_modifier # :none AZAR :speed VELOCIDAD :lifetime VIDA RESTANTE
  attr_accessor :size -
  attr_accessor :size_modifier # :none AZAR :speed VELOCIDAD :lifetime VIDA RESTANTE
  attr_accessor :rotation -
  attr_accessor :rotation_modifier # :none AZAR :speed VELOCIDAD :lifetime VIDA RESTANTE
  attr_accessor :opacity -
  attr_accessor :opacity_modifier # :none AZAR :speed VELOCIDAD :lifetime VIDA RESTANTE
  attr_accessor :color -
  attr_accessor :color_modifier # :none AZAR :speed VELOCIDAD :lifetime VIDA RESTANTE
  def initialize(bitmaps=[]) -Inicializador, recibe bitmaps a usar.
  def get_random_bitmap -Devuelve un bitmap al azar de bitmaps.
Devuelve un bitmap blanco de 8x8 si no hay bitmaps.
 
class ParticleEmissor
  attr_accessor :properties
  attr_accessor :x
  attr_accessor :y
  def initialize(x, y, z, _properties=ParticleEmissorProperties.new)
  def update
  def create_new_particle(bmp)
  def get_shape_coordinate
  def dispose
================================================================================
=end

module OZMath
  def self.deg2rad(degrees)
    return degrees * Math::PI / 180
  end
 
  def self.lerp(v,a,b)
    return (b-a)*v + a
  end
 
  def self.clamp(v,min,max)
    return [ [ min, v ].max, max ].min
  end
 
  def self.rand_range(a,b)
    return rand * (b-a) + a
  end
 
  def self.rand_range_i(a,b)
    return rand(b-a)+a
  end
 
  def self.lerp_col(v, c1, c2)
    r = lerp(v, c1.red, c2.red)
    g = lerp(v, c1.green, c2.green)
    b = lerp(v, c1.blue, c2.blue)
    a = lerp(v, c1.alpha, c2.alpha)
    return Color.new(r,g,b,a)
  end
end

class FreeRange
  def initialize(first,last)
    @first = first
    @last = last
  end
 
  attr_reader :first
  attr_reader :last
end

class Particle < Sprite
  attr_reader :dead
 
  def initialize(bitmap, emissor, x, y, viewport=nil)
    super(viewport)
    self.bitmap = bitmap
    self.blend_type = 1
    @ref = emissor if emissor.properties.simulation_space==:local
    @x = x
    @y = y
    if @ref==nil
      @x += emissor.x
      @y += emissor.y
    end
    # Lifetime is constant
    @lifetime = get_property(emissor.properties.lifetime)
    @starting_lifetime = @lifetime
    @dead = false
    # Modifiers are also constant
    @speed_modifier = emissor.properties.speed_modifier
    @acceleration_modifier = emissor.properties.acceleration_modifier
    @size_modifier = emissor.properties.size_modifier
    @rotation_modifier = emissor.properties.rotation_modifier
    @opacity_modifier = emissor.properties.opacity_modifier
    @color_modifier = emissor.properties.color_modifier
   
    # Others are processed
    @speed = emissor.properties.speed
    @top_speed = get_max(emissor.properties.speed,:array)
    @acceleration = emissor.properties.acceleration
    @size = emissor.properties.size
    @rotation = emissor.properties.rotation
    @opacity_ = emissor.properties.opacity
    @color = emissor.properties.color
    # Initialize speed
    if @speed_modifier==:lifetime
      @current_speed = get_property(@speed,0,:array)
    else
      @current_speed = get_property(@speed,nil,:array)
    end
    # Update
    update
  end
 
  def iter_modifiers(m, lm, sm)
    return (m==:lifetime) ? lm : (m==:speed) ? sm : nil
  end
 
  def update
    super
    # Lifetime update
    return if @dead==true
    @lifetime -= 1
   
    # Buffer modifiers
    lm = get_modifier(:lifetime)
    sm = get_modifier(:speed)
    # Set modifier buffers to each
    speed_mod = iter_modifiers(@speed_modifier,lm,sm)
    accel_mod = iter_modifiers(@acceleration_modifier,lm,sm)
    size_mod = iter_modifiers(@size_modifier,lm,sm)
    rot_mod = iter_modifiers(@rotation_modifier,lm,sm)
    opacity_mod = iter_modifiers(@opacity_modifier,lm,sm)
    color_mod = iter_modifiers(@color_modifier, lm, sm)
    # Update speed
    accel = get_property(@acceleration,accel_mod,:array)
    @current_speed[0] += accel[0]
    @current_speed[1] += accel[1]
    # Update size
    self.zoom_x = get_property(@size[0],size_mod) if size_mod != nil
    self.zoom_y = get_property(@size[1],size_mod) if size_mod != nil
    # Update angle
    self.angle += get_property(@rotation,rot_mod)
    self.opacity = get_property(@opacity_,opacity_mod)
    # Update color
    self.color = get_property(@color, color_mod, :color)
    # Update position
    sm = speed_mod==nil ? 1 : speed_mod
    @x += @current_speed[0]*sm
    @y += @current_speed[1]*sm
    if @ref==nil
      self.x = @x
      self.y = @y
    else
      self.x = @x + @ref.x
      self.y = @y + @ref.y
    end
   
    if (@lifetime <= 0)
      @dead = true
      self.visible = false
    end
  end
 
  # Returns: Any number / array of number
  def get_property(p,modifier=nil,k=:number)
    return get_property_color(p, modifier) if k==:color
    return get_property_array(p, modifier) if k==:array
    return get_property_number(p,modifier)
  end
  # Returns: Any number / array of number
  def get_max(p, k=:number)
    return get_max_array(p) if k==:array
    return get_max_number(p)
  end
  # Returns: 0..1
  def get_modifier(mod)
    if mod==:lifetime
      return (@starting_lifetime-@lifetime)*1.0/@starting_lifetime
    end
    if mod==:speed
      s = @current_speed[0].abs + @current_speed[1].abs
      ts= @top_speed[0].abs + @top_speed[1].abs
      return (s*1.0/ts)
    end
    return 0
  end
 
  # "HELPERS" (or internal methods)
  def get_property_color(p,modifier)
    if p.is_a?(Array)
      m = modifier==nil ? rand() : modifier
      a = (p.size * m).floor
      a = p.size-1 if a>=p.size
      b = a+1
      b = a if b>=p.size
      c1 = p[a]
      c2 = p[b]
      l = (m * p.size) - a
      return OZMath.lerp_col(l, c1, c2)
    elsif p.is_a?(Color)
      return p
    end
    return Color.new(0,0,0)
  end
  def get_property_array(p,modifier)
    val = []
    for i in 0...p.size
      val[i] = get_property_number(p[i], modifier)
    end
    return val
  end
  def get_property_number(p,modifier)
    # If modifier set to none
    if (modifier == nil)
      if p.is_a?(Numeric)||p.is_a?(Color)
        return p
      elsif p.is_a?(Array)
        return 0 if p.size==0
        a = rand(p.size)
        return p[a]
      elsif p.is_a?(Range) || p.is_a?(FreeRange)
        return OZMath.rand_range(p.first, p.last)
      end
    end
    # Modifier must be 0..1
    if p.is_a?(Numeric)
      return p * modifier
    elsif p.is_a?(Array)
      return 0 if p.size==0
      a = (p.size * modifier).floor
      a = OZMath.clamp(a, 0, p.size-1)
      return p[a]
    elsif p.is_a?(Range) || p.is_a?(FreeRange)
      return OZMath.lerp(modifier, p.first, p.last)
    end
  end
 
 
  def get_max_array(p)
    val = []
    for i in 0...p.size
      val[i] = get_max_number(p[i])
    end
    return val
  end
  def get_max_number(p)
    if p.is_a?(Numeric)
      return p
    elsif p.is_a?(Array)
      a = 0
      p.each {|v| a = v if a<v}
      return a
    elsif p.is_a?(Range) || p.is_a?(FreeRange)
      return p.last
    end
  end
 
end

class ParticleEmissorProperties
  # Global attributes
  attr_accessor :viewport
  attr_accessor :simulation_space
  attr_accessor :max_particles
  attr_accessor :duration
  attr_accessor :looping
  attr_accessor :autoplay
  attr_accessor :bitmaps
 
  # Emission attributes
  attr_accessor :pps #Particles Per Second
  attr_accessor :bursts #Array [[t1,n1],[t2,n2]]
  attr_accessor :shape # :circle :square
  attr_accessor :shape_a
  attr_accessor :shape_b
  attr_accessor :shape_angle #circle only, [a,b,c]
 
  # Particle attributes (can receive array, range, etc)
  attr_accessor :lifetime
  attr_accessor :speed
  attr_accessor :speed_modifier # :none :speed :lifetime
  attr_accessor :acceleration
  attr_accessor :acceleration_modifier # :none :speed :lifetime
  attr_accessor :size
  attr_accessor :size_modifier # :none :speed :lifetime
  attr_accessor :rotation
  attr_accessor :rotation_modifier # :none :speed :lifetime
  attr_accessor :opacity
  attr_accessor :opacity_modifier # :none :speed :lifetime
  attr_accessor :color
  attr_accessor :color_modifier # :none :speed :lifetime
 
  def initialize(bitmaps=[])
    @viewport = nil
    @simulation_space = :global
    @max_particles = 1000
    @duration = 200
    @looping = true
    @autoplay = true
   
    @pps = 24
    @bursts = []
    @shape = :circle
    @shape_a = 8
    @shape_b = 0
    @shape_angle = [0,360,0]
   
    @lifetime = 60
    @speed = [FreeRange.new(-1,1),FreeRange.new(-1,1)]# ??
    @speed_modifier = :none
    @acceleration = [0,0]
    @acceleration_modifier = :none
    @size = [FreeRange.new(0.5,1.0),FreeRange.new(0.5,1.0)]
    @size_modifier = :none
    @rotation = 2
    @rotation_modifier = :none
    @opacity = FreeRange.new(192,32)
    @opacity_modifier = :lifetime
    @color = [Color.new(255,255,255,255),
              Color.new(255,255,0,255),
              Color.new(0,0,255,255)]
    @color_modifier = :lifetime
    @bitmaps = bitmaps
  end
 
  def get_random_bitmap
    if @bitmaps.size==0
      b = Bitmap.new(8,8)
      b.fill_rect(b.rect, Color.new(255,255,255,255))
      @bitmaps[0] = b
      return b
    end
    return @bitmaps[rand(bitmaps.size)]
  end
end

class ParticleEmissor
  attr_accessor :properties
  attr_accessor :x
  attr_accessor :y
 
  def initialize(x, y, z, _properties=ParticleEmissorProperties.new)
    @particles = []
    @properties = _properties
    @playing = @properties.autoplay
    @timer = @properties.duration
    @x = x
    @y = y
    @z = z
    @fps = @pps = 0 # Particle creation control variables
  end
 
  def update
    # Create control variables
    to_delete = []
    count = 0
    # Update existing particles.
    @particles.each {|p|
      if p.dead==true
        to_delete.push(p)
      else
        count += 1
        p.update
      end
    }
    # Remove old particles from array
    @particles = (@particles-to_delete)
   
    # Playing particle effect (creates new particles if it's playing)
    return if (!@playing)
    @timer -= 1
    if @timer <= 0
      if @properties.looping
        @timer = @properties.duration
      else
        @playing = false
      end
    end
    return if count > @properties.max_particles
   
    # Current second particles
    @fps += 1
    if @fps > Graphics.frame_rate
      @pps = @fps = 0
    end
    expected_pps = @properties.pps * @fps / Graphics.frame_rate
    particles_to_create = expected_pps - @pps
   
    # TODO - Bursts
    curr_time = @properties.duration - @timer
    @properties.bursts.each { |burst|
      if burst[0]==curr_time
        burst[1].times {|n| create_new_particle(burst[2])}
      end
    }
   
    if particles_to_create > 0
      # Create particle x times
      particles_to_create.times {|n| create_new_particle(nil)}
    end
    @pps = expected_pps
  end
 
  def create_new_particle(bmp)
    return if @particles.size >= @properties.max_particles
    # Create new particles
    if bmp==nil
      b = properties.get_random_bitmap
    else
      b = bmp
    end
    coord = get_shape_coordinate
    p = Particle.new(b, self, coord[0], coord[1], @viewport)
    p.z = @z
    @particles.push(p)
  end
 
  def get_shape_coordinate
    coord = [0,0]
    case @properties.shape
    when :circle
      _ap = @properties.shape_angle
      angle = OZMath.rand_range(_ap[0], _ap[1])
      angle = (angle / _ap[2]).floor * _ap[2] if _ap[2] > 0
      radius = OZMath.rand_range(@properties.shape_a, @properties.shape_b)
      rad = OZMath.deg2rad(angle)
      coord[0] = Math.cos(rad)*radius
      coord[0] = Math.sin(rad)*radius
    when :square
      ah = @properties.shape_a/2
      bh = @properties.shape_b/2
      coord[0] = OZMath.rand_range(-ah,ah)
      coord[1] = OZMath.rand_range(-bh,bh)
    end
    return coord
  end
 
  def dispose
    @particles.each {|p| p.dispose }
  end
end



Instructions

You can refer to the usage in the demo inside Scene_Title, as it showcases some of the features. But basically it works as an sprite, by changing parameters and other stuff. I did however sepparate the particle emissor properties from the emitter object, as preparation for an editor.

Most basic usage:

@yourvariable = ParticleEmissor.new(x, y, z)
#At update
@yourvariable.update
#At dispose
@yourvariable.dispose

Some extra stuff I did at the demo

p = ParticleEmissorProperties.new
# By default, all particles use a white autogenerated 8x8 square.
# This is how you assign custom bitmaps. Pass an array, and it will select one at random.
p.bitmaps = [RPG::Cache.picture("particle1")]
# Defining bursts.
p.bursts = [
      [100,32,RPG::Cache.picture("particle2")] #At the hundredth frame, spawns 32 particles using "particle2" as bitmap.
      ]
@particles = ParticleEmissor.new(320, 160, 600, p) #This is how you pass custom properties to an emitter object.



Compatibility

Afaik, none. It's an independent class.


Credits and Thanks


  • Unity, I tried ripping off as much as possible.




Author's Notes

License is Creative Commons 0. Free for use, commercial or non-commercial. You can use, share, modify it. Whatever. :^)
A lot of comments are in Spanish. Sorry! Had no time to change it. But other comments are in English just because. So there is some balance! (?)
2
Resources / OZCM - OZ Character Maker v1.03
March 06, 2016, 11:08:38 pm
Orochii Zouveleki Character Maker
Version 1.03 - Visual Basic 2008


http://puu.sh/nw4u0/60b28757a1.png

This is a tool I made several years ago, then this week took again and added some small new features.
It's a character generator. It uses a set of graphics, then combines them. You select between multiple hairs, body types, shirts, etc. And it merges it all into a single image.
I made this for my personal use in my game, to make lots of NPC variants and stuff. But it's made in a way that it supports adding graphics (because I'm making resources as I need them anyway).

There are things that could be better, but right now it works. And for the sake of usage I converted CharaMakerXP resources to be used in this.

Features:
  • - Supports all PNGs except for 4bit colors because VB2008. Only PNGs though, sorry!

  • Can work with alpha channel.

  • Exports to 24bit PNG with alpha channel.

  • You can add resources just by dropping them into the proper directories.

  • Preset save/load. Save the chara you're making, and load it. All saved into a pretty simple format.

  • Can set it to use female variations. You can just pile them all in one place too, but it's meant to make things cleaner.


Requires:
.Net Framework, any version is fine.

Downloads:
OZ Chara Maker v1.03
XP RTP Resources (converted from CharaMakerXP)

Changelog:
1.03 - It now saves width/height. And there is a checkbox to set if it uses female parts or male parts.
1.02 - Added preset save/load. Top layer for hairs. Female version support for various objects. Proper window resizing.
1.01 - Bugfixes that I don't remember. Added multiple sized character support.
1.00 - Initial version.

Salut!
3
External Animation Editor
Authors: Orochii Zouveleki
Version: 0.2
Type: Game Utility
Key Term: Game Utility

Introduction
Due to life's unexpected happenings (?), I got fed up of certain limitations in battle animations, more specifically the X/Y coordinates. So I started doing this to break those limits. It's still unfinished, barely started maybe. There is a lot to be reimplemented from the default editor to this.
This is probably going to be either made slow, or could even never be completed. I have a lot of assignments in college and/or desires to continue my game (fun fact is, I started this to use it on my own game so... heck).


Features

  • External animation editor without limitations imposed.
  • Uh... can be expanded upon. :^D!

Screenshots



Demo
https://www.dropbox.com/s/gdulaha9fgkjiyv/AnimationEditor.rar?dl=0

Instructions

Copy the Animations.rxdata file from your project to the Data folder of this thing. Then copy the Graphics\Animations folder too.
I'm sorry, maybe one day it will support opening projects.
THEN open the program (Game.exe). Do stuff.
THEN, lastly, copy the Animations.rxdata to your project. Remember to make sure your project isn't open!

RPG::SPRITE ANIMATION MOD SCRIPTLET
This is necessary in case you want to use some extra functions from the editor. These extra functions include by now:
- More than 16 sprites per frame.
More extra functions will be added in the future.

RPG::Sprite Animation Mod
Spoiler: ShowHide

module RPG
  class Sprite < ::Sprite
   
    def animation(animation, hit)
      dispose_animation
      @_animation = animation
      return if @_animation == nil
      @_animation_hit = hit
      @_animation_duration = @_animation.frame_max
      animation_name = @_animation.animation_name
      animation_hue = @_animation.animation_hue
      bitmap = RPG::Cache.animation(animation_name, animation_hue)
      if @@_reference_count.include?(bitmap)
        @@_reference_count[bitmap] += 1
      else
        @@_reference_count[bitmap] = 1
      end
      max_sprite = get_max_sprites(@_animation)
      @_animation_sprites = []
      if @_animation.position != 3 or not @@_animations.include?(animation)
        max_sprite.times {
          sprite = ::Sprite.new(self.viewport)
          sprite.bitmap = bitmap
          sprite.visible = false
          @_animation_sprites.push(sprite)
        }
        unless @@_animations.include?(animation)
          @@_animations.push(animation)
        end
      end
      update_animation
    end
   
    def loop_animation(animation)
      return if animation == @_loop_animation
      dispose_loop_animation
      @_loop_animation = animation
      return if @_loop_animation == nil
      @_loop_animation_index = 0
      animation_name = @_loop_animation.animation_name
      animation_hue = @_loop_animation.animation_hue
      bitmap = RPG::Cache.animation(animation_name, animation_hue)
      if @@_reference_count.include?(bitmap)
        @@_reference_count[bitmap] += 1
      else
        @@_reference_count[bitmap] = 1
      end
      max_sprite = get_max_sprites(@_loop_animation)
      @_loop_animation_sprites = []
      max_sprite.times {
        sprite = ::Sprite.new(self.viewport)
        sprite.bitmap = bitmap
        sprite.visible = false
        @_loop_animation_sprites.push(sprite)
      }
      update_loop_animation
    end
   
    def get_max_sprites(animation)
      max = 0
      animation.frames.each {|frame|
        max = frame.cell_max if max<frame.cell_max
      }
      return max
    end
   
    def dispose_animation
      if @_animation_sprites != nil
        sprite = @_animation_sprites[0]
        if sprite != nil
          @@_reference_count[sprite.bitmap] -= 1
          if @@_reference_count[sprite.bitmap] == 0
            sprite.bitmap.dispose
          end
        end
        for sprite in @_animation_sprites
          sprite.dispose
        end
        @_animation_sprites = nil
        @_animation = nil
      end
    end
   
    def dispose_loop_animation
      if @_loop_animation_sprites != nil
        sprite = @_loop_animation_sprites[0]
        if sprite != nil
          @@_reference_count[sprite.bitmap] -= 1
          if @@_reference_count[sprite.bitmap] == 0
            sprite.bitmap.dispose
          end
        end
        for sprite in @_loop_animation_sprites
          sprite.dispose
        end
        @_loop_animation_sprites = nil
        @_loop_animation = nil
      end
    end
   
    def update_animation
      if @_animation_duration > 0
        frame_index = @_animation.frame_max - @_animation_duration
        cell_data = @_animation.frames[frame_index].cell_data
        position = @_animation.position
        animation_set_sprites(@_animation_sprites, cell_data, position)
        for timing in @_animation.timings
          if timing.frame == frame_index
            animation_process_timing(timing, @_animation_hit)
          end
        end
      else
        dispose_animation
      end
    end
   
    def update_loop_animation
      frame_index = @_loop_animation_index
      cell_data = @_loop_animation.frames[frame_index].cell_data
      position = @_loop_animation.position
      animation_set_sprites(@_loop_animation_sprites, cell_data, position)
      for timing in @_loop_animation.timings
        if timing.frame == frame_index
          animation_process_timing(timing, true)
        end
      end
    end
   
    def animation_set_sprites(sprites, cell_data, position)
      sprites.size.times{ |i|
        sprite = sprites[i]
        pattern = cell_data[i, 0]
        if sprite == nil or pattern == nil or pattern == -1
          sprite.visible = false if sprite != nil
          next
        end
        sprite.visible = true
        sprite.src_rect.set(pattern % 5 * 192, pattern / 5 * 192, 192, 192)
        if position == 3
          if self.viewport != nil
            sprite.x = self.viewport.rect.width / 2
            sprite.y = self.viewport.rect.height - 160
          else
            sprite.x = 320
            sprite.y = 240
          end
        else
          sprite.x = self.x - self.ox + self.src_rect.width / 2
          sprite.y = self.y - self.oy + self.src_rect.height / 2
          sprite.y -= self.src_rect.height / 4 if position == 0
          sprite.y += self.src_rect.height / 4 if position == 2
        end
        sprite.x += cell_data[i, 1]
        sprite.y += cell_data[i, 2]
        sprite.z = 2000
        sprite.ox = 96
        sprite.oy = 96
        sprite.zoom_x = cell_data[i, 3] / 100.0
        sprite.zoom_y = cell_data[i, 3] / 100.0
        sprite.angle = cell_data[i, 4]
        sprite.mirror = (cell_data[i, 5] == 1)
        sprite.opacity = cell_data[i, 6] * self.opacity / 255.0
        sprite.blend_type = cell_data[i, 7]
      }
    end
   
    def animation_process_timing(timing, hit)
      if (timing.condition == 0) or
        (timing.condition == 1 and hit == true) or
        (timing.condition == 2 and hit == false)
        if timing.se.name != ""
          se = timing.se
          Audio.se_play("Audio/SE/" + se.name, se.volume, se.pitch)
        end
        case timing.flash_scope
        when 1
          self.flash(timing.flash_color, timing.flash_duration * 2)
        when 2
          if self.viewport != nil
            self.viewport.flash(timing.flash_color, timing.flash_duration * 2)
          end
        when 3
          self.flash(nil, timing.flash_duration * 2)
        end
      end
    end
   
    def x=(x)
      sx = x - self.x
      if sx != 0
        if @_animation_sprites != nil
          @_animation_sprites.size.times {|i|
            @_animation_sprites[i].x += sx
          }
        end
        if @_loop_animation_sprites != nil
          @_loop_animation_sprites.size.times {|i|
            @_loop_animation_sprites[i].x += sx
          }
        end
      end
      super
    end
   
    def y=(y)
      sy = y - self.y
      if sy != 0
        if @_animation_sprites != nil
          @_animation_sprites.size.times {|i|
            @_animation_sprites[i].y += sy
          }
        end
        if @_loop_animation_sprites != nil
          @_loop_animation_sprites.size.times {|i|
            @_loop_animation_sprites[i].y += sy
          }
        end
      end
      super
    end
   
  end
end



Compatibility
It can be potentially uncompatible with anything that overrides the RPG::Sprite class. Because for several extra functions it needs a small scriptlet that modifies that.


Credits and Thanks

  • My dog.

Author's Notes
Licence is CC0, so make anything you wish with it.
4
RPG Maker Scripts / RGSS3 TCP/IP implementation
May 01, 2014, 12:24:42 am
Hello! Now, I was reading a little here and there, mostly stood upon this thing and I got pretty fueled: http://lthzelda.wordpress.com/2010/04/28/rm-4-tcp-sockets-in-rpg-maker-vx/
I've always wanted to try out and make a game with some online capabilities. Not an MMO, just connect to a friend, and do something, like battles a-la-RPG style. Akin to Pokémon games I suppose.

So I started messing up with the code in that article. But then I found some nasty stuff I still don't get x'D, and I got pretty confused.

Take into account, I'm using the code the guy... umm... took from RMX-OS. I'll put it here for reference.
#==============================================================================
# ** Module Win32 - Handles numerical based data.
#------------------------------------------------------------------------------
# Author    Ruby
# Version   1.8.1
#==============================================================================

module Win32

  #----------------------------------------------------------------------------
  # ● Retrieves data from a pointer.
  #----------------------------------------------------------------------------
  def copymem(len)
    buf = "\0" * len
    Win32API.new('kernel32', 'RtlMoveMemory', 'ppl', '').call(buf, self, len)
    buf
  end
 
end

# Extends the numeric class.
class Numeric
  include Win32
end

# Extends the string class.
class String
  include Win32
end

#==============================================================================
# ** Module Winsock - Maps out the functions held in the Winsock DLL.
#------------------------------------------------------------------------------
# Author    Ruby
# Version   1.8.1
#==============================================================================

module Winsock

  DLL = 'ws2_32'

  #----------------------------------------------------------------------------
  # * Accept Connection
  #----------------------------------------------------------------------------
  def self.accept(*args)
    Win32API.new(DLL, 'accept', 'ppl', 'l').call(*args)
  end
  #----------------------------------------------------------------------------
  # * Bind
  #----------------------------------------------------------------------------
  def self.bind(*args)
    Win32API.new(DLL, 'bind', 'ppl', 'l').call(*args)
  end
  #----------------------------------------------------------------------------
  # * Close Socket
  #----------------------------------------------------------------------------
  def self.closesocket(*args)
    Win32API.new(DLL, 'closesocket', 'p', 'l').call(*args)
  end 
  #----------------------------------------------------------------------------
  # * Connect
  #----------------------------------------------------------------------------
  def self.connect(*args)
    Win32API.new(DLL, 'connect', 'ppl', 'l').call(*args)
  end   
  #----------------------------------------------------------------------------
  # * Get host (Using Adress)
  #----------------------------------------------------------------------------
  def self.gethostbyaddr(*args)
    Win32API.new(DLL, 'gethostbyaddr', 'pll', 'l').call(*args)
  end
  #----------------------------------------------------------------------------
  # * Get host (Using Name)
  #----------------------------------------------------------------------------
  def self.gethostbyname(*args)
    Win32API.new(DLL, 'gethostbyname', 'p', 'l').call(*args)
  end
  #----------------------------------------------------------------------------
  # * Get host's Name
  #----------------------------------------------------------------------------
  def self.gethostname(*args)
    Win32API.new(DLL, 'gethostname', 'pl', '').call(*args)
  end
  #----------------------------------------------------------------------------
  # * Get Server (Using Name)
  #----------------------------------------------------------------------------
  def self.getservbyname(*args)
    Win32API.new(DLL, 'getservbyname', 'pp', 'p').call(*args)
  end
  #----------------------------------------------------------------------------
  # * HT OnL
  #----------------------------------------------------------------------------
  def self.htonl(*args)
    Win32API.new(DLL, 'htonl', 'l', 'l').call(*args)
  end
  #----------------------------------------------------------------------------
  # * HT OnS
  #----------------------------------------------------------------------------
  def self.htons(*args)
    Win32API.new(DLL, 'htons', 'l', 'l').call(*args)
  end
  #----------------------------------------------------------------------------
  # * Inet Adress
  #----------------------------------------------------------------------------
  def self.inet_addr(*args)
    Win32API.new(DLL, 'inet_addr', 'p', 'l').call(*args)
  end
  #----------------------------------------------------------------------------
  # * Inet NtOA
  #----------------------------------------------------------------------------
  def self.inet_ntoa(*args)
    Win32API.new(DLL, 'inet_ntoa', 'l', 'p').call(*args)
  end 
  #----------------------------------------------------------------------------
  # * Listen
  #----------------------------------------------------------------------------
  def self.listen(*args)
    Win32API.new(DLL, 'listen', 'pl', 'l').call(*args)
  end
  #----------------------------------------------------------------------------
  # * Recieve
  #----------------------------------------------------------------------------
  def self.recv(*args)
    Win32API.new(DLL, 'recv', 'ppll', 'l').call(*args)
  end
  #----------------------------------------------------------------------------
  # * Select
  #----------------------------------------------------------------------------
  def self.select(*args)
    Win32API.new(DLL, 'select', 'lpppp', 'l').call(*args)
  end
  #----------------------------------------------------------------------------
  # * Send
  #----------------------------------------------------------------------------
  def self.send(*args)
    Win32API.new(DLL, 'send', 'ppll', 'l').call(*args)
  end
  #----------------------------------------------------------------------------
  # * Set Socket Options
  #----------------------------------------------------------------------------
  def self.setsockopt(*args)
    Win32API.new(DLL, 'setsockopt', 'pllpl', 'l').call(*args)
  end 
  #----------------------------------------------------------------------------
  # * Shutdown
  #----------------------------------------------------------------------------
  def self.shutdown(*args)
    Win32API.new(DLL, 'shutdown', 'pl', 'l').call(*args)
  end
  #----------------------------------------------------------------------------
  # * Socket
  #----------------------------------------------------------------------------
  def self.socket(*args)
    Win32API.new(DLL, 'socket', 'lll', 'l').call(*args) 
  end
  #----------------------------------------------------------------------------
  # * Get Last Error
  #----------------------------------------------------------------------------
  def self.WSAGetLastError(*args)
    Win32API.new(DLL, 'WSAGetLastError', '', 'l').call(*args)
  end

end

#==============================================================================
# ** Socket - Creates and manages sockets.
#------------------------------------------------------------------------------
# Author    Ruby
# Version   1.8.1
#==============================================================================

class Socket

  #----------------------------------------------------------------------------
  # ● Constants
  #----------------------------------------------------------------------------
  AF_UNSPEC                 = 0 
  AF_UNIX                   = 1
  AF_INET                   = 2
  AF_IPX                    = 6
  AF_APPLETALK              = 16

  PF_UNSPEC                 = 0 
  PF_UNIX                   = 1
  PF_INET                   = 2
  PF_IPX                    = 6
  PF_APPLETALK              = 16

  SOCK_STREAM               = 1
  SOCK_DGRAM                = 2
  SOCK_RAW                  = 3
  SOCK_RDM                  = 4
  SOCK_SEQPACKET            = 5
 
  IPPROTO_IP                = 0
  IPPROTO_ICMP              = 1
  IPPROTO_IGMP              = 2
  IPPROTO_GGP               = 3
  IPPROTO_TCP               = 6
  IPPROTO_PUP               = 12
  IPPROTO_UDP               = 17
  IPPROTO_IDP               = 22
  IPPROTO_ND                = 77
  IPPROTO_RAW               = 255
  IPPROTO_MAX               = 256

  SOL_SOCKET                = 65535
 
  SO_DEBUG                  = 1
  SO_REUSEADDR              = 4
  SO_KEEPALIVE              = 8
  SO_DONTROUTE              = 16
  SO_BROADCAST              = 32
  SO_LINGER                 = 128
  SO_OOBINLINE              = 256
  SO_RCVLOWAT               = 4100
  SO_SNDTIMEO               = 4101
  SO_RCVTIMEO               = 4102
  SO_ERROR                  = 4103
  SO_TYPE                   = 4104
  SO_SNDBUF                 = 4097
  SO_RCVBUF                 = 4098
  SO_SNDLOWAT               = 4099
 
  TCP_NODELAY               = 1
 
  MSG_OOB                   = 1
  MSG_PEEK                  = 2
  MSG_DONTROUTE             = 4
 
  IP_OPTIONS                = 1
  IP_DEFAULT_MULTICAST_LOOP = 1
  IP_DEFAULT_MULTICAST_TTL  = 1
  IP_MULTICAST_IF           = 2
  IP_MULTICAST_TTL          = 3
  IP_MULTICAST_LOOP         = 4
  IP_ADD_MEMBERSHIP         = 5
  IP_DROP_MEMBERSHIP        = 6
  IP_TTL                    = 7
  IP_TOS                    = 8
  IP_MAX_MEMBERSHIPS        = 20

  EAI_ADDRFAMILY            = 1
  EAI_AGAIN                 = 2
  EAI_BADFLAGS              = 3
  EAI_FAIL                  = 4
  EAI_FAMILY                = 5
  EAI_MEMORY                = 6
  EAI_NODATA                = 7
  EAI_NONAME                = 8
  EAI_SERVICE               = 9
  EAI_SOCKTYPE              = 10
  EAI_SYSTEM                = 11
  EAI_BADHINTS              = 12
  EAI_PROTOCOL              = 13
  EAI_MAX                   = 14

  AI_PASSIVE                = 1
  AI_CANONNAME              = 2
  AI_NUMERICHOST            = 4
  AI_MASK                   = 7
  AI_ALL                    = 256
  AI_V4MAPPED_CFG           = 512
  AI_ADDRCONFIG             = 1024
  AI_DEFAULT                = 1536
  AI_V4MAPPED               = 2048
 
  #----------------------------------------------------------------------------
  # ● Returns the associated IP address for the given hostname.
  #---------------------------------------------------------------------------- 
  def self.getaddress(host)
    gethostbyname(host)[3].unpack('C4').join('.')
  end
  #----------------------------------------------------------------------------
  # ● Returns the associated IP address for the given hostname.
  #---------------------------------------------------------------------------- 
  def self.getservice(serv)
    case serv
    when Numeric
      return serv
    when String
      return getservbyname(serv)
    else
      raise 'Please us an interger or string for services.'
    end
  end
  #----------------------------------------------------------------------------
  # ● Returns information about the given hostname.
  #----------------------------------------------------------------------------
  def self.gethostbyname(name)
    raise SocketError::ENOASSOCHOST if (ptr = Winsock.gethostbyname(name)) == 0
    host = ptr.copymem(16).unpack('iissi')
    [host[0].copymem(64).split("\0")[0], [], host[2], host[4].copymem(4).unpack('l')[0].copymem(4)]
  end
  #----------------------------------------------------------------------------
  # ● Returns the user's hostname.
  #---------------------------------------------------------------------------- 
  def self.gethostname
    buf = "\0" * 256
    Winsock.gethostname(buf, 256)
    buf.strip
  end
  #----------------------------------------------------------------------------
  # ● Returns information about the given service.
  #----------------------------------------------------------------------------
  def self.getservbyname(name)
    case name
    when /echo/i
      return 7
    when /daytime/i
      return 13
    when /ftp/i
      return 21
    when /telnet/i
      return 23
    when /smtp/i
      return 25
    when /time/i
      return 37
    when /http/i
      return 80
    when /pop/i
      return 110
    else
      raise 'Service not recognized.'
    end
  end
  #----------------------------------------------------------------------------
  # ● Creates an INET-sockaddr struct.
  #---------------------------------------------------------------------------- 
  def self.sockaddr_in(port, host)
    begin
      [AF_INET, getservice(port)].pack('sn') + gethostbyname(host)[3] + [].pack('x8')
    rescue
    end
  end
  #----------------------------------------------------------------------------
  # ● Creates a new socket and connects it to the given host and port.
  #---------------------------------------------------------------------------- 
  def self.open(*args)
    socket = new(*args)
    if block_given?
      begin
        yield socket
      ensure
        socket.close
      end
    end
    nil
  end
  #----------------------------------------------------------------------------
  # ● Creates a new socket.
  #---------------------------------------------------------------------------- 
  def initialize(domain, type, protocol)
    SocketError.check if (@fd = Winsock.socket(domain, type, protocol)) == -1
    @fd
  end
  #----------------------------------------------------------------------------
  # ● Accepts incoming connections.
  #---------------------------------------------------------------------------- 
  def accept(flags = 0)
    buf = "\0" * 16
    SocketError.check if Winsock.accept(@fd, buf, flags) == -1
    buf
  end
  #----------------------------------------------------------------------------
  # ● Binds a socket to the given sockaddr.
  #---------------------------------------------------------------------------- 
  def bind(sockaddr)
    SocketError.check if (ret = Winsock.bind(@fd, sockaddr, sockaddr.size)) == -1
    ret
  end
  #----------------------------------------------------------------------------
  # ● Closes a socket.
  #---------------------------------------------------------------------------- 
  def close
    SocketError.check if (ret = Winsock.closesocket(@fd)) == -1
    ret
  end
  #----------------------------------------------------------------------------
  # ● Connects a socket to the given sockaddr.
  #---------------------------------------------------------------------------- 
  def connect(sockaddr)
    SocketError.check if (ret = Winsock.connect(@fd, sockaddr, sockaddr.size)) == -1
    ret
  end
  #----------------------------------------------------------------------------
  # ● Listens for incoming connections.
  #---------------------------------------------------------------------------- 
  def listen(backlog)
    SocketError.check if (ret = Winsock.listen(@fd, backlog)) == -1
    ret
  end
  #----------------------------------------------------------------------------
  # ● Checks waiting data's status.
  #---------------------------------------------------------------------------- 
  def select(timeout)
    SocketError.check if (ret = Winsock.select(1, [1, @fd].pack('ll'), 0, 0, [timeout, timeout * 1000000].pack('ll'))) == -1
    ret
  end
  #----------------------------------------------------------------------------
  # ● Checks if data is waiting.
  #---------------------------------------------------------------------------- 
  def ready?
    not select(0) == 0
  end 
  #----------------------------------------------------------------------------
  # ● Reads data from socket.
  #---------------------------------------------------------------------------- 
  def read(len)
    buf = "\0" * len
    Win32API.new('msvcrt', '_read', 'lpl', 'l').call(@fd, buf, len)
    buf
  end
  #----------------------------------------------------------------------------
  # ● Returns recieved data.
  #---------------------------------------------------------------------------- 
  def recv(len, flags = 0)
    buf = "\0" * len
    SocketError.check if Winsock.recv(@fd, buf, buf.size, flags) == -1
    buf
  end
  #----------------------------------------------------------------------------
  # ● Sends data to a host.
  #---------------------------------------------------------------------------- 
  def send(data, flags = 0)
    SocketError.check if (ret = Winsock.send(@fd, data, data.size, flags)) == -1
    ret
  end
  #----------------------------------------------------------------------------
  # ● Writes data to socket.
  #---------------------------------------------------------------------------- 
  def write(data)
    Win32API.new('msvcrt', '_write', 'lpl', 'l').call(@fd, data, 1)
  end

end

#==============================================================================
# ** TCPSocket - Creates and manages TCP sockets.
#------------------------------------------------------------------------------
# Author    Ruby
# Version   1.8.1
#==============================================================================

class TCPSocket < Socket

  #----------------------------------------------------------------------------
  # ● Creates a new socket and connects it to the given host and port.
  #---------------------------------------------------------------------------- 
  def self.open(*args)
    socket = new(*args)
    if block_given?
      begin
        yield socket
      ensure
        socket.close
      end
    end
    nil
  end
  #----------------------------------------------------------------------------
  # ● Creates a new socket and connects it to the given host and port.
  #---------------------------------------------------------------------------- 
  def initialize(host, port)
    super(AF_INET, SOCK_STREAM, IPPROTO_TCP)
    connect(Socket.sockaddr_in(port, host))
  end
 
end

#==============================================================================
# ** SocketError
#------------------------------------------------------------------------------
# Default exception class for sockets.
#==============================================================================

class SocketError < StandardError
 
  ENOASSOCHOST = 'getaddrinfo: no address associated with hostname.'
 
  def self.check
    errno = Winsock.WSAGetLastError
    raise Errno.const_get(Errno.constants.detect { |c| Errno.const_get(c).new.errno == errno })
  end
 
end


I started by getting an error in this line.
SocketError.check if (ret = Winsock.connect(@fd, sockaddr, sockaddr.size)) == -1

Basically, it said that sockaddr was nil, so "size" didn't exist. I got deeper, following the trace...
def self.sockaddr_in(port, host)
    begin
      [AF_INET, getservice(port)].pack('sn') + gethostbyname(host)[3] + [].pack('x8')
    rescue
     
    end
  end

I then "removed" the rescue, just to know what error was I getting there.
It sent me to this part:
#----------------------------------------------------------------------------
  # ● Returns information about the given hostname.
  #----------------------------------------------------------------------------
  def self.gethostbyname(name)
    raise SocketError::ENOASSOCHOST if (ptr = Winsock.gethostbyname(name)) == 0
    host = ptr.copymem(16).unpack('iissi')
    [host[0].copymem(64).split("\0")[0], [], host[2], host[4].copymem(4).unpack('l')[0].copymem(4)]
  end

Was getting something about an invalid UTF-8 string. I read somewhere that Ruby 1.9.2 (the version that RGSS3 uses) strings are compatible with nul-ended strings (C chars and the such), so I just changed this accordingly, no need to cut the null char at the end.
[host[0].copymem(64), [], host[2], host[4].copymem(4).unpack('l')[0].copymem(4)]


But then, it came to a dead end. I don't know what the error I get means x'D. Tried the original code on both XP and VX projects, and none of them seemed to work either.


This is the error I get on VX/XP.


And this is the one I get on my RGSS3 XP game (pretty sure the same happens on a VXA project).

I somehow think that both errors are the same, but what changes is the nil handling. But I don't really know.

Again, no pressure. This is a feature I have zillions of seconds to develop. But wanted to try and ask if someone has any idea. Right now, I just have a small headache xD.

Salutations to all of you, ladies and gentlemen.
5
New Projects / [RM2003] Panzer
September 21, 2013, 01:18:01 am

AUTHOR: Orochii Zouveleki
GENRE: Visual Novel/RPG.
STYLE: Sci-Fi/Future/Epic.
STATUS: Complete (v1.2).

Download (v1.2)


SYNOPSIS:
Year is 2651. A world in war. Two factions reign and conquered most part of the entire planet.
The army of the kingdom of Reigarn, with huge power and politic influence.
And the tribes of the Urok, with heavy numbers and born for the battlefield.
The fight continued on and on, and for that matter, a small group parted on a mission to stop it in a movement, once and for all.

CHARACTERS:


DATA:
"Hangar": ShowHide
The hangar option lets your savegame get updated. Some game updates change certain small aspects of your game, and the hangar option lets your saved game behave correctly, fixing those issues. So, if you update your game, care to check the hangar.

"Workshop": ShowHide
The workshop is maybe one of the most important parts on the whole game. But first there is some stuff to be clear.
You use a warmech, which consists of four parts: Core, Left Arm, Right Arm and Support. The idea is to upgrade each of these parts, either on their basic characteristics (Physical, Shooting, Defense and Mobility). Or buying weaponry. Any of these upgrades cost the same kind of currency: £.

Another variable to take into account is the rank. It raises accordingly to your characteristics (a small internal calculation). When your rank is at its maximum (S:Legend), you will be unable to raise any more characteristics.
Two variables are delimited by rank. One of them are the encounters you get on the arena. The other one, is the amount of weapons you can equip on every part of your mech.

"Town": ShowHide
The town gives you three options:
-Arena: It lets you fight against some enemies before the next "mission" (aka as farming grounds).
-Shop: Buy/sell consumable items.
-INN: Save and exit the game.


IMAGES:
These are in spanish because I'm a lazy dog, foxes often jump over me. But don't worry, the game is already translated to ZeroWing-quality English! Hurrae!





ACCREDITATIONS:
QuoteGRAPHICS
    Front Mission - Squaresoft
    Metal Slug - NAZCA/SNK (Intro)

MUSIC
    Front Mission - Squaresoft

SPECIAL THANKS
    Spriters-Resource contributors
    Dr.Pete's SFXR

HONORIFIC MENTION
    Imaginarium, for RPG Maker Weekend contest. It was, aside from Front Mission, the inspiration for this game.


Salut,
Orochii Zouveleki

PD.: I'm planning to do a Panzer2 on libGDX, but I can't right now because of life. I need to die get free from some things first.
6
RPG Maker Scripts / Which is fastest? Tone or Array?
September 12, 2013, 08:04:08 pm
Hello, well I've been cleaning my code, and now I'm trying to optimize my "daylight system" from my game. Thing is, I've done something like this:
class Game_System
# I put this on a constant because I'm constantly (lol) tweaking it.
  DAY_TONES = [
      [-96,-80,-48,48],
      [-36,-72,-64,32],
      [-18,-36,-32,16],
      [8,0,0,0],
      [-64,-51,-33,32],
      [-96,-80,-48,40],
      [-128,-102,-64,48],
      [0,0,0,0]
    ]
 
  #This gives me the info from the class constant to outsiders
  #It could actually be slow because of returning sub-arrays, but... I dunno x'D...
  def day_tone
    i = 7
    if $game_map.exterior
      if @game_time[0] > 19
        i=0
      elsif @game_time[0] > 17
        i=1
      elsif @game_time[0] > 12
        i=2
      elsif @game_time[0] > 10
        i=3
      elsif @game_time[0] > 5
        i=4
      elsif @game_time[0] > 3
        i=5
      else
        i=6
      end
    end
    return DAY_TONES[i]
  end
end

class Game_Screen
  #And this is probably VERY bad. But what I meant to make was an adjustment
  def update_tone
    d = @tone_duration
    tone_day = $game_system.day_tone
    toun = [0,0,0,0]
    toun[0]=[(@tone.red * (d - 1) + (@tone_target.red + tone_day[0])) / d ,256].min
    toun[1]=[(@tone.green * (d - 1) + (@tone_target.green + tone_day[1]) / d ,255].min
    toun[2]=[(@tone.blue * (d - 1) + (@tone_target.blue + tone_day[2]) / d ,255].min
    toun[3]=[(@tone.gray * (d - 1) + (@tone_target.gray + tone_day[3]) / d ,255].min
    @tone.set(toun[0],toun[1],toun[2],toun[3])
    @tone_duration -= 1
  end
end
Any observation or... almost anything is very appreciated.

Salut,
OZ
7
Video Games / Any Indie game you love?
September 10, 2013, 03:34:12 pm
Indie, as independent. No publisher, or not from the high spheres. Those that EA and Acclaim surely think that are pure shit they stomp with their fetid feet.

So, um, spread your love!

I want to start with some kind-of pretty popular games. Cave Story, yuss. I know it is not an Indie anymore, but anyways, I do recognize it because of Pixel (Amaya Daisuke) having perseverance and stuff making the game all on its own for several years. I respect that kind of stuff, and feel a little jealous at the same time for the amount of love CaveStory receives :'D. I want some of that for my children!

As a special mention I put in Another World, from Éric Chahi. He was not Indie, but the Another World started pretty much as it. Chahi worked on it at its own house, taking photographs to make the cutscenes and stuff, and speaking of cutscenes and overall graphics, he made its own vector graphics engine, drawing a lot of solid polygons per frame in pretty limited hardware. I think that's awesome C:.

I don't know, maybe I respect a lot this kind of guru game makers (like you, probably),
Orochii Zouveleki
8

AUTOR: Orochii Zouveleki
GENRE: Light RPG
FLAVOUR: Post-apocalyptic Science fantasy
ENGINE: RPG Maker XP
STATUS: On development
DOWNLOADS:
Updater (Dropbox)
Gamejolt
RPGMaker.net


In a post-apocalyptic world, humanity continues their diary living. A world full of monsters, a violent nature and other dangers, product of long ago scientific catastrophes.
It is here where our main heroine, Hikari Morishita, gets up and starts her travelling around the world, in the name of the Academy, as a member of their special forces. People set into the world, helping the needed, and risking their lives in favor of the weak.

Following up her story, you will be able to face a lot of adventures, misadventures and much more. Discover all of the mysteries that the world of Drekirökr has to offer!


*An epic adventure with a lot of places to explore and lots of content!
*SNES/GBA styled low-res graphics.
*Fight against hordes of enemies in tactical battles!
*A lively world! Simulation of time passing, that influences most of places!
*And best of all, forever free!





"Screen captures": ShowHide




"Videos": ShowHide
Fylgja and counter demonstration - Intended to make a monthly devlog, but didn't because of time.
Battle against moles (special battle) - A little old, but showcases a little of what can be done when eventing.



Spoiler: ShowHide
Music -
Titan Némesis (Claudio Noemí).
Orochii Zouveleki

Systematic (Scripting) -
CCOA - Custom Battle Script
Dirtie - Map Wrapping (not used anymore, but thanks anyway)
ForeverZero - MMW Optimizations
Fantasist & ForeverZer0 - Transition Pack
Glitchfinder - Keyb&Gamepad Input Modules
Midge - Double Sword/Shield Support
MOG - EX Version and Damage "System"
PARA - Cursor add-on for windows
RiseField - Shadowed texts
Wachunga - Multiple Message Windows
XMS - CP Stuff I think
Orochii Zouveleki - anything else

Everyting else -
Orochii Zouveleki

Special thanks -
ToniCaprini
DarkZero
Frikilangelo
Pabloxulo
Cetros
Klaus
Destructor
Zando
Zokark2
CelioHogane
Sig
Addit
Dangaioh
Dyhalto
Edchuy
Finrod
MrHawi
Sebax



Webpage: http://drekirokr.weebly.com/

VISUAL CUSTOMIZATION
Visual style for WinXP Shell (v0.5) Screen
Wallpaper 1 - Hikari 1600x1200 1280x1024 1360x768

USERBARS
9
RPG Maker Scripts / MD5 checksum in RPG Maker XP?
April 06, 2013, 04:51:43 pm
Does anyone had tried generating a MD5 checksum in RPG Maker XP?
I have tried a lot, but can't seem to either get a DLL to work, or make the Digest class to work with RPG Maker (the RGSS ruby doesn't have that class, and it throws me an error when I try to import .so files, which are used by digest.rb).

I've also made an attempt at writing it, but I messed up with something in the algorithm because it doesn't creates a valid MD5 checksum.

Ex.: I use this online generator to verify my resulting checksums.
string: asdfqwer
result: feee448b492937af8fb5b30072d2a78
generator-result: c69874b898abb180ac71bd99bc16f8fb

Here's the code
module MD5
 
  WORD_BUFFER = [0x67452301,0xefcdab89,0x98badcfe,0x10325476]
  SINE_TABLE = [
  0xd76aa478, 0xe8c7b756, 0x242070db, 0xc1bdceee,
  0xf57c0faf, 0x4787c62a, 0xa8304613, 0xfd469501,
  0x698098d8, 0x8b44f7af, 0xffff5bb1, 0x895cd7be,
  0x6b901122, 0xfd987193, 0xa679438e, 0x49b40821,
  0xf61e2562, 0xc040b340, 0x265e5a51, 0xe9b6c7aa,
  0xd62f105d, 0x02441453, 0xd8a1e681, 0xe7d3fbc8,
  0x21e1cde6, 0xc33707d6, 0xf4d50d87, 0x455a14ed,
  0xa9e3e905, 0xfcefa3f8, 0x676f02d9, 0x8d2a4c8a,
  0xfffa3942, 0x8771f681, 0x6d9d6122, 0xfde5380c,
  0xa4beea44, 0x4bdecfa9, 0xf6bb4b60, 0xbebfbc70,
  0x289b7ec6, 0xeaa127fa, 0xd4ef3085, 0x04881d05,
  0xd9d4d039, 0xe6db99e5, 0x1fa27cf8, 0xc4ac5665,
  0xf4292244, 0x432aff97, 0xab9423a7, 0xfc93a039,
  0x655b59c3, 0x8f0ccc92, 0xffeff47d, 0x85845dd1,
  0x6fa87e4f, 0xfe2ce6e0, 0xa3014314, 0x4e0811a1,
  0xf7537e82, 0xbd3af235, 0x2ad7d2bb, 0xeb86d391
  ]
  SHIFT_AMOUNT=[ 
  7,12,17,22,5,9,14,20,4,11,16,23,6,10,15,21
  ]
 
  def self.calc_md5(string)
    r_a = little_endian(WORD_BUFFER[0]).to_i(16)
    r_b = little_endian(WORD_BUFFER[1]).to_i(16)
    r_c = little_endian(WORD_BUFFER[2]).to_i(16)
    r_d = little_endian(WORD_BUFFER[3]).to_i(16)
    #Create a binary chain from the string
    arr = Array.new
    string.each_byte{|c|
      c.to_i
      arr.push(c)
    }
    n_str = ""
    arr.each {|n|
      a = sprintf("%#b", n)
      a.slice!(0,2)
      n_str += a
    }
   
    #Padding
    n_str += "1"
    old_size = n_str.size
    while n_str.size%512 != 448
      n_str += "0"
    end
    #Prepare size to be appended
    old_size_b = sprintf("%#b", old_size)
    old_size_b.slice!(0,2)
    while old_size_b.size < 64
      old_size_b.insert(0, "0")
    end
    #Append size
    n_str += old_size_b
    #Divide in 512bit chunks
    chunks = []
    (n_str.size/512).times{|i|
      chunks.push n_str.slice( i*512,512 )
    }
    #Iterate each chunk
    chunks.each{|chunk|
      #Divide chunk in 16 32bit words
      words = []
      16.times{|i|
        words.push ((chunk.slice( i*32,32 )).to_i(2))
      }
      #Set temp variables to resulting words
      aa = wrap32(r_a)
      bb = wrap32(r_b)
      cc = wrap32(r_c)
      dd = wrap32(r_d)
      (0..63).each{|i|
        if    (0 <= i) && (i <= 15)
          ff = func(bb,cc,dd)
          g = wrap32(i)
          off_i = 0
        elsif (16<= i) && (i <= 31)
          ff = gunc(bb,cc,dd)
          g = wrap32(((5*i)+1)%16)
          off_i = 4
        elsif (32<= i) && (i <= 47)
          ff = hunc(bb,cc,dd)
          g = wrap32((3*i+5)%16)
          off_i = 8
        elsif (48<= i) && (i <= 63)
          ff = iunc(bb,cc,dd)
          g = wrap32((7*i)%16)
          off_i = 12
        end
       
        dTemp = dd
        dd = cc
        cc = bb
        ii = (i%4)+off_i
        bb = wrap32(bb + leftrotate(aa + ff + little_endian(SINE_TABLE[i]).to_i(16) + words[g], SHIFT_AMOUNT[ii]))
        aa = dTemp
      }
      r_a += aa
      r_b += bb
      r_c += cc
      r_d += dd
      r_a = wrap32(r_a)
      r_b = wrap32(r_b)
      r_c = wrap32(r_c)
      r_d = wrap32(r_d)
     
    }
    rr_a = sprintf("%#x", r_a);rr_b = sprintf("%#x", r_b)
    rr_c = sprintf("%#x", r_c);rr_d = sprintf("%#x", r_d)
    rr_a.slice!(0,2);rr_b.slice!(0,2);rr_c.slice!(0,2);rr_d.slice!(0,2)
    rr_a + rr_b + rr_c + rr_d
  end
 
  def self.leftrotate(x,c)
    b_num = sprintf("%#b", x)
    b_num.slice!(0,2)
    b_num_a = b_num.to_a
    c.times {
      b_num_a.push(b_num_a.shift)
    }
    (b_num_a.to_s).to_i(2)
  end
 
  #// F, G, H and I are basic MD5 functions.
  #define F(x, y, z) (((x) & (y)) | ((~x) & (z)))
  #define G(x, y, z) (((x) & (z)) | ((y) & (~z)))
  #define H(x, y, z) ((x) ^ (y) ^ (z))
  #define I(x, y, z) ((y) ^ ((x) | (~z)))
 
  def self.func(x,y,z)
    (x & y) | (~(x) & z)
  end
  def self.gunc(x,y,z)
    (x & z) | (y & ~(z))
  end
  def self.hunc(x,y,z)
    (x) ^ (y) ^ (z)
  end
  def self.iunc(x,y,z)
    (y) ^ (x | ~(z))
  end
 
  # Little-endian application to hex-string/number
  def self.little_endian(val,base = :hex)
    val_a = []
    case base
    when :hex
      if !(val.is_a?(String))
        val = sprintf("%#x", val)
        val.slice!(0,2)
      end
      (val.size / 2).times {
        val_a.insert (0,val.slice!(0,2))
      }
    when :bin
      if !(val.is_a?(String))
        val = sprintf("%#b", val)
        val.slice!(0,2)
      end
      (val.size / 16).times {|i|
        val_a.insert (0,val.slice!(0,16))
      }
    end
    val = val_a.to_s
    val
  end
 
  # Wrapping methods (in-module use only, sorry -?-)
  def self.wrap(val,max)
    val%max
  end
  def self.wrap32(val)
    wrap(val,4294967296)
  end
end

I made most stuff by converting to string, mostly because I ignore if there's an actual way to manipulate variable values at bit-level in Ruby.
Also I based "my" algorithm in the pseudocode I found on Wikipedia here.

So, that's it, thanks in advance,
Orochii Zouveleki
10
Alternate Style Menu Scenes
Authors: Orochii Zouveleki
Version: 1.01
Type: Custom Menu System
Key Term: Custom Menu System



Introduction

This script is based on Rune's One Man CMS. Talking about the style. I liked it, and thought that making the rest of the windows in the same "format" was a nice thing to do. So I did it.
I have to say first, that I took some lines from it, and also some others for tinting the background from BlizzABS itself (I wanted to make it a little more coherent with the premenu).
Also, even if it uses the tinted back, it doesn't neccessarily needs the BlizzABS, neither the OneManCMS. But it looks cool with them 8D.


Features


  • Centered small squared windows! It has so much style! Awww yiah!

  • Item/skill description on item, equip and skill scenes.

  • Status screen tries to be a prolongation from the OMCMS menu status (it's not like, if I would be that lazy to copy it and add some more stuff).

  • Coherent with OneMan CMS and BlizzABS. But independent from them, in case you want to use them with other main menu and stuff.

  • Includes a patch to tint the OneManCMS background (and any other custom menu, by the way).




Screenshots
Spoiler: ShowHide

Blizzard rainbow power ON!






Don't worry, even if database and default scripts are in spanish, the "important" scripts are in english.




Demo
Demonstration project, version 1.01 (hosted on MediaFire)


Script

You better grab it from the demo, included above.
Add them over main.
If using?, add it over BlizzABS.
If using?, add it below OneManCMS.


Instructions

See "Config and definitions" for further instructions related to configuration.
Much of it is just plug and play.


Compatibility

Compatible with BlizzABS and OneMan CMS.
Scripts that make changes at Item/Skill/Equip/any other window from menu screens could not be displayed properly/not work. So you have to check for that (CBSs that change item and skill visuals or something). (Almost) any menu behaviour change (update phases) will work fine C:.


Credits and Thanks


  • Blizzard and winkio, for the BlizzABS C:.

  • Rune and modern algebra, for the One-Man CMS.

  • And my dog, because he is a good boy.




Author's Notes

Hope it works for you C:. I mean, it works! but I hope that you make a good use of it, and you like it, and make your game with it and become millionaire =D!. And if you do, you can thank me with some millions ;D. Or a cheesecake.
Edit: Aw damn! Wrong section! I know! Sorry! Not anymore, thanks ForeverZer0 for moving it.