What? A map editor for Cptn. Ruby.
Why? Because.
No, seriously, why? Because I needed to have a starting project.
Current version? Version 1.0
Screenshots?Sure:
Should we credit you if we use this?Yeah! It's not much, but I've made this script; and no-one should get credit where it's not due..
So, just credit me, AmIMeYet, if you use this..
Requirements?Ruby
Gosu
The Cptn. Ruby example (comes with gosu, in the 'example' directory)
How do I install it?Put the script inside the folder you've got the Cptn. Ruby example in, and run it.
How do I use it?Use buttons 1-4 to select the Earth, Grass, Gem and Erase tiles.
The current selection will be placed in the title bar, along with the tile currently hovering over.
Click with the left mouse button to apply the currently selected tile to the map.
Press S to save, and overwrite the default map file (so back that one up!)
Any bugs?If you launch the editor, and then go do something else on your computer, it crashes.. so always SAVE.
And the code?Here you go:
http://amimeyet.890m.com/misc/editor.txtOr if that's down:
=begin
An editor for the oh so popular game 'Cptn. Ruby'!
Made by AmIMeYet
Version 1.0
Buttons:
Left Mouse Button: Add Tile
1: Select Earth (#)
2: Select Grass (")
3: Select Gem (x)
4: Erase
S: Save map (overwrite)
=end
#media/Editor Tileset.png -> CptnRuby Tileset.png
# -> CptnRuby.png
# Editor Gem -> CptnRuby Gem.png
begin
# In case you use Gosu via rubygems.
require 'rubygems'
rescue LoadError
# In case you don't.
end
require 'gosu'
include Gosu
# Module tiles defines the types of tile
module Tiles
Grass = 0
Earth = 1
end
# CollectibleGem is a class to show gems
class CollectibleGem
attr_reader :x, :y
def initialize(image, x, y)
@image = image
@x, @y = x, y
end
def draw(screen_x, screen_y)
@image.draw(@x - screen_x - 5, @y - screen_y -5, 0, 0.5, 0.5)
#-5 == offset#
end
end
# MousePointer class adds a nice little cursor to the window
class MousePointer
attr_reader :x, :y
def initialize(window, image)
@image = Image.new(window, image, false)
@x = window.mouse_x
@y = window.mouse_y
end
def draw(window)
@image.draw($edwin.mouse_x, $edwin.mouse_y, 0)
end
end
# Map class holds and draws tiles and gems.
class Map
attr_reader :width, :height, :gems, :tiles
def initialize(window, filename)
# Load 60x60 tiles, 5px overlap in all four directions.
@tileset = Image.load_tiles(window, "media/CptnRuby Tileset.png", 60, 60, true)
@sky = Image.new(window, "media/Space.png", true)
gem_img = Image.new(window, "media/CptnRuby Gem.png", false)
@gems = []
$lines = File.readlines(filename).map { |line| line.chop }
@height = $lines.size
@width = $lines[0].size
@tiles = Array.new(@width) do |x|
Array.new(@height) do |y|
case $lines[y][x, 1]
when '"'
Tiles::Grass
when '#'
Tiles::Earth
when 'x'
@gems.push(CollectibleGem.new(gem_img, x * 20 + 5, y * 20 + 5)) # 5 > 25
nil
else
nil
end
end
end
end
def reload
@height = $lines.size
@width = $lines[0].size
gem_img = Image.new($edwin, "media/CptnRuby Gem.png", false)
@gems = []
@tiles = Array.new(@width) do |x|
Array.new(@height) do |y|
case $lines[y][x, 1]
when '"'
Tiles::Grass
when '#'
Tiles::Earth
when 'x'
@gems.push(CollectibleGem.new(gem_img, x * 20 + 5, y * 20 + 5)) # 5 > 25
nil
else
nil
end
end
end
end
def draw(screen_x, screen_y)
# Sigh, stars!
@sky.draw(0, 0, 0)
# Very primitive drawing function:
# Draws all the tiles, some off-screen, some on-screen.
@height.times do |y|
@width.times do |x|
tile = @tiles[x][y]
if tile
# Draw the tile with an offset (tile images have some overlap)
# Scrolling is implemented here just as in the game objects.
@tileset[tile].draw(x * 20 - screen_x - 5, y * 20 - screen_y - 5, 0, 0.5, 0.5)
end
end
end
@gems.each { |c| c.draw(screen_x, screen_y) }
end
# Solid at a given pixel position?
def solid?(x, y)
y < 0 || @tiles[x / 20][y / 20]
end
end
# Ted class handles editing functions
class Ted
attr_reader :type
def initialize
@type = "#"
end
def save
file = File.new("media/CptnRuby Map.txt", "w+")
file.puts($lines)
file.close
end
def load
$edwin.map.reload
end
def set_type(btn)
case btn
when "1"
@type = "#"
when "2"
@type = "\""
when "3"
@type = "x"
else
@type = "."
end
end
def clicked(sx, sy)
mx = $edwin.mouse_x
my = $edwin.mouse_y
ry = ((sy + my) / 20).floor
rx = ((sx + mx) / 20).floor
$lines[ry][rx] = @type
load
end
end
# The Game class is the main window
class Game < Window
attr_reader :map
attr_reader :mouse
WIDTH = 640
HEIGHT = 480
def initialize
super(WIDTH , HEIGHT, false)
self.caption = "Cptn. Ruby"
@map = Map.new(self, "media/CptnRuby Map.txt")
@mouse = MousePointer.new(self, "media/cursor.png")
@ted = Ted.new
# Scrolling is stored as the position of the top left corner of the screen.
@screen_x = @screen_y = 0
@font = Gosu::Font.new(self, Gosu::default_font_name, 20)
end
def update
move_x = 0
move_x -= 5 if atedge?("left")
move_x += 5 if atedge?("right")
move_y = 0
move_y -= 5 if atedge?("up")
move_y += 5 if atedge?("down")
tempscreen_x = @screen_x + move_x
tempscreen_y = @screen_y + move_y
if tempscreen_x <= 0
tempscreen_x = 0
elsif tempscreen_x >= @map.width * 20 - WIDTH
tempscreen_x = @map.width * 20 - WIDTH
end
if tempscreen_y <= 0
tempscreen_y = 0
elsif tempscreen_y >= @map.height * 20 - HEIGHT
tempscreen_y = @map.height * 20 - HEIGHT
end
@screen_x = tempscreen_x
@screen_y = tempscreen_y
cx = ((@screen_x + mouse_x) / 20).floor
cy = ((@screen_y+ mouse_y) / 20).floor
case @ted.type
when '#'
ct = "Earth"
when '"'
ct = "Grass"
when 'x'
ct = "Diamond"
when '.'
ct = "Erase"
end
self.caption = "Capt. Ruby - Editor (#{cx}; #{cy}; #{ct})"
end
def draw
@map.draw @screen_x, @screen_y
@mouse.draw self
@font.draw(@message, 10, 10, 999, 1.0, 1.0, 0xffffff00)
end
def button_down(id)
if id == Button::KbEscape then close end
if id == Button::Kb1 then @ted.set_type("1") end
if id == Button::Kb2 then @ted.set_type("2") end
if id == Button::Kb3 then @ted.set_type("3") end
if id == Button::Kb4 then @ted.set_type("4") end
if id == Button::MsLeft then @ted.clicked(@screen_x, @screen_y) end
if id == Button::KbS then @ted.save end
end
def atedge?(dir)
val = false
case dir
when "left"
if mouse_x.between?(0, 20)
val = true
end
when "right"
if mouse_x.between?(620, 6405)
val = true
end
when "up"
if mouse_y.between?(0, 20)
val = true
end
when "down"
if mouse_y.between?(460, 480)
val = true
end
end
return val
end
end
# Set window as new window and show it (edwin == Editor Window)
$edwin = Game.new
$edwin.show
Hey AmiMeYet
Great work with the map editor for Cptn Ruby
though when I ran it the sprites(gems) where not placed where they should have been
they where a bit lower than where they should have been (compared to where they are when you play Cptn Ruby)
so I edited the source code and now it works fine(for me at lease)
please try out the changes Ive made and see what you think
I plan to use the new version of your map editor for my game Arthur's Adventures,hope you don't mind,I will give you full credit of course
Here is the source code for the new version I made
=begin
Originaly an Level Editor for the oh so popular game 'Cptn. Ruby'!
Made by AmIMeYet
Modifyed by Shinobi Chef
Now the Level Editor for Arthur's Adventure
Version 1.1
Buttons:
Left Mouse Button: Add Tile
1: Select Earth (#)
2: Select Grass (")
3: Select Gold (x)
4: Erase
5: Select Blue Shield (s)
S: Save map (overwrite)
=end
#media/Editor Tileset.png -> CptnRuby Tileset.png
# -> CptnRuby.png
# Editor Gold -> CptnRuby Gold.png
begin
# In case you use Gosu via rubygolds.
require 'rubygolds'
rescue LoadError
# In case you don't.
end
require 'gosu'
include Gosu
# Module tiles defines the types of tile
module Tiles
Grass = 0
Earth = 1
end
# CollectibleGold is a class to show golds
class CollectibleGold
attr_reader :x, :y
def initialize(image, x, y)
@image = image
@x, @y = x, y
end
def draw(screen_x, screen_y)
@image.draw(@x - screen_x - 5, @y - screen_y -5, 0, 0.5, 0.5)
#-5 == offset#
end
end
class CollectibleBlueshield
attr_reader :x, :y
def initialize(image, x, y)
@image = image
@x, @y = x, y
end
def draw(screen_x, screen_y)
@image.draw(@x - screen_x - 5, @y - screen_y -5, 0, 0.5, 0.5)
#-5 == offset#
end
end
# MousePointer class adds a nice little cursor to the window
class MousePointer
attr_reader :x, :y
def initialize(window, image)
@image = Image.new(window, image, false)
@x = window.mouse_x
@y = window.mouse_y
end
def draw(window)
@image.draw($edwin.mouse_x, $edwin.mouse_y, 0)
end
end
# Map class holds and draws tiles and golds.
class Map
attr_reader :width, :height, :golds, :tiles, :blueshields
def initialize(window, filename)
# Load 60x60 tiles, 5px overlap in all four directions.
@tileset = Image.load_tiles(window, "media/CptnRuby Tileset.png", 60, 60, true)
@sky = Image.new(window, "media/skybackground.png", true)
gold_img = Image.new(window, "media/gold.png", false)
@golds = []
blueshield_img = Image.new(window, "media/blueshield.png", false)
@blueshields = []
$lines = File.readlines(filename).map { |line| line.chop }
@height = $lines.size
@width = $lines[0].size
@tiles = Array.new(@width) do |x|
Array.new(@height) do |y|
case $lines[y][x, 1]
when '"'
Tiles::Grass
when '#'
Tiles::Earth
when 's'
@blueshields.push(CollectibleBlueshield.new(blueshield_img, x * 25 + 2, y * 25 + 2))
nil
when 'x'
@golds.push(CollectibleGold.new(gold_img, x * 25 + 2 , y * 25 + 2)) # 5 > 25
nil
else
nil
end
end
end
end
def reload
@height = $lines.size
@width = $lines[0].size
gold_img = Image.new($edwin, "media/gold.png", false)
@golds = []
blueshield_img = Image.new($edwin, "media/blueshield.png", false)
@blueshields = []
@tiles = Array.new(@width) do |x|
Array.new(@height) do |y|
case $lines[y][x, 1]
when '"'
Tiles::Grass
when '#'
Tiles::Earth
when 's'
@blueshields.push(CollectibleBlueshield.new(blueshield_img, x * 25 + 2, y * 25 + 2))
nil
when 'x'
@golds.push(CollectibleGold.new(gold_img, x * 25 + 2, y * 25+ 2)) # 5 > 25
nil
else
nil
end
end
end
end
def draw(screen_x, screen_y)
# Sigh, stars!
@sky.draw(0, 0, 0)
# Very primitive drawing function:
# Draws all the tiles, some off-screen, some on-screen.
@height.times do |y|
@width.times do |x|
tile = @tiles[x][y]
if tile
# Draw the tile with an offset (tile images have some overlap)
# Scrolling is implemented here just as in the game objects.
@tileset[tile].draw(x * 25 - screen_x - 5, y * 25 - screen_y - 5, 0, 0.5, 0.5)
end
end
end
@golds.each { |c| c.draw(screen_x, screen_y) }
@blueshields.each { |c| c.draw(screen_x, screen_y) }
end
# Solid at a given pixel position?
def solid?(x, y)
y < 0 || @tiles[x / 25][y / 25]
end
end
# Ted class handles editing functions
class Ted
attr_reader :type
def initialize
@type = "#"
end
def save
file = File.new("maps/level1.txt", "w+")
file.puts($lines)
file.close
end
def load
$edwin.map.reload
end
def set_type(btn)
case btn
when "1"
@type = "#"
when "2"
@type = "\""
when "5"
@type = "s"
when "3"
@type = "x"
else
@type = "."
end
end
def clicked(sx, sy)
mx = $edwin.mouse_x
my = $edwin.mouse_y
ry = ((sy + my) / 25).floor
rx = ((sx + mx) / 25).floor
$lines[ry][rx] = @type
load
end
end
# The Game class is the main window
class Game < Window
attr_reader :map
attr_reader :mouse
WIDTH = 640
HEIGHT = 480
def initialize
super(WIDTH , HEIGHT, false)
self.caption = "Arthur's Adventures - Level Editor"
@map = Map.new(self, "maps/level1.txt")
@mouse = MousePointer.new(self, "media/cursor.png")
@ted = Ted.new
# Scrolling is stored as the position of the top left corner of the screen.
@screen_x = @screen_y = 0
@font = Gosu::Font.new(self, Gosu::default_font_name, 25)
end
def update
move_x = 0
move_x -= 5 if atedge?("left")
move_x += 5 if atedge?("right")
move_y = 0
move_y -= 5 if atedge?("up")
move_y += 5 if atedge?("down")
tempscreen_x = @screen_x + move_x
tempscreen_y = @screen_y + move_y
if tempscreen_x <= 0
tempscreen_x = 0
elsif tempscreen_x >= @map.width * 25 - WIDTH
tempscreen_x = @map.width * 25 - WIDTH
end
if tempscreen_y <= 0
tempscreen_y = 0
elsif tempscreen_y >= @map.height * 25 - HEIGHT
tempscreen_y = @map.height * 25 - HEIGHT
end
@screen_x = tempscreen_x
@screen_y = tempscreen_y
cx = ((@screen_x + mouse_x) / 25).floor
cy = ((@screen_y+ mouse_y) / 25).floor
case @ted.type
when '#'
ct = "Earth"
when '"'
ct = "Grass"
when 's'
ct = "Blue Shield"
when 'x'
ct = "Gold"
when '.'
ct = "Erase"
end
self.caption = "Arthur's Adventures - Level Editor (#{cx}; #{cy}; #{ct})"
end
def draw
@map.draw @screen_x, @screen_y
@mouse.draw self
@font.draw(@message, 10, 10, 999, 1.0, 1.0, 0xffffff00)
end
def button_down(id)
if id == Button::KbEscape then close end
if id == Button::Kb1 then @ted.set_type("1") end
if id == Button::Kb2 then @ted.set_type("2") end
if id == Button::Kb3 then @ted.set_type("3") end
if id == Button::Kb4 then @ted.set_type("4") end
if id == Button::Kb5 then @ted.set_type("5") end
if id == Button::MsLeft then @ted.clicked(@screen_x, @screen_y) end
if id == Button::KbS then @ted.save end
end
def atedge?(dir)
val = false
case dir
when "left"
if mouse_x.between?(0, 25)
val = true
end
when "right"
if mouse_x.between?(620, 6405)
val = true
end
when "up"
if mouse_y.between?(0, 25)
val = true
end
when "down"
if mouse_y.between?(460, 480)
val = true
end
end
return val
end
end
# Set window as new window and show it (edwin == Editor Window)
$edwin = Game.new
$edwin.show
Loading...