Lekcja 4: Edytor
Dzisiaj odejdziemy nieco od samego robienia gry. Niemniej jednak, to co będziemy robili, jest ważne. Mianowicie: zrobimy podstawę naszego edytora. Samą podstawę, tylko i wyłącznie edytor mapy. Potem, w miarę prac nad grą, będziemy również dodawać więcej funkcji w naszym edytorze.
Od razu na początek ostrzegam, że będzie trochę pisania kodu. Efekty również będą nieco nudne, ale nie można robić tylko ciekawych rzeczy :p
Jako, że edytor nie będzie częścią gry, musimy zrobić osobny folder: '/edytor'. Tam będziemy umieszcać wszystko co jest częścią samego edytora (więc wszystkie skrypty i grafiki). Także stwórzcie ten folder w folderze głównym gry:
Będziemy potrzebowali również stworzyć trzy nowe pliki: Edytor.rb (odpowiednik naszego Run.rb, zapisany w folderze głównym), EditorWindow.rb (odpowiednik naszego GameWindow.rb) i SceneEditor.rb (oba zapisane w '/edytor'). W tej chwili powinniście już wiedzieć jak je zrobić. Jedyną różnicą jest to, że nasze okno będzie większe niż okno gry - 1024x768. Jeśli wasza rozdzielczość ekranu jest taka sama, lub niewiele większa, możecie się zastanowić nad ustawieniem 'true' jako parametru fullscreen, ponieważ w przypadku gdy okno Gosu jest większe niż bodajże 90% rozmiaru ekranu, jest ono skalowane w dół. To nieco pogarsza precyzję (aczkolwiek wciąż jest możliwość używania takiego zeskalowanego okna). W dalszej części możecie porównać sobie działanie edytora jako okienko i fullscreen (jeśli oczywiście skalowanie was tyczy), i podjąć decyzję ;)
Kod: Zaznacz cały
$: << File.dirname(__FILE__)
require 'gosu'
require 'rubygems'
include Gosu
require 'edytor/EditorWindow.rb'
require 'edytor/SceneEditor.rb'
$window = EditorWindow.new
$window.show
Kod: Zaznacz cały
class EditorWindow < Gosu::Window
def initialize
super(1024,768,false)
self.caption = "Fuzed: Map Editor"
$window = self
$scene = SceneEditor.new
end
def update
$scene.update
end
def draw
$scene.draw
end
def button_down(id)
$scene.button_down(id)
end
def button_up(id)
$scene.button_up(id)
end
end
Kod: Zaznacz cały
class SceneEditor
def initialize
end
def update
end
def draw
end
def button_down(id)
end
def button_up(id)
end
end
Będziemy również potrzebowali grafiki dla naszego edytora. Użyjemy tej:
https://dl.dropboxusercontent.com/u/189 ... editor.png
(jako link, ponieważ obraz za duży dla forum ;))
Wczytajmy ją w naszym SceneEditor jako '@bg', jako zwykły obrazek, oraz umieśćmy ją w draw ;)
Kod: Zaznacz cały
#initialize
@bg = Image.new($window,"edytor/editor.png", false)
# draw
@bg.draw(0,0,0)
Jako, że edytor będzie używał sterowania myszą, musimy go do niej dostosować. Obsługa myszy jest wbudowana w Gosu, ale jak zauważycie, kursor myszy się nie wyświetla gdy najedziecie na okno. Można to obejść w dwa sposoby. Pierwszym jest utworzenie grafiki kursora (Image) i wyświetlanie go na pozycji $window.mouse_x, $window.mouse_y. To pozwala na używanie dowolnych kursorów, ale w przypadku niskiego FPS kursor skacze.
Drugim jest zapewnienie naszego programu, że tak, potrzebujemy kursora myszy. Wtedy jest używany systemowy kursor. W poradniku użyjemy tego drugiego sposobu, ale jeśli ktoś chce, możecie spokojnie wykorzystać sposób #1 ;)
Żeby kursor systemowy wyświetlał się w oknie, musimy w naszej klasie EditorWindow dać tę oto metodę:
W ten sposób informujemy system, żeby wyświetlał nasz kursor myszy.
Kolejną rzeczą jaką musimy zrobić to utworzyć siatkę naszej mapy. Siatka będzie oczywiście trójwymiarową tablicą. Dlaczego trójwymiarową, a nie tak jak mieliśmy, dwuwymiarową?
Ponieważ dodamy warstwy! Na razie robimy mapę o stałym rozmiarze, ale to się zmieni z czasem :p
Kod: Zaznacz cały
width = 60
height = 45
@level = []
for layer in 0...2
@level[layer] = []
for y in 0...height
@level[layer][y] = []
for x in 0...width
@level[layer][y][x] = 0
end
end
end
Tłumaczenie powyższego kodu: dla każdej z warstw (warstwy mamy 2 w tej chwili) tworzy tablicę rozmiarów 60x45 wypełnioną zerami. To jest nasza, na razie pusta, plansza. Potrzebujemy jeszcze wczytać nasz tileset:
Kod: Zaznacz cały
@tileset = Image.load_tiles($window, "graphics/tiles/area02_level_tiles.png", 16, 16, true)
Zacznijmy może od narysowania naszej mapy w obszarze "Map", żebyśmy mogli upewnić się, że nasza siatka @level działa. W metodzie draw musimy ponownie stworzyć potrójną pętle for.
Kod: Zaznacz cały
for l in 0...@level.size
for y in 0...@level[l].size
for x in 0...@level[l][y].size
end
end
end
Zanim zaczniemy rysować obszar mapy, musimy wiedzieć jaki x i y mają poszczególne tile. Zauważcie, że obszar "Map" nie zaczyna się w 0:0, a w 368:160. Tak więc obliczamy nasze położenie:
Kod: Zaznacz cały
tx = 368 + (x*16)
ty = 160 + (y*16)
i = @level[l][y][x]
@tileset[i].draw(tx,ty,1+l)
To nam dla każdego tila obliczy jego położenie i wyświetli, na z 1 + warstwa. Uruchomienie teraz edytora nie pokaże nic, ponieważ wypełniamy naszą mapę przeźroczystymi grafikami. Dlatego też dla sprawdzenia zmieńmy na chwilę wszystkie wartości z 0 na 1 w initialize ('@level[layer][y][x] = 1'). I rzeczywiście, wyświetla się grafika, ale jest pewien problem:
Grafika wychodzi poza krawędzie! Co z tym zrobić?
Ograniczyć pętlę ;) przy rozmiarze obszaru "Map" (które równe jest okienku naszej gry) zmieścimy 40x30 kratek. Więc:
Kod: Zaznacz cały
if x < 40 and y < 30 then
tx = 368 + (x*16)
ty = 160 + (y*16)
i = @level[l][y][x]
@tileset[i].draw(tx,ty,1+l)
end
I rezultat:
To przy okazji nieco zmniejsza zużycie procesora, bo wyświetla mniejszą ilość grafik. Żeby jeszcze bardziej przyśpieszyć, możemy do linijki '@tileset
.draw(tx,ty,1+l)' dodać:
To nie będzie wyświetlało grafiki jeśli index danego tila jest 0 (czyli grafika jest w 100% przeźroczysta). Dobra, możecie ustawić tile znów na 0, sprawdziliśmy to, co chcieliśmy. Teraz trzeba wyświetlić nasz tileset. Co może być nieco trudne, ze względu na zapętlenie. Grafika tilesetu zaczyna się w pozycji 16:112.
Kod: Zaznacz cały
for i in 0...@tileset.size
tx = 16 + (i*16)
ty = 112
@tileset[i].draw(tx,ty,1)
end
Powyższy kod narysuje wszystko w prostej, ciągłej linii, a ten kod:
Kod: Zaznacz cały
for i in 0...@tileset.size
tx = 16 + (i*16)
ty = 112 + (i*16)
@tileset[i].draw(tx,ty,1)
end
Narysuje całość po skosie. Więc jak zrobić, żeby grafika narysowała się 20 razy a potem przeskoczyła do kolejnej linijki?
Otóż, logicznie biorąc, musimy wyświetlić 20 tili, następnie przejść do kolejnej linijki, wyświetlić kolejne 20 tili i tak dalej. Zrobić to możemy tym oto kodem:
Kod: Zaznacz cały
for i in 0...@tileset.size
tx = 16 + ((i%20)*16)
ty = 112 + ((i/20)*16)
@tileset[i].draw(tx,ty,1)
end
W oczy powinien wam się od razu rzucić nowy znak: %. Znak %, lub mod, modulo, reszta wykonuje dzielenie, ale zwraca nie wynik tego dzielenia, a resztę (np. 5 % 2 zwróci nam 1). Jak więc nasz kod działa?
Obliczając tx bierzemy index w zasięgu 1 - 20 (i%20) i mnożymy przez 16 dla dokładnej pozycji. Dla obliczenia ty po prostu dzielimy obecny indeks i dzielimy przez 20. Takie obliczanie pozwoli nam osiągnąć to:
Teraz musimy zrobić obsługę kliknięcia myszą. Zaczniemy od samego wykrycia kliknięcia, potem gdzie to kliknięcie nastąpiło, a na końcu wybieranie tila i stawianie go na mapie :) W SceneEditor#button_down(id) dajcie warunek sprawdzający, czy wykryło kliknięcie lewym przyciskiem myszy. Jeśli tak, powinniśmy zostać odesłani do metody 'click'.
Oczywiście musimy również utworzyć tę metodę. W niej na razie będziemy mieli dwa warunki. Jeden sprawdzi, czy kliknęliśmy nad obszarem tilesetu, drugi: nad obszarem mapy. Do tego możemy użyć metody #between().
Kod: Zaznacz cały
def click
if $window.mouse_x.between?(16, 336) and $window.mouse_y.between?(112, 304) then
p "tileset"
elsif $window.mouse_x.between?(368, 1008) and $window.mouse_y.between?(160, 640) then
p "mapa"
end
end
Teraz jeśli klikniecie nad tilesetem albo mapą powinniście otrzymać odpowiednią informację w naszym wierszu poleceń. Skoro to już działa, czas zrobić zaznaczanie tile. Przyda nam się do tego poniższa grafika, którą będziemy określać obecnie zaznaczonego tila:
Wczytajcie ją jako '@sel_16'. Zróbcie też dwie zmienne, @sel_16_x i @sel_16_y, ich wartości ustawcie na 16:112, przez co zostanie wyświetlona na pierwszym zaznaczonym tile. Zróbcie też zmienną '@selected_tile = 0'
Kod: Zaznacz cały
#Initialize
@sel_16 = Image.new($window, "edytor/sel16.png", false)
@sel_16_x = 16
@sel_16_y = 112
@selected_tile = 0
# Draw
@sel_16.draw(@sel_16_x, @sel_16_y, 5)
To łatwiejsze mamy z głowy. Teraz musimy zrobić zaznaczanie tile. W naszej metodzie 'click' , zastąpcie 'p "tileset"' wywołaniem metody: 'select_tile($window.mouse_x, $window.mouse_y)'. Metodę oczywiście trzeba stworzyć, z dwoma parametrami: x i y.
Kod: Zaznacz cały
def select_tile(x,y)
tx = ((x - 16) / 16).floor
ty = ((y - 112) / 16).floor
i = tx + (ty*20)
@sel_16_x = (tx * 16) + 16
@sel_16_y = (ty * 16) + 112
@select_tile = i
end
Co robi ten kod? Po kolei: Sprawdza x i y danego tila, na którym kliknęliśmy. .floor sprawia, że zawsze jest zaokrąglona wartość w dół (więc w przypadku, gdy klikniemy za połową tila nie zostanie zaznaczony następny tile). Następnie obliczamy index danego tila (pamiętajcie, że nasz tileset jest tablicą jednowymiarową!). Kolejną rzeczą jest ustalenie pozycji x i y dla naszego zaznaczenia. Dlaczego zrobiłem to tak, a nie po prostu przypisałem wartości x i y które przesłałem jako parametry? Ponieważ nie byłyby wyrównane do siatki 16x16, i zaznaczenie nie byłoby dokładne. Ostatnią rzeczą jest zmienienie wartości @selected_tile na index który obliczyliśmy. Teraz zróbmy stawianie tila na mapie. Zróbmy metodę 'place_tile(x,y)', i prześlijmy do niej dane identycznie jak przed chwilą. W initialize zróbmy jeszcze jedną zmienną: @current_layer = 0. Będziemy jej teraz potrzebowali.
Metoda stawiania tila jest bardzo prosta. Znajdujemy tx i ty (czyli x i y tila nad którym kliknęliśmy) i zmieniamy wartość @level[warstwa][y][x] na @selected_tile. Myślę, że sami dacie sobie z tym radę ;)
Kod: Zaznacz cały
def place_tile(x,y)
tx = ((x - 368) / 16).floor
ty = ((y - 160) / 16).floor
@level[@current_layer][ty][tx] = @select_tile
end
Jak zauważycie, możecie spokojnie stawiać tile, ale pojedynczo. Skoczmy więc szybko do update'a i dodajmy taki kod:
Kod: Zaznacz cały
if $window.button_down?(MsLeft) and $window.mouse_x.between?(368, 1008) and $window.mouse_y.between?(160, 640) then
place_tile($window.mouse_x, $window.mouse_y)
end
To pozwoli nam rysować danym tilem po mapie. Jednak jest problem, jeśli nie zaznaczymy nic, tylko od razu spróbujemy rysować po mapie, czeka na nas (nie)miła niespodzianka:
Jak możemy wyczytać z błędu, skrypt ma problem z odczytaniem wartości Integer z podanej wartości nil (czyli nie potrafi odczytać Liczby z wartości nic). Nie powinno tak być, więc szybko znajdźmy linijkę w której to się dzieje:
I dodajmy jeszcze jeden warunek:
Kod: Zaznacz cały
@tileset[i].draw(tx,ty,1+l) if i != 0 and i != nil
Uruchomcie jeszcze raz i sprawdźcie, czy błąd wyskakuje. Nie powinien ;) do tego możemy już robić nieco szybciej nasze mapy:
(to nie jest szczyt moich mappingowych umiejętności, ale cóż :P). Wygląda jakbyśmy byli blisko końca?
No niestety, musimy zrobić jeszcze kilka rzeczy. Najpierw ściągnijcie ten obrazek:
I wczytajcie go w edytorze. Wyświetlimy go nad mapą, żeby dokładniej widzieć krawędzie naszych tili. Sami już potraficie to zrobić. Wyświetlcie na współrzędnych 368:160:5
Poza tym mamy do zrobienia jeszcze kilka rzeczy. Pierwszą będzie przesuwanie mapy. Następnie zrobimy przełączanie między warstwą 1 a 2, stawianie postaci gracza na pozycji startowej i, oczywiście, zapisywanie mapy do pliku.
Zacznijmy od ustawienia trzech nowych zmiennych:
Kod: Zaznacz cały
@offset_x = 0
@offset_y = 0
@ctrl_held = false
Pierwsze dwie mają nasz offset, czyli o ile tili przesunięta mapa jest. Ostatnia będzie służyła do przełączania między przewijaniem poziomo a pionowo. Przejdźmy do metody 'button_down(id)' i dajmy trzy warunki:
Kod: Zaznacz cały
if id == MsWheelDown then
increase_offset
end
if id == MsWheelUp then
decrease_offset
end
if id == KbLeftControl then
@ctrl_held = true
end
Ostatni warunek również dajmy do metody 'button_up(id)', z tą różnicą, że tam zmieniamy wartość na false. Zróbmy również dwie brakujące metody.
Kod: Zaznacz cały
def increase_offset
if @ctrl_held then
@offset_x += 1
else
@offset_y += 1
end
end
def decrease_offset
if @ctrl_held then
@offset_x -= 1
else
@offset_y -= 1
end
end
Co tu zrobiliśmy, i jak to działa. Za każdym razem gdy użyjemy pokrętła w rolce, nasz @offset_y się zwiększa (rolka w dół) albo zmniejsza (rolka w górę). Jednak gdy w międzyczasie trzymamy wciśnięty lewy control, zmienia się nasz @offset_x (zmiany są analogiczne). Zróbmy jeszcze kilka warunków: zabrońmy offsetów mniejszych niż 0, i większych niż szerokość/wysokość mapy - obszar który widzimy. Przez to będziemy mieli pewność, że nasza mapa nie zginie gdzieś tak poza granicami ;) Potrzebujemy jeszcze, żeby nasze offsety miały jakieś odzwierciedlenie na mapie. W metodzie 'draw' znajdźcie linijkę:
i dodajcie w niej nasze offsety:
Kod: Zaznacz cały
i = @level[l][y + @offset_y][x + @offset_x]
Odpalcie grę, postawcie jakiś tile i zobaczcie jak zmienia pozycję. Jeśli nie posiadacie w myszce rolki, albo używacie laptopa, musimy zmienić nieco metodę i dodać możliwość użycia klawiatury. Do obu metod odpowiedzialnych za offset dajcie parametr 'forced = false' i zmieńcie je w taki sposób:
Kod: Zaznacz cały
def increase_offset(forced = false)
if @ctrl_held or forced then
@offset_x += 1 if (@offset_x < @level[0][0].size - 40)
else
@offset_y += 1 if (@offset_y < @level[0].size - 30)
end
end
def decrease_offset(forced = false)
if @ctrl_held or forced then
@offset_x -= 1 if @offset_x > 0
else
@offset_y -= 1 if @offset_y > 0
end
end
A do 'button_down(id)' dajcie warunki dla każdej ze strzałek:
Kod: Zaznacz cały
if id == KbUp then
decrease_offset
end
if id == KbDown then
increase_offset
end
if id == KbLeft then
decrease_offset(true)
end
if id == KbRight then
increase_offset(true)
end
Parametr 'forced', jak mam nadzieję, że zauważyliście, jest wysyłany tylko przy poruszaniu się strzałkami w prawo i lewo. Dzięki temu @offset_x może zostać zmieniany za pomocą odpowiednich strzałek, a nie musimy trzymać lewego controla i używać strzałek w górę i w dół (aczkolwiek ten sposób również działa, możecie sprawdzić ;) ).
Możliwe również, że zauważyliście kolejny mały błąd. Otóż offsety nie wpływają na to, gdzie kładziemy kolejne tile. Nie działają, ponieważ stawiając tila nie bierzemy ich pod uwagę ;) w metodzie 'place_tile(x,y)' musicie dodać nasze offsety do tx i ty. Gdy to zrobicie, wszystko będzie działało tak, jak powinno.
Teraz zajmijmy się przełączaniem warstw. Potrzebna nam będzie ta grafika:
zapisana jako @sel_32. Do niej również zróbcie zmienne _x/_y, jak robiliśmy to wcześniej, i ustawcie współrzędne na 672:112. Od razu ustawcie rysowanie tego w metodzie draw, na z=5.
Zmieńcie funkcję click żeby brała pod uwagę kliknięcia nad dwoma przyciskami wartstw:
Kod: Zaznacz cały
elsif $window.mouse_x.between?(672,704) and $window.mouse_y.between?(112,144) then
@current_layer = 0
@sel_32_x = 672
elsif $window.mouse_x.between?(720,752) and $window.mouse_y.between?(112,144) then
@current_layer = 1
@sel_32_x = 720
Dodatkowo przejdźmy do draw i ustawmy, żeby aktywna warstwa różniła się nieco od nieaktywnej. Najprostrzym będzie zmienienie przeźroczystości nieaktywnej warstwy na 160. Nasz kod:
Kod: Zaznacz cały
@tileset[i].draw(tx,ty,1+l) if i != 0 and i != nil
musimy nieco rozbudować. Pierwsza rzecz, którą musimy zrobić, to sprawdzić, czy warstwa l jest aktywna czy nie:
I rozbudować kod rysowania. Metoda Image#draw może pobrać więcej argumentów niż x,y,z:
Kod: Zaznacz cały
draw(x, y, z, scale_x, scale_y, color, mode)
Scale_x i _y są proste do zrozumienia. Po naszym z musimy dać wartości 1.0 dla obu skali (ponieważ nie chcemy zmieniać rozmiaru naszego obrazka). To wartość color nas obchodzi. Dla aktywnej warstwy nie zmieniamy nic, a dla warstwy nieaktywnej (w części 'else' warunku) musimy ustawić kolor: 'Color.new(160,255,255,255)'.
Kod: Zaznacz cały
@tileset[i].draw(tx,ty,1+l,1.0,1.0,Color.new(160,255,255,255)) if i != 0 and i != nil
Sprawdźcie sami, ustawcie kilka bloków na pierwszej warstwie a następnie przełączcie na warstwę drugą. Pierwsza warstwa jest nieco przeźroczysta. Możecie dopasować przeźroczystość do własnych potrzeb, zmieniając '160' na inną wartość.
Teraz zajmiemy się stawianiem naszej postaci. Do tego potrzebujemy kilku zmiennych:
Kod: Zaznacz cały
@objects = []
@player_graphic = Image.load_tiles($window, "graphics/sprites/player_1_run_left.png", 32, 32, false)
@active_mode = :map
@object_held = nil
@active_mode jest ważną zmienną. Nią ustalamy, czy w danym momencie stawiamy objekty (gracz, później więcej elementów) czy robimy mapę.
Narysujmy jeszcze naszą postać gracza:
Kod: Zaznacz cały
frame = milliseconds / 150 % @player_graphic.size
@player_graphic[frame].draw(32,352,1)
Następnie sprawdźmy, czy kliknęliśmy w tym miejscu (32:352, rozmiar 32x32 piksele). Jeśli tak, odeślijmy do metody 'select_object(:player)'. W tej metodzie przypiszemy zmiennej '@object_held' wartość ':player' i zmienimy mode na ':objects'. Następnie zejdźmy do 'draw' i dodajmy ten oto kod:
Kod: Zaznacz cały
case @object_held
when nil
when :player
@player_graphic[0].draw($window.mouse_x, $window.mouse_y,10)
end
Tak wygląda switch statement. Czasami będziemy go używać. Ten oto rysuje grafikę postaci (jeśli mamy ją zaznaczoną) pod kursorem myszy. Mamy zaznaczanie postaci, teraz czas na stawianie jej na mapie. Wróćmy do metody 'click', a dokładnie do części odsyłającej do 'place_tile' i zmieńmy ją na:
Kod: Zaznacz cały
if @active_mode == :map then
place_tile($window.mouse_x, $window.mouse_y)
elsif @active_mode == :objects then
place_object($window.mouse_x, $window.mouse_y)
end
Dodajmy również tę metodę:
Kod: Zaznacz cały
def place_object(x,y)
rx = x + (@offset_x*16) - 368
ry = y + (@offset_y*16) - 160
@objects << [@object_held, rx, ry]
if @object_held == :player then
@object_held = nil
end
end
Ten kod ustawi informacje o pozycji gracza, oraz (w tym przypadku) zmieni trzymany objekt na pustą wartość. W przypadku innych elementów nie będziemy tego robić (będzie można stawiać elementy masowo). Musimy jeszcze wyświetlać nasze elementy na mapie:
Kod: Zaznacz cały
for i in 0...@objects.size
case @objects[i][0]
when :player
frame = milliseconds / 150 % @player_graphic.size
rx = @objects[i][1] - (@offset_x * 16) + 368
ry = @objects[i][2] - (@offset_y * 16) + 160
@player_graphic[frame].draw(rx,ry,6)
end
end
Teraz gdy postawicie naszego gracza, zauważycie, że pojawił się na naszej mapce. Ale gdy postawicie drugiego, są dwie postaci. Musimy coś z tym zrobić. Wróćmy do metody 'place_object' i na samym jej początku dajmy:
Kod: Zaznacz cały
if @object_held == :player then
for i in 0...@objects.size
if @objects[i][0] == :player
@objects.delete_at(i)
end
end
end
To sprawdzi, czy mamy już gracza w naszej zmiennej, i jeśli tak jest - usuwa go przed postawieniem w nowej pozycji.
Zanim przejdziemy do ostatniej już części, dajcie w metodzie 'select_tile' zmianę na mapę:
Gdy to zrobiliśmy, czas na końcówkę dzisiejszej lekcji, czyli zapisywanie naszej mapy do pliku!
Najpierw wykrywajmy kliknięcie myszą nad pozycją 560:112 (ikonka zapisu). Jeśli tak, niech nas kliknięcie tam odeśle do metody 'save'.
W naszym pliku mapy musimy zachować trzy informacje: naszą mapę, tileset użyty i objekty. Na ten moment będziemy zapisywać jako "Map000.map". To oczywiście z czasem dopracujemy ;)
Nasza metoda save:
Kod: Zaznacz cały
def save
f = File.new("Map000.map", "w+")
Marshal.dump(@tileset, f)
Marshal.dump(@level, f)
Marshal.dump(@objects, f)
f.close
end
Jednak użycie jej wyświetli nam taki oto błąd:
Powód tego błędu jest taki, że Marshal nie potrafi zapisać iformacji z Gosu::Image. Możemy jedynie zapisać ścieżkę/nazwę tileseta w postaci stringa. Dlatego w naszym initialize dokonajmy drobnej zmiany:
Kod: Zaznacz cały
@used_tileset = "area02_level_tiles.png"
@tileset = Image.load_tiles($window, "graphics/tiles/#{@used_tileset}", 16, 16, true)
I w metodzie 'save' zmieńmy '@tileset' na '@used_tileset'. Teraz po kliknięciu ikonki zapisu dzieje się magia, której wynikiem jest:
.
Na dzisiaj to koniec, w następnej części nauczymy się wczytywania mapy, zrobimy też obsługę mapy większej, niż wielkość ekranu. A potem... zobaczymy ;)
Archiwum winrara z efektem dzisiejszej pracy.