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.

Drawing thicklines

EJlol

Member

I'm trying to draw a straight thick line. To do that the easiest way is to use some code that look like this:
Code:
    def drawLine(x1, y1, x2, y2, width = 1)

      # 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

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

      # If Y Coordinates are equal

      elsif y1 == y2

        # Draw Horizontal line

        drawSquare(x1, y1 - s, x2 - x1, width) 

      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 

        drawSquare(x-s, y-s, width, width)

        # Increment X and Y

        x += x_increment

        y += y_increment

      end

    end

However for my current project it comes with 2 problems. The first actually just a disadvantage, it's very ineffecient and slow. The second problem I have is that most pixels are actually drawn multiple times.

Example:
I'm trying to draw some rocks on the floor in a straight thick line, however it should only be drawn 50% of the time, so that not the whole floor is filled with rocks. While drawing this, the following will happen if a pixel is drawn more than once:

First time the chance will be 50%
Second time the chance will be 50% it has been drawn the first time, and again 50% it will be drawn this time. (= 75%)
Third time it will be 87,5%

I hope you understand why I want pixels only to be drawn once. The following Algorithm explains how to draw a thick line:
http://homepages.enterprise.net/murphy/ ... index.html

It uses the Bresenham's line algorithm. It draws multiple parralel lines, in a way that it looks like one thick line. The website provides some explanation, notes and a example code in Pascal.

Sadly I don't understand Pascal at all. Not only that he uses variable names like u, v, p, and q which doesn't help me at all.

I'm able to draw single straight lines, but it's impossible for me to draw thicklines. If anyone would be able to help I would be really happy. I included some code that I use to test my drawing function. If a pixel is drawn, it will turn green, if it's drawn twice or more, it will turn red.

Code:
class Bitmap

  def draw(x, y)

    if get_pixel(x, y) == Color.new(0, 255, 0) 

      set_pixel(x, y, Color.new(255, 0, 0))

    else

      set_pixel(x, y, Color.new(0, 255, 0))

    end

  end

  

  def fill

    for x in 0...self.width

      for y in 0...self.height

        draw(x, y)

      end

    end

  end

  

  def drawSingleLine(x1, y1, x2, y2, f = 0)

    dx = x2 - x1

    dy = y2 - y1

    

    if dx >= 0

      stepx = 1

    else

      stepx = -1

      dx = dx.abs

    end

 

    if dy >= 0

      stepy = 1

    else

      stepy = -1

      dy = dy.abs

    end

    

    dx *= 2

    dy *= 2

    

    draw(x1, y1)

    

    if dx >= dy

      fraction = 2 * dy - dx

      while x1 != x2

        if fraction >= 0

          y1 += stepy

          fraction -= dx

        end

        x1 += stepx

        fraction += dy

        draw(x1, y1)

      end

    else

      fraction = 2 * dx - dy

      while y1 != y2

        if fraction >= 0

          x1 += stepx

          fraction -= dy

        end

        y1 += stepy

        fraction += dx

        draw(x1, y1)

      end

    end

  end

  

  def drawLine(x1, y1, x2, y2, width)

    dx = x2 - x1

    dy = y2 - y1

    drawSingleLine(x1, y1, x2, y2)

  end

end

 

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

# ** Scene_Paint

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

#  This class performs title screen processing.

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

 

class Scene_Paint

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

  # * Main Processing

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

  def main

    # If battle test

    if $BTEST

      battle_test

      return

    end

    # Load database

    $data_actors        = load_data("Data/Actors.rxdata")

    $data_classes       = load_data("Data/Classes.rxdata")

    $data_skills        = load_data("Data/Skills.rxdata")

    $data_items         = load_data("Data/Items.rxdata")

    $data_weapons       = load_data("Data/Weapons.rxdata")

    $data_armors        = load_data("Data/Armors.rxdata")

    $data_enemies       = load_data("Data/Enemies.rxdata")

    $data_troops        = load_data("Data/Troops.rxdata")

    $data_states        = load_data("Data/States.rxdata")

    $data_animations    = load_data("Data/Animations.rxdata")

    $data_tilesets      = load_data("Data/Tilesets.rxdata")

    $data_common_events = load_data("Data/CommonEvents.rxdata")

    $data_system        = load_data("Data/System.rxdata")

    # Make system object

    $game_system = Game_System.new

    # Make title graphic

    @sprite = Sprite.new

    @sprite.bitmap = Bitmap.new(640, 480)

    @sprite.bitmap.drawLine(32,300,500,400, 32)

    # Stop playing ME and BGS

    Audio.me_stop

    Audio.bgs_stop

    # Execute transition

    Graphics.transition

    # Main loop

    loop do

      # Update game screen

      Graphics.update

      # Update input information

      Input.update

      # Abort loop if screen is changed

      if $scene != self

        break

      end

    end

    # Prepare for transition

    Graphics.freeze

    # Dispose

    @sprite.bitmap.dispose

    @sprite.dispose

  end

end
 
First of all, it this just meant to work in RM and / or also on other platforms / applications?

BTW remember that in Ruby and RGSS you use underscores in method names instead of CamelCase.
 

EJlol

Member

I will use it for RMXP, though I'm sure it can also be used for other ruby platforms.
as for the method names, its cause I mainly program in Java and C#, both don't use the underscore :P
 

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