Various.
- Map drawing is now possible with custom object-specific drawing code. A few examples have been added, including one that draws borders. Please note that those borders are still not perfect, however, as some inner angles are being rendered with plain/full-tile textures. The drawing code helpers will probably be moved to a location that makes them easy to reuse. - Some of the old map drawing code is still present (in particular in src/main.cr). That code is deprecated and will be removed soon. - WIP Naka::Map::ObjectReference. May or may not remain as it currently is. - Some mapgen updates to match the new drawing methods. - Possibly other minor tweaks or grooming.master
After Width: | Height: | Size: 5.3 KiB |
After Width: | Height: | Size: 5.3 KiB |
After Width: | Height: | Size: 5.3 KiB |
After Width: | Height: | Size: 5.3 KiB |
After Width: | Height: | Size: 5.4 KiB |
After Width: | Height: | Size: 5.2 KiB |
After Width: | Height: | Size: 5.3 KiB |
After Width: | Height: | Size: 5.1 KiB |
After Width: | Height: | Size: 5.3 KiB |
After Width: | Height: | Size: 5.3 KiB |
After Width: | Height: | Size: 5.3 KiB |
After Width: | Height: | Size: 5.3 KiB |
After Width: | Height: | Size: 5.3 KiB |
After Width: | Height: | Size: 5.2 KiB |
After Width: | Height: | Size: 5.3 KiB |
Before Width: | Height: | Size: 5.0 KiB After Width: | Height: | Size: 5.0 KiB |
After Width: | Height: | Size: 5.3 KiB |
After Width: | Height: | Size: 5.3 KiB |
After Width: | Height: | Size: 5.3 KiB |
After Width: | Height: | Size: 5.3 KiB |
After Width: | Height: | Size: 5.3 KiB |
After Width: | Height: | Size: 5.2 KiB |
After Width: | Height: | Size: 5.3 KiB |
After Width: | Height: | Size: 5.1 KiB |
After Width: | Height: | Size: 5.3 KiB |
After Width: | Height: | Size: 5.3 KiB |
After Width: | Height: | Size: 5.3 KiB |
After Width: | Height: | Size: 5.3 KiB |
After Width: | Height: | Size: 5.3 KiB |
After Width: | Height: | Size: 5.2 KiB |
After Width: | Height: | Size: 5.2 KiB |
Before Width: | Height: | Size: 5.1 KiB After Width: | Height: | Size: 5.1 KiB |
182
src/main.cr
|
@ -4,9 +4,7 @@ require "json"
|
||||||
require "./naka.cr"
|
require "./naka.cr"
|
||||||
|
|
||||||
class ImagesLoader
|
class ImagesLoader
|
||||||
getter grass : SDL::Texture
|
|
||||||
getter stone : SDL::Texture
|
getter stone : SDL::Texture
|
||||||
getter dirt : SDL::Texture
|
|
||||||
getter tree : SDL::Texture
|
getter tree : SDL::Texture
|
||||||
getter pine : SDL::Texture
|
getter pine : SDL::Texture
|
||||||
getter flowers : SDL::Texture
|
getter flowers : SDL::Texture
|
||||||
|
@ -16,9 +14,7 @@ class ImagesLoader
|
||||||
getter rocks : SDL::Texture
|
getter rocks : SDL::Texture
|
||||||
|
|
||||||
def initialize(window)
|
def initialize(window)
|
||||||
@grass = window.newImage "assets/grass.png"
|
|
||||||
@stone = window.newImage "assets/stone.png"
|
@stone = window.newImage "assets/stone.png"
|
||||||
@dirt = window.newImage "assets/dirt.png"
|
|
||||||
@tree = window.newImage "assets/tree.png"
|
@tree = window.newImage "assets/tree.png"
|
||||||
@flowers = window.newImage "assets/flowers.png"
|
@flowers = window.newImage "assets/flowers.png"
|
||||||
@sand = window.newImage "assets/sand.png"
|
@sand = window.newImage "assets/sand.png"
|
||||||
|
@ -38,6 +34,114 @@ images = ImagesLoader.new window
|
||||||
connection_font = window.newFont "assets/connection.otf", 30.5
|
connection_font = window.newFont "assets/connection.otf", 30.5
|
||||||
window.set_font connection_font
|
window.set_font connection_font
|
||||||
|
|
||||||
|
def simple_tile_drawer(window : Naka::Window, tile_path : String)
|
||||||
|
texture = window.newImage tile_path
|
||||||
|
|
||||||
|
->(map : Naka::Map, x : Int32, y : Int32, z : Int32, tile : Naka::Map::Tile, object : Naka::Map::Object, draw_x : Int32, draw_y : Int32, zoom : Float64){
|
||||||
|
window.draw texture, draw_x, draw_y, scale_x: zoom, scale_y: zoom
|
||||||
|
nil
|
||||||
|
}
|
||||||
|
end
|
||||||
|
|
||||||
|
def bordered_tile_drawer(window : Naka::Window, base_tile_path : String)
|
||||||
|
# FIXME: Both excessive, insufficient, and broken.
|
||||||
|
|
||||||
|
mod = [
|
||||||
|
"trbl",
|
||||||
|
"-rbl",
|
||||||
|
"t-bl",
|
||||||
|
"tr-l",
|
||||||
|
"trb-",
|
||||||
|
"t-b-",
|
||||||
|
"-r-l",
|
||||||
|
"tr--",
|
||||||
|
"-rb-",
|
||||||
|
"--bl",
|
||||||
|
"t--l",
|
||||||
|
"t---",
|
||||||
|
"-r--",
|
||||||
|
"--b-",
|
||||||
|
"---l",
|
||||||
|
"----"
|
||||||
|
]
|
||||||
|
|
||||||
|
textures = Hash(String, SDL::Texture).new
|
||||||
|
|
||||||
|
mod.each do |s|
|
||||||
|
begin
|
||||||
|
textures[s] = window.newImage base_tile_path.sub /{}/, "-" + s
|
||||||
|
rescue
|
||||||
|
# Not even sure we should be doing something here…
|
||||||
|
# Maybe in the future, in debug mode?
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
->(map : Naka::Map, x : Int32, y : Int32, z : Int32, tile : Naka::Map::Tile, object : Naka::Map::Object, draw_x : Int32, draw_y : Int32, zoom : Float64){
|
||||||
|
neighbours = [
|
||||||
|
{x, y-1, "t"},
|
||||||
|
{x+1, y, "r"},
|
||||||
|
{x, y+1, "b"},
|
||||||
|
{x-1, y, "l"}
|
||||||
|
]
|
||||||
|
|
||||||
|
neighbours = neighbours.map do |x, y|
|
||||||
|
map.get(x, y)[z]?.try &.reference.== object.reference
|
||||||
|
end
|
||||||
|
|
||||||
|
t, r, b, l = neighbours
|
||||||
|
t = t ? 't' : '-'
|
||||||
|
r = r ? 'r' : '-'
|
||||||
|
b = b ? 'b' : '-'
|
||||||
|
l = l ? 'l' : '-'
|
||||||
|
|
||||||
|
neighbours = [t, r, b, l].reduce "" { |a, c| a + c }
|
||||||
|
|
||||||
|
window.draw (textures[neighbours]? || textures["trbl"]), draw_x, draw_y, scale_x: zoom, scale_y: zoom
|
||||||
|
|
||||||
|
nil
|
||||||
|
}
|
||||||
|
end
|
||||||
|
|
||||||
|
stone = Naka::Map::ObjectReference.new(
|
||||||
|
name: "Stone",
|
||||||
|
walkable: true,
|
||||||
|
drawer: simple_tile_drawer window, "assets/stone.png"
|
||||||
|
)
|
||||||
|
grass = Naka::Map::ObjectReference.new(
|
||||||
|
name: "Grass",
|
||||||
|
walkable: true,
|
||||||
|
drawer: bordered_tile_drawer window, "assets/grass{}.png"
|
||||||
|
)
|
||||||
|
dirt = Naka::Map::ObjectReference.new(
|
||||||
|
name: "Dirt",
|
||||||
|
walkable: true,
|
||||||
|
drawer: bordered_tile_drawer window, "assets/dirt{}.png"
|
||||||
|
)
|
||||||
|
sand = Naka::Map::ObjectReference.new(
|
||||||
|
name: "Sand",
|
||||||
|
walkable: true
|
||||||
|
)
|
||||||
|
water = Naka::Map::ObjectReference.new(
|
||||||
|
name: "Water"
|
||||||
|
)
|
||||||
|
flowers = Naka::Map::ObjectReference.new(
|
||||||
|
name: "Flowers",
|
||||||
|
walkable: true
|
||||||
|
)
|
||||||
|
haunted = Naka::Map::ObjectReference.new(
|
||||||
|
name: "Haunted",
|
||||||
|
walkable: true
|
||||||
|
)
|
||||||
|
tree = Naka::Map::ObjectReference.new(
|
||||||
|
name: "Tree"
|
||||||
|
)
|
||||||
|
pine = Naka::Map::ObjectReference.new(
|
||||||
|
name: "Pine Tree"
|
||||||
|
)
|
||||||
|
rocks = Naka::Map::ObjectReference.new(
|
||||||
|
name: "Rocks"
|
||||||
|
)
|
||||||
|
|
||||||
altitude_noise = Naka::Noise2D.new.tap do |a|
|
altitude_noise = Naka::Noise2D.new.tap do |a|
|
||||||
a.add_octave(32, 1)
|
a.add_octave(32, 1)
|
||||||
a.add_octave(16, 0.5)
|
a.add_octave(16, 0.5)
|
||||||
|
@ -61,55 +165,61 @@ evil_noise = Naka::Noise2D.new.tap do |a|
|
||||||
a.add_octave(16, 0.3)
|
a.add_octave(16, 0.3)
|
||||||
end
|
end
|
||||||
|
|
||||||
map = Naka::Map.new "map-test-01" do |tile, x, y|
|
map = Naka::Map.new stone, "map-test-01" do |tile, x, y|
|
||||||
altitude = altitude_noise.get(x, y) + 0.5
|
altitude = altitude_noise.get(x, y) + 0.5
|
||||||
|
|
||||||
humidity = humidity_noise.get(x, y) + 0.5
|
humidity = humidity_noise.get(x, y) + 0.5
|
||||||
|
|
||||||
evil = evil_noise.get(x, y)
|
evil = evil_noise.get(x, y)
|
||||||
|
|
||||||
if altitude < 0.25
|
if altitude < 0.35
|
||||||
tile << Naka::Map::Object.new "sand"
|
tile << Naka::Map::Object.new water
|
||||||
|
else
|
||||||
|
tile << Naka::Map::Object.new stone
|
||||||
|
end
|
||||||
|
|
||||||
if altitude < 0.175
|
if altitude < 0.25
|
||||||
tile << Naka::Map::Object.new "water"
|
if altitude > 0.175
|
||||||
else
|
|
||||||
if humidity < 0.33
|
if humidity < 0.33
|
||||||
tile << Naka::Map::Object.new "sand"
|
tile << Naka::Map::Object.new sand
|
||||||
else
|
else
|
||||||
tile << Naka::Map::Object.new "dirt"
|
tile << Naka::Map::Object.new dirt
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
elsif altitude < 0.75
|
elsif altitude < 0.75
|
||||||
tile << Naka::Map::Object.new "dirt"
|
tile << Naka::Map::Object.new dirt
|
||||||
|
|
||||||
if evil > 0.5
|
if evil > 0.5
|
||||||
tile << Naka::Map::Object.new "haunted"
|
tile << Naka::Map::Object.new haunted
|
||||||
else
|
else
|
||||||
tile << Naka::Map::Object.new "grass"
|
tile << Naka::Map::Object.new grass
|
||||||
end
|
end
|
||||||
|
|
||||||
if altitude > 0.35 && altitude < 0.65
|
if altitude > 0.35 && altitude < 0.65
|
||||||
if humidity > 0.4
|
if humidity > 0.4
|
||||||
if humidity > 0.8
|
if humidity > 0.8
|
||||||
tile << Naka::Map::Object.new "tree"
|
tile << Naka::Map::Object.new tree
|
||||||
elsif humidity < 0.6
|
elsif humidity < 0.6
|
||||||
tile << Naka::Map::Object.new "pine"
|
tile << Naka::Map::Object.new pine
|
||||||
else
|
else
|
||||||
if Random.rand(2) == 0
|
if Random.rand(2) == 0
|
||||||
tile << Naka::Map::Object.new "tree"
|
tile << Naka::Map::Object.new tree
|
||||||
else
|
else
|
||||||
tile << Naka::Map::Object.new "pine"
|
tile << Naka::Map::Object.new pine
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
else
|
else
|
||||||
if Random.rand(10) == 0
|
if Random.rand(10) == 0
|
||||||
tile << Naka::Map::Object.new "flowers"
|
tile << Naka::Map::Object.new flowers
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
elsif altitude > 0.85
|
else
|
||||||
tile << Naka::Map::Object.new "rocks"
|
tile << Naka::Map::Object.new stone
|
||||||
|
|
||||||
|
if altitude > 0.85
|
||||||
|
tile << Naka::Map::Object.new rocks
|
||||||
|
end
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
|
@ -119,7 +229,7 @@ Naka::Event.loop window do |event|
|
||||||
next Naka::Event::Quit
|
next Naka::Event::Quit
|
||||||
when Naka::Event::Update
|
when Naka::Event::Update
|
||||||
when Naka::Event::Draw
|
when Naka::Event::Draw
|
||||||
zoom_level = 1.0
|
zoom_level = 4.0
|
||||||
|
|
||||||
128.times do |x|
|
128.times do |x|
|
||||||
128.times do |y|
|
128.times do |y|
|
||||||
|
@ -128,17 +238,11 @@ Naka::Event.loop window do |event|
|
||||||
# FIXME:
|
# FIXME:
|
||||||
# - Please don’t draw more than one layer of ground…
|
# - Please don’t draw more than one layer of ground…
|
||||||
# - Transitions. (eg. between dirt and grass)
|
# - Transitions. (eg. between dirt and grass)
|
||||||
tile.each do |object|
|
tile.each_with_index do |object, z|
|
||||||
image = case object.type
|
image = case object.reference.name.downcase
|
||||||
when "grass"
|
|
||||||
images.grass
|
|
||||||
when "dirt"
|
|
||||||
images.dirt
|
|
||||||
when "stone"
|
|
||||||
images.stone
|
|
||||||
when "tree"
|
when "tree"
|
||||||
images.tree
|
images.tree
|
||||||
when "pine"
|
when "pine tree"
|
||||||
images.pine
|
images.pine
|
||||||
when "flowers"
|
when "flowers"
|
||||||
images.flowers
|
images.flowers
|
||||||
|
@ -154,13 +258,23 @@ Naka::Event.loop window do |event|
|
||||||
images.stone
|
images.stone
|
||||||
end
|
end
|
||||||
|
|
||||||
|
draw_x = (x * 16 * zoom_level).to_i
|
||||||
|
draw_y = (y * 16 * zoom_level - (image.height - 16) * zoom_level).to_i
|
||||||
|
|
||||||
|
drawer = object.reference.drawer
|
||||||
|
|
||||||
|
if drawer.nil?
|
||||||
window.draw(
|
window.draw(
|
||||||
image,
|
image,
|
||||||
x: (x * 16 * zoom_level).to_i,
|
x: draw_x,
|
||||||
y: (y * 16 * zoom_level - (image.height - 16) * zoom_level).to_i,
|
y: draw_y,
|
||||||
scale_x: zoom_level,
|
scale_x: zoom_level,
|
||||||
scale_y: zoom_level
|
scale_y: zoom_level
|
||||||
)
|
)
|
||||||
|
next
|
||||||
|
end
|
||||||
|
|
||||||
|
drawer.call map, x, y, z, tile, object, draw_x, draw_y, zoom_level
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
|
@ -3,21 +3,33 @@ require "json"
|
||||||
|
|
||||||
class Naka::Map
|
class Naka::Map
|
||||||
@save_directory : String
|
@save_directory : String
|
||||||
|
getter default_reference : ObjectReference
|
||||||
getter generator
|
getter generator
|
||||||
def initialize(@save_directory, &block : Proc(Tile, Int32, Int32, Tile?))
|
|
||||||
|
def initialize(@default_reference, @save_directory, &block : Proc(Tile, Int32, Int32, Tile?))
|
||||||
Dir.mkdir_p @save_directory
|
Dir.mkdir_p @save_directory
|
||||||
|
|
||||||
@generator = block
|
@generator = block
|
||||||
end
|
end
|
||||||
|
|
||||||
|
class ObjectReference
|
||||||
|
getter name : String
|
||||||
|
getter walkable : Bool
|
||||||
|
getter tiles : Array(String)
|
||||||
|
getter drawer : Proc(Map, Int32, Int32, Int32, Tile, Object, Int32, Int32, Float64, Nil)?
|
||||||
|
|
||||||
|
def initialize(@name, @walkable = false, @tiles = [] of String, @drawer = nil)
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
class Object
|
class Object
|
||||||
getter type : String
|
getter reference : ObjectReference
|
||||||
def initialize(@type)
|
def initialize(@reference)
|
||||||
end
|
end
|
||||||
|
|
||||||
def to_json(builder)
|
def to_json(builder)
|
||||||
builder.object do
|
builder.object do
|
||||||
builder.field "type", @type
|
builder.field "type", @reference.name
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
@ -45,7 +57,7 @@ class Naka::Map
|
||||||
Array.new(CHUNK_SIZE) do |y|
|
Array.new(CHUNK_SIZE) do |y|
|
||||||
y += @y * CHUNK_SIZE
|
y += @y * CHUNK_SIZE
|
||||||
|
|
||||||
Tile.new(Object.new "stone").tap do |tile|
|
Tile.new(Object.new map.default_reference).tap do |tile|
|
||||||
map.generator.call tile, x, y
|
map.generator.call tile, x, y
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|