Envision, Create, Share

Welcome to HBGames, a leading amateur game development forum and Discord server. All are welcome, and amongst our ranks you will find experts in their field from all aspects of video game design and development.

Dynamic Lights & Shadows

Dynamic Lights & Shadows
Version: 1.5

Introduction

Based on the Rataime's Shadow script, I've rewrote it, using a clearer code in my opinion, and adding new features to make it a bit more realistics.

Features
Basically the same as Rataime's Shadow script. But!
  • Shadows overlay, the system know when to display the shadow or not
  • Possibility to control the source: turn the light on/off, change its direction, make it move
  • Height of objects is handled, no more 1 event per tile for the shadow of a pillar
  • Auto-Screen tint according to the number of lights off
videos
http://rmxp.trebor777.net/rmxp/dynamic_lights_and_shadows.avi
10Mb, H.264, Tell me if you can't read it.
http://rmxp.trebor777.net/rmxp/Dynamic Light and Shadow.wmv - 6.7Mb
Demo

Link

Script

Code:
=begin

==============================================================================

 ** Dynamic Light & Shadows

------------------------------------------------------------------------------

 Trebor777

 Version 1.5

 16/11/2007

 Version 1.5 is based on Rataime's shadows script,Rewrote the code structure

 and Added extra features

 

==============================================================================

Instructions

==============================================================================

To create a source light:

Write a comment on 2 lines

  Light

  arg1|arg2|arg3|arg4|arg5

 

arg1, is the minimum angle.

arg2, is the maximum angle

arg3, the distance in pixel covered by the light

arg4, the height, in tiles where the light is.

arg5, the direction of the light, use the same numbers as RMXP is using:

up: 8, right: 6, down: 2, left: 4

It will turn the event automatically to this direction and 

draw the light according to it, using its min and max angle.

 

The 0 is always on the left of the direction.

example, 

the light "look at" the right, so its direction is 6.

the min angle is 0, so it'll start from the tile above to whatever

 the max angle is, in a clockwise way.

 

So if you need to create a light, who covers only a cone of 60?, facing to the 

right, at a height of 1 tile, covering a radius of 150pixels:

    Light

    60|120|150|1|6

    

    

I might do in the future, a simpler version for that.

_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-

To have an event with a shadow:

Write a comment on 2 lines

  Shadow

  arg1

 

arg1, is the maximum height of the object, so if you have a pillar on your map

covering several tiles in height, just create a shadow event at its base, 

and give the height of that pillar as arg1.

 

For characters, just use a height of 0.

 

To turn off/on a light:

Use a script call:

a simple "self.off=true" (to turn off) or "self.off=false" to turn on is needed.

What is important is where you use this script call:

 

If the event switching the light is not the same as the source, you need use the

"call script" command inside the "set move route" command

  (of course, don't forget to say on which event it applies)

instead of the default "call script" command found on page3.

 

==============================================================================

Configuration

==============================================================================

==============================================================================

 You probably won't need to touch this : it's the 'map' of how to display the

 shadow depending on the event's direction and his relative position to the

 source. a minus means the shadow is mirrored. It seems complex, and it is.

 Complain to Enterbrain (why didn't they use something clockwise or counter-

 clockwise ? I suspect it's because of the rm2k legacy. More explanations 

 below.

=============================================================================

=end

SDK.log('DL&S', "trebor777", 1, "16.11.07")

if SDK.state('DL&S')

 

SHADOWS_DIRECTION_ARRAY = Array.new

SHADOWS_DIRECTION_ARRAY[2] = [ -3, 4, -2, 1 ]

SHADOWS_DIRECTION_ARRAY[4] = [ 4, -2, 1, -3 ]

SHADOWS_DIRECTION_ARRAY[6] = [ 1, -3, 4, -2 ]

SHADOWS_DIRECTION_ARRAY[8] = [ -2, 1, -3, 4 ]

 

#==============================================================================

# An important option : if you set it to true, the shadows will get longer if

# you are far from the source. Nice, but induces lag : it will eat your CPU,

# and quite possibly your first born if you try that on a big map.

#============================================================================== 

SHADOW_GETS_LONGER = true

 

#==============================================================================

# Misc options

# If an event has its opacity below SHADOWS_OPACITY_THRESHOLD, no shadow will

# be displayed.

# Set SHADOWS_CATERPILLAR_COMPATIBLE to true if you uses the caterpillar script

#==============================================================================

SHADOWS_OPACITY_THRESHOLD = 254

SHADOWS_CATERPILLAR_COMPATIBLE = true

 

#==============================================================================

# Class Light

#==============================================================================

class Light

  @@lights=[]

  attr_reader :character, :parameters

  #--------------------------------------------------------------------------

  def initialize(viewport,character, param)

    @character = character

    @viewport = viewport

    unless param.nil?

      @parameters = param[0].split('|')

      @anglemin =  @parameters.first.to_i

      @anglemax = @parameters[1].to_i

      @distancemax = @parameters[2].to_i

      @light_height = @parameters[3].to_i

      @base_face_at = @parameters.last.to_i

      @character.direction=@base_face_at

      test = @@lights.find_all{|l| l.character==@character and l.parameters==@parameters}

      if test.size==0

        draw_lights

        update

        @@lights.push(self)

      end

    end

  end

  #--------------------------------------------------------------------------

  def Light.set

    return @@lights

  end

  #--------------------------------------------------------------------------

  def Light.off_size

    result=0

    @@lights.each do |light|

      result+=1 if light.character.off

    end

    return result

  end

  #--------------------------------------------------------------------------

  def dispose

    @s_light.dispose

    @@lights.delete(self)

  end

  #--------------------------------------------------------------------------

  def update

    unless @s_light.nil?

      @s_light.visible=!@character.off

      @s_light.angle=0 if @character.direction==2

      @s_light.angle=-90 if @character.direction==4

      @s_light.angle=180 if @character.direction==8

      @s_light.angle=90 if @character.direction==6

      @s_light.x=@character.screen_x

      @s_light.y=@character.screen_y+32*@light_height

      @s_light.z=@character.screen_z

    end

  end

  #--------------------------------------------------------------------------

  def draw_lights

 

    return if @@lights.include?(self) or (@@lights.find_all{|l| l.character==@character and l.parameters==@parameters}).size>0

    

    radius = @distancemax

    @s_light=Sprite.new(@viewport)

    @s_light.x=@character.screen_x

    @s_light.y=@character.screen_y+32*@light_height

    @s_light.z=@character.screen_z

    @s_light.bitmap=Bitmap.new(radius*2,radius*2)

    @s_light.opacity=90

    @s_light.ox+=radius

    @s_light.oy+=radius

    @s_light.angle=0 if @base_face_at==2

    @s_light.angle=270 if @base_face_at==4

    @s_light.angle=180 if @base_face_at==8

    @s_light.angle=90 if @base_face_at==6

    @s_light.bitmap.draw_pie(radius,radius,radius,Color.new(255,255,100,90),@anglemin, @anglemax)

  end

end

#==============================================================================

# Class shadow

#==============================================================================

class Shadow

  attr_accessor :character

  attr_reader :distance, :distancemax, :overlayed

  @@shadows=[]

  #--------------------------------------------------------------------------

  def initialize(viewport,character, param,light)

    @character = character

    @viewport = viewport

    unless param.nil?

      @parameters = param[0].split('|')

      @shadow_max_height = @parameters[1].to_i

      @anglemin=light.parameters[0].to_f

      @anglemax=light.parameters[1].to_f

      @distancemax=light.parameters[2].to_f

      @light_height= light.parameters[3].to_i

      @source = light

      @s_shadow = RPG::Sprite.new(@viewport)

      @s_shadow.color = Color.new(0, 0, 0)

      update

    end

    @@shadows.push(self)

  end

  #--------------------------------------------------------------------------

  def Shadow.set

    return @@shadows

  end

  #--------------------------------------------------------------------------

  def sprite

    return @s_shadow

  end

  #--------------------------------------------------------------------------

  def dispose

    @s_shadow.dispose

    @@shadows.delete(self)

  end

  #--------------------------------------------------------------------------

  def in_light_range?

    return (@distance<=@distancemax)

  end

  #--------------------------------------------------------------------------

  def overlayed?

    @overlayed =  false

    @@shadows.each do |i|

      s = i.sprite

      next if s.nil? or i == self or @character.tile_id!=0 or s.disposed?

      if (@s_shadow.z)>s.z and @s_shadow.angle.between?(s.angle-1.5,s.angle+1.5)\

       and ((@character.x-i.character.x)**2 + (@character.y-i.character.y)**2)**0.5<=s.zoom_y \

       and s.z>=0

        @s_shadow.visible=false

        @overlayed = true

      end

      return if !@s_shadow.visible

    end

    

    return @overlayed

  end

  #--------------------------------------------------------------------------

  def update

    # set shadow visibility according to the light state

    @s_shadow.visible = !@source.character.off

    if @character.transparent or @character.opacity <= SHADOWS_OPACITY_THRESHOLD

      @s_shadow.visible = false

      return

    end

    if @old_amin.nil? and @old_amax.nil? and @old_dir.nil?

      @old_amin= @anglemin

      @old_amax= @anglemax

      @old_dir = @source.character.direction

    end

    # adapt the angle according to the source direction

    case @source.character.direction

      when 2

        @anglemin= @old_amin+180

        @anglemax= @old_amax+180

      when 4

        @anglemin= @old_amin+90

        @anglemax= @old_amax+90

      when 8

        @anglemin= @old_amin

        @anglemax= @old_amax

      when 6

        @anglemin= @old_amin+270

        @anglemax= @old_amax+270

      end

    if @old_dir!=@source.character.direction

      @old_dir = @source.character.direction

    end

    # simplify the angles if more than 360 or less than 0

    @anglemin%=360 ;@anglemax%=360

    

    tile_height= @shadow_max_height

    @deltax=(@source.character.real_x-@character.real_x)/4

    @deltay= ((@source.character.real_y+@light_height*128)-(@character.real_y+tile_height*128))/4

    @distance = (((@deltax ** 2) + (@deltay ** 2))** 0.5)

    if @distancemax !=0 and @distance>@distancemax

      @s_shadow.visible = false

      return

    end

    

    @s_shadow.angle = 57.3*Math.atan2(@deltax, @deltay )

    @angle_trigo= (@s_shadow.angle+90) % 360

    

    #test if there is a shadow above it, from something close,and then 

    # don't display its shadow

    return if overlayed?

    

    if @anglemin !=0 or @anglemax !=0

      if (@angle_trigo<@anglemin or @angle_trigo>@anglemax) and \

          @anglemin<@anglemax

        @s_shadow.visible = false

        return

      elsif (@angle_trigo<@anglemin and @angle_trigo>@anglemax) and \

             @anglemin>@anglemax

        @s_shadow.visible = false

        return

      end     

    end

    @s_shadow.update

    if @tile_id != @character.tile_id or

       @character_name != @character.character_name or

       @character_hue != @character.character_hue

       @tile_id = @character.tile_id

      @character_name = @character.character_name

      @character_hue = @character.character_hue

      if @tile_id >= 384

        @s_shadow.bitmap = RPG::Cache.tile($game_map.tileset_name,

        @tile_id, @character.character_hue)

        @s_shadow.src_rect.set(0, 0, 32, 32)

        @s_shadow.ox = 16

        @s_shadow.oy = 32

      else

        @s_shadow.bitmap = RPG::Cache.character(@character.character_name,

          @character.character_hue)

        @cw = @s_shadow.bitmap.width / 4

        @ch = @s_shadow.bitmap.height / 4

        @s_shadow.ox = @cw / 2

        @s_shadow.oy = @ch

      end

    end

    @s_shadow.x = @character.screen_x

    @s_shadow.y = @character.screen_y-8

    @s_shadow.z = @character.screen_z(@ch)-1

    

    if @tile_id!=0 # if the sprite graphic is from the tileset

      # set the Z-Index using the tileset priority settings

      @s_shadow.z = ($game_map.priorities[@tile_id])*32

      # convert the shadow angle, into 8-directions (0-7)

      direction_shadow=((@s_shadow.angle/45+45/2.0+90).round)%8

      # for the middle-Top and top layers,

      for i in [1, 2]

        # get the tile from the converted angle

        tile_around=[$game_map.data[@character.x,@character.y-1,i],

        $game_map.data[@character.x-1,@character.y-1,i],

        $game_map.data[@character.x-1,@character.y,i],

        $game_map.data[@character.x-1,@character.y+1,i],   

        $game_map.data[@character.x,@character.y+1,i],

        $game_map.data[@character.x+1,@character.y+1,i],

        $game_map.data[@character.x+1,@character.y,i],

        $game_map.data[@character.x+1,@character.y-1,i]]

        # if the tile is the empty one go to the next layer

        next if tile_around[direction_shadow]==0

        # else, lower the Z-index if the tile around is "above" or at the same 

        # priority of our tile

        @s_shadow.z-=32 if $game_map.priorities[tile_around[direction_shadow]]>=$game_map.priorities[@tile_id]

      end

    end

    if @tile_id == 0

      sx = @character.pattern * @cw

      quarter = ((@angle_trigo/90+0.5).floor)%4

      

      # The quarter is the position of the event relative to the source.

      # Imagine the source is the o point (0,0). Trace the 2 lines

      # y=x and y=-x : you get something like a big X

      # On the right, quarter=0. Up, quarter = 1, and so on

      # Take the @character.direction row (2,4,6,8), and the quarter

      # column (0,1,2,3) (remember, it starts at 0), and you'll get

      # a number between 1 and 4. It correspond to the row of the charset

      # the shadow will be, and mirrored if negative.

      # Yes, it isn't obvious, but I didn't find any simple operation to

      # get those.

      magic = SHADOWS_DIRECTION_ARRAY[@character.direction][quarter]

      magic = -magic

      if magic < 0

        @s_shadow.mirror = true

        magic = -magic

      else

        @s_shadow.mirror = false

      end

      sy = (magic-1)*@ch

      @s_shadow.src_rect.set(sx, sy, @cw, @ch)

    end

    # This is the formula of the opacity in function of the distance

    # ** 2 means square

    @s_shadow.opacity = 1200/((@distance ** 2)/ 1000 + 6)

    # This is the formula of the size in function of the distance

    # The 0.75 is here so you have a size of 1:1 when next to the source.

    @s_shadow.zoom_y=0.75*(@shadow_max_height+1) + (@distance) / 256 if SHADOW_GETS_LONGER

  end

end

#============================================================================== 

# ** Zlib     

#==============================================================================

 

module Zlib

  #============================================================================ 

  # ** Png_File     

  #============================================================================

 

  class Png_File < GzipWriter

    #--------------------------------------------------------------------------

    # * Make PNG

    #--------------------------------------------------------------------------

    def make_png(bitmap, mode = 0)

      # Save Bitmap & Mode

      @bitmap, @mode = bitmap, mode

      # Create & Save PNG

      self.write(make_header)

      self.write(make_ihdr)

      self.write(make_idat)

      self.write(make_iend)

    end

    #--------------------------------------------------------------------------

    # * Make Header

    #--------------------------------------------------------------------------

    def make_header

      return [0x89, 0x50, 0x4e, 0x47, 0x0d, 0x0a, 0x1a, 0x0a].pack('C*')

    end

    #--------------------------------------------------------------------------

    # * Make IHDR

    #--------------------------------------------------------------------------

    def make_ihdr

      ih_size               = [13].pack("N")

      ih_sign               = 'IHDR'

      ih_width              = [@bitmap.width].pack('N')

      ih_height             = [@bitmap.height].pack('N')

      ih_bit_depth          = [8].pack('C')

      ih_color_type         = [6].pack('C')

      ih_compression_method = [0].pack('C')

      ih_filter_method      = [0].pack('C')

      ih_interlace_method   = [0].pack('C')

      string = ih_sign + ih_width + ih_height + ih_bit_depth + ih_color_type +

               ih_compression_method + ih_filter_method + ih_interlace_method

      ih_crc = [Zlib.crc32(string)].pack('N')

      return ih_size + string + ih_crc

    end

    #--------------------------------------------------------------------------

    # * Make IDAT

    #--------------------------------------------------------------------------

    def make_idat

      header  = "\x49\x44\x41\x54"

      data    = @mode == 0 ? make_bitmap_data0 : make_bitmap_data1

      data    = Zlib::Deflate.deflate(data, 8)

      crc     = [Zlib.crc32(header + data)].pack('N')

      size    = [data.length].pack('N')

      return size + header + data + crc

    end

    #--------------------------------------------------------------------------

    # * Make Bitmap Data 0

    #--------------------------------------------------------------------------

    def make_bitmap_data0

      gz = Zlib::GzipWriter.open('hoge.gz')

      t_Fx = 0

      w = @bitmap.width

      h = @bitmap.height

      data = []

      for y in 0...h

        data.push(0)

        for x in 0...w

          t_Fx += 1

          if t_Fx % 10000 == 0

            Graphics.update

          end

          if t_Fx % 100000 == 0

            s = data.pack("C*")

            gz.write(s)

            data.clear

          end

          color = @bitmap.get_pixel(x, y)

          red = color.red

          green = color.green

          blue = color.blue

          alpha = color.alpha

          data.push(red)

          data.push(green)

          data.push(blue)

          data.push(alpha)

        end

      end

      s = data.pack("C*")

      gz.write(s)

      gz.close   

      data.clear

      gz = Zlib::GzipReader.open('hoge.gz')

      data = gz.read

      gz.close

      File.delete('hoge.gz')

      return data

    end

    #--------------------------------------------------------------------------

    # * Make Bitmap Data Mode 1

    #--------------------------------------------------------------------------

    def make_bitmap_data1

      w = @bitmap.width

      h = @bitmap.height

      data = []

      for y in 0...h

        data.push(0)

        for x in 0...w

          color = @bitmap.get_pixel(x, y)

          red = color.red

          green = color.green

          blue = color.blue

          alpha = color.alpha

          data.push(red)

          data.push(green)

          data.push(blue)

          data.push(alpha)

        end

      end

      return data.pack("C*")

    end

    #--------------------------------------------------------------------------

    # * Make IEND

    #--------------------------------------------------------------------------

    def make_iend

      ie_size = [0].pack('N')

      ie_sign = 'IEND'

      ie_crc  = [Zlib.crc32(ie_sign)].pack('N')

      return ie_size + ie_sign + ie_crc

    end

  end

end

#==============================================================================

# Class Game Event

#==============================================================================

class Game_Event

  alias treb_mobile_source_game_event_initialize initialize

  attr_accessor :off, :direction

  def initialize(*args)

    # create the off attribute, only used for the lights

    @off = false

    treb_mobile_source_game_event_initialize(*args)

  end

end

#==============================================================================

# class Spriteset Map

#==============================================================================

class Spriteset_Map

  alias trebor777_DLS_spriteset_map_init_characters init_characters

  alias trebor777_DLS_spriteset_map_update_character_sprites update_character_sprites

  alias trebor777_DLS_spriteset_map_dispose dispose

  #--------------------------------------------------------------------------

  def init_characters

    trebor777_DLS_spriteset_map_init_characters

    # create the lights and shadows arrays

    @lights = []

    @shadows = []

    @viewport1.visible=false

    @viewport2.visible=false

    @viewport3.visible=false

    for i in $game_map.events.keys.sort

      # Search for light trigger

      light_param = SDK.event_comment_input($game_map.events[i], 1, "Light")

      # if not found go to the next iteration

      next if light_param.nil?

      # else add it to the Lights Hash, and create a new light

      @lights.push( Light.new(@viewport1,$game_map.events[i],light_param) )

      # create the shadow for the player.

      @shadows.push( Shadow.new(@viewport1,$game_player, ['0'], @lights.last) )

    end

    for i in $game_map.events.keys.sort

      for light in @lights

        # Search for shadow trigger

        shadow_param = SDK.event_comment_input($game_map.events[i], 1, "Shadow")

        next if shadow_param.nil? 

        @shadows.push( Shadow.new(@viewport1,$game_map.events[i], shadow_param, light) )

      end

    end

    @viewport1.visible=true

    @viewport2.visible=true

    @viewport3.visible=true

  end

  #--------------------------------------------------------------------------

  def update_character_sprites

    trebor777_DLS_spriteset_map_update_character_sprites

    lights_off = 0

    # Update the lights

    for light in @lights

      light.update

      # count the number of lights off

      lights_off+=1 if light.character.off

    end

    # Update the Shadows

    for shade in @shadows

      shade.update

    end

    if @lights.size>0

      # updating screen tinting according to the number of lights on

      value=((lights_off.to_f/@lights.size)*(-180)).round

      $game_screen.start_tone_change(Tone.new(value,value,value,value), 1)

    else

      $game_screen.start_tone_change(Tone.new(0,0,0,0), 1)

    end

  end

 #--------------------------------------------------------------------------

  def dispose

    for light in @lights

      light.dispose

    end

    # Update the Shadows

    for shade in @shadows

      shade.dispose

    end

    @lights = []

    @shadows = []

  end

end

#==============================================================================

# Class Bitmap

#==============================================================================

class Bitmap

  #--------------------------------------------------------------------------

  def draw_line(x1, y1, x2, y2, width = 1, color = Color.new(255, 255, 255))

    # Return if width is less than or 0

    return if width <= 0

    # Reverse all parameters sent if 2 x is less than the first x

    x1, x2, y1, y2 = x2, x1, y2, y1 if x2 < x1    

    # Get S (1/2 width)

    s = width / 2.0

    # If X Coordinates are equal

    if x1 == x2

      # Draw Vertical line

      fill_rect(x1 - s, [y1, y2].min, width, (y2 - y1).abs, color) 

    # If Y Coordinates are equal

    elsif y1 == y2

      # Draw Horizontal line

      fill_rect(x1, y1 - s, x2 - x1, width, color) 

    end

    # Get Length

    length = x2 - x1 < (y2 - y1).abs ? (y2 - y1).abs : x2 - x1

    # Get Increments

    x_increment, y_increment = (x2 - x1) / length.to_f, (y2 - y1) / length.to_f

    # Get Current X and Y

    x, y = x1, y1

    # While Current X is less than end X

    while x < x2

      # Draw Box of width width and width height 

      fill_rect(x-s, y-s, width, width, color)

      # Increment X and Y

      x += x_increment

      y += y_increment

    end

  end

  #--------------------------------------------------------------------------

  # Draw pie, take quite a long time as it draws each line.

  #--------------------------------------------------------------------------

  def draw_pie(x,y,radius,color = Color.new(255, 255, 255, 255),start_angle=0,end_angle=360)

    end_angle+=360 if end_angle<start_angle

    name_string="#{radius}_#{start_angle}_#{end_angle}"

    #filename="Graphics/Pictures/#{name_string}.png"

    if FileTest.exist?("Graphics/Pictures/#{name_string}.png")

      temp = RPG::Cache.picture(name_string)

      blt(0,0,temp,temp.rect)

    else

      Graphics.transition

      t = Progress_Bar.new(160,240,320,20,end_angle-start_angle+2 )

      for i in start_angle...end_angle

        t.current_step+=1

        t.update

        Graphics.update

        for j in 0..2

          x_=(Math::cos((i+j/2.0)*Math::PI/180)*radius).round+x

          y_=(Math::sin((i+j/2.0)*Math::PI/180)*radius).round+y

          draw_line(x, y, x_, y_, 2,color)

        end

      end

      t.current_step+=1

      t.update

      Graphics.update

      make_png(name_string, 'Graphics/Pictures/')

      t.current_step+=1

      t.update

      Graphics.update

      t.dispose

    end

  end

  def make_png(name = 'like', path = '', mode = 0)

    Dir.make_dir(path) if path != '' and !FileTest.directory?(path)

    Zlib::Png_File.open('temp.gz')   { |gz| gz.make_png(self, mode) }

    Zlib::GzipReader.open('temp.gz') { |gz| $read = gz.read }

    f = File.open(path + name + '.png', 'wb')

    f.write($read)

    f.close

    File.delete('temp.gz')

  end

end

 

class Progress_Bar < Sprite

  #--------------------------------------------------------------------------

  # * Public Instance Variables

  #--------------------------------------------------------------------------

  attr_accessor :current_step   # The Current Step

  attr_accessor :steps          # The max amount of steps

  #----------------------------------------------------------------------------

  # * Initialize Object

  #----------------------------------------------------------------------------

  def initialize(x,y,width,height=16,steps=100,start=0)

    super()

    @steps = steps

    self.x = x

    self.y = y

    @current_step= start

    @width = width

    @height = height

    @w = 9

    @nb_bars = @width/@w

    @c1 = Color.new(46,211,49,255)

    @c2 = Color.new(46,211,49,227)

    @c3 = Color.new(46,211,49,202)

    @c4 = Color.new(46,211,49,177)

    @c5 = Color.new(46,211,49,152)

    @c6 = Color.new(46,211,49,127)

    @stretch_c = (@height-4)/16.0

    self.bitmap = Bitmap.new(@width, @height)

    self.bitmap.clear

    self.bitmap.fill_rect(0, 0, @width, @height, Color.new(59,59,59,167))

    draw

  end

  #----------------------------------------------------------------------------

  # * Draw Bar

  #----------------------------------------------------------------------------

  def draw

    self.bitmap.fill_rect(1, 1, @width-2, @height-2, Color.new(59,59,59,0))

    for i in 0...((@current_step/@steps.to_f)*@nb_bars).round

      self.bitmap.fill_rect(i*@w+1,2,@w-2,@height-4,@c6)

      self.bitmap.fill_rect(i*@w+1,3*@stretch_c,@w-2,@height-6*@stretch_c,@c5)

      self.bitmap.fill_rect(i*@w+1,4*@stretch_c,@w-2,@height-8*@stretch_c,@c4)

      self.bitmap.fill_rect(i*@w+1,5*@stretch_c,@w-2,@height-10*@stretch_c,@c3)

      self.bitmap.fill_rect(i*@w+1,6*@stretch_c,@w-2,@height-12*@stretch_c,@c2)

      self.bitmap.fill_rect(i*@w+1,7*@stretch_c,@w-2,@height-14*@stretch_c,@c1)

    end

    @old = @current_step

  end

  #----------------------------------------------------------------------------

  # * Update

  #----------------------------------------------------------------------------

  def update

    draw if @current_step != @old

  end

end

#SDK test

end

 

Instructions
Everything is explained in the comments.

FAQ

Why is it so long when i'm starting to play, or going to another map?
- That's because of the time needed to draw the lights. I'm sorry about that...I need a real fast method to draw lines... So don't abuse of lights lol
and it's not to annoying as it's only a loading time, instead of slow down during gameplay.

I might make a Loading screen for that! XD

Compatibility

Require The SDK, whatever the version.

Credits and Thanks

Rataime's for his script, Learned a lot^^.
MACL stuff,but I only use one method, so I didn't make it required.

Author's Notes
I'm thinking of doing an easier version for the light settings. Remind me if I forgot!




Terms and Conditions

Use it as you want!
 
Not bad. The video is very impressive. I see a little metal gear action going on eh? Or maybe splinter cell. I don't know. But I'm very interested to see your other work. I gotta try this out and see how it actually works. But great job from what I've seen!
 
Hum yeah the video is made from a project request from a customer, named Badmonur.
That's why I need to do a proper Demo for this script!^^
 
But will this work with the sdk 1.5? Because I'm using Caldron's ABS and yeah I don't know how to switch it up from 1.5 to 2.3.

edit: well it works but for some odd reason the screen flashes like crazy. I mean its nice and easy to use but is there a way to keep it from flickering like that? Just curious if so I will be using this for sure.
 
arf, I was wrong lol actually

It should work with all versions of the SDK lol
I thought that the aliased methods I used, were only in the v2.xx
 
Well I can't really explain it but if you get the Evergore demo in Caldrons ABS and insert your script in there you'll see the screen flicker. Its really odd because it doesn't happen in Mr.Mo's ABS but it does in that one so I don't know whats the deal there.
 
I must say it looks fine on my computer...
I just tested the caldaron's Evergore demo, and no problem.

But it poped up a bug lol, when i tried without any light lol, it crash I need to fix that lol.
EDIT, fixed! Script updated.
 
Seems like a really good lighting script, but I have one question, is it possible to set it so that the hero is the one casting the light? I mean, for example the hero has a lantern or flashlight on them is this possible with the current script or could it even be done?
 
oh, lol, I didn't think to that one, lol even if it's a quite obvious thing.
Hum, nope, there is no way for the moment to make the game_player as a source.

But It's a usefull feature to include in the next version!
And, hum, I think... it could be done quite easily.

About the video, lol it's seems laggy because of the capture software... it does the same thing on other video i created... when moving the mouse for example, it dropped the frame rate, and if it's just recording it remove only like 5 or 6 fps.
else the script only creates long loading time between maps.

it would be perfect to create the same kind of effects of your static lighting script...( like having a gradient light "halo" thing)

XD I must that I never had so much replies so quickly after posting a script XD

May I remind you of the wonderful "Edit" button? ;p - arevulopapo
 
try this one:
http://rmxp.trebor777.net/rmxp/Dynamic Light and Shadow.wmv


EDIT: Big News!
I just found a nice solution to the "slow loading times" problem...
Basically, it only draw the bitmap one time, so it doesn't have to create it each time.
Instead a png file is created if not found. If found, the file is loaded. So loading times only happen the first time you load the map.

Moreover, it means, that, if the game creator is nice, he will play his game one time to create all the lights file, and then create the game archive. Like this, the players won't be affected by this problem.
 
O_o??
is your event is supposed to follow the player?? Check Please...

Big News!
I just found a nice solution to the "slow loading times" problem...
Basically, it only draw the bitmap one time, so it doesn't have to create it each time.
Instead a png file is created if not found. If found, the file is loaded. So loading times only happen the first time you load the map.

Moreover, it means, that, if the game creator is nice, he will play his game one time to create all the lights file, and then create the game archive. Like this, the players won't be affected by this problem.

EDIT: Solution Done, I've also included a small loading bar,
The script on the first page will be updated soon.
 
O_o??
hum, explain me everything you did,
script used etc;.;
a demo (would be easier)

Have you tried with the updated script I just posted with the Demo?
 

Thank you for viewing

HBGames is a leading amateur video game development forum and Discord server open to all ability levels. Feel free to have a nosey around!

Discord

Join our growing and active Discord server to discuss all aspects of game making in a relaxed environment. Join Us

Content

  • Our Games
  • Games in Development
  • Emoji by Twemoji.
    Top