Blockspiel

Kommentare anzeigen Worklog abonnieren

Worklogs Blockspiel

Weitere lua geschichten.

Mittwoch, 16. Mai 2012 von AnniXa
Erstmal konnte ich nun dank studieren des LUA manuals und Sicherheitsnachfragem im englischen Forum endlich voll durchblicken was es mit dem ganzen State und stack und so weiter auf sich hat.

Im das ganze push und pop ist im grunde wenn man erstmal dahinter gestiegen ist ähnlich simpel wie die OpenGL push und popperei Smile

So konnte ich nun z.B. den code der eine funktion in lua aufruft nun so gestalten:

Code: [AUSKLAPPEN]

   lua_getglobal(Lua.l, "on_mapGenerate") '<-------------- 1
   If Not lua_isfunction(Lua.L, -1) Then '<-------------- 2
      Print "Warning! map:" + toGenerate.name + " script:" + toGenerate.source + " hat keine on_mapGenerate function!"
        lua_pop(Lua.L, 1)
        Return
    EndIf
   lua_pushbmaxobject(Lua.l, toGenerate.LuaInterfaceMap) '<-------------- 3
   lua_pcall(Lua.l, 1, 0, 0) '<-------------- 4


1: Erstmal schieben wir die globale "on_mapGenerate" auf den stack.
2: Dann prüfen wir mit lua_isfunction ob es sich bei dem was gerade auf dem stack ist um eine funktion handelt.
3: Dann schieben wir das map object hinterher.
4: Hier rufen wir die funktion auf, mit 1 parameter und 0 rückgabewerten.

Funktioniert alles ganz gut nun, und so habe ich die ersten funktionen und objekte eingbaut mit denen man von Lua aus das spielgeschehen beinflussen kann, da dies garnichtmal so wenige sind und im laufe der zeit sicher mehr werden, habe ich dafür ein google doc angelegt, wer mag kann es sich ja einmal anschauen:

https://docs.google.com/spread...UY3c#gid=0

Alle mit X markierten Einträge sind bereits eingebaut und Getestet.

Um das ganze besser debuggen zu können habe ich einen neuen server befehl eingebaut:
/script <file>
damit kann man vom clienten aus ein script (aus einer datei) auf dem server ausführen um so die scripte und auch die funktionen auf der blitzmax seite zu überprüfen, oder sich eben mal ein paar HP dazu zu cheaten ;D.

Dies ganze habe ich hier mit diesem lua script mal verdeutlicht:

Code: [AUSKLAPPEN]

-- Player mit ID 0 holen:
local player = GetPlayer(0)
-- einen text dem spieler schicken:
player:SendNotify ("deine maximalen hp:"..player:GetMaxHP())
player:SendNotify ("deine aktuellen hp:"..player:GetCurrentHP())
-- die map auf dem der spieler ist holen:
map = player:GetMap()
-- Das licht der map ändern:
map:SetAmbientLight(64,64,64)
map:SetSun(255,128,128,45,21)
-- dem player den namen der map sagen, auf der er ist:
player:SendNotify ("du bist auf der map:"..map:GetName())
-- dem Player seine HP voll aufladen:
player:SetCurrentHP(player:GetMaxHP())


Dies ist ist vor der ausführung:
Der obligatorische HP balken ist fast runter, und das licht ist Recht hell eingestellt (so wie es aus dem .map file gelesen wurde)
user posted image


Nach einem druck auf enter, sieht es dann so aus:
Das licht wurde verstellt (sonne und ambient)
Es wurden nachrichten an den spieler gesandt, und seine HP aufgeladen.
user posted image

Das Script wurde serverseitig ausgefürt und sämtliche infos an den clienten übertragen.

Als nächstes werde ich nun mich damit befassen eine art event system zu bauen, und bestimmte funktionen immer aufrufen wenn etwas passiert, also so etwas wie on_PlayerDie(player) wenn jemand gestorben ist usw.

Auserdem möchte ich ein paar grundlegende gui-fenster vom server senden können mittels lua, und entsprechende events auslösen wenn ein user auf eines dieser reagiert.
Erstmal so simple dinge wie eine message senden oder eine frage stellen die man mit ja/nein beantworten kann.

Lua->LuGi

Montag, 14. Mai 2012 von AnniXa
So nun mal ein neuer bericht =)
Das WE über hatte ich nicht soviel zeit aber heute dann wieder ein wenig.

Erstmal habe ich das Lua zeug nochmal überarbeitet und es mit Lugi und dem mitgelieferten reflection code vorgenerator cooler lösen können.

Dazu habe ich die leute im Blitzbasic.com forum leicht belasten müssen.

Mehrere Maps können sich nun ein LUA script teilen, es wird dann immer die function
on_mapGenerate(map) in lua aufgerufen, und die map übergeben die gerade generiert werden soll.
Möchte man trozdem verschiedene map generatoren für die maps verwenden kann man entweder in der .map datei verschiedene .lua dateien angeben, oder aber in seiner on_mapGenerate funktion am anfang den namen der map sich ausgeben lassen und anhand dessen entscheiden.
map hat die methoden:

map:GetSizeX()
map:GetSizeY()
map:GetSizeZ()
map:GetName()
map:GetBlock(x,y,z)
map:SetBlock(x,y,z,b)
map:GetAmbientR()
map:GetAmbientG()
map:GetAmbientB()
map:SetAmbient(r,g,b)
map:GetSunG()
map:GetSunB()
map:SetSun(r,g,b)
map:GetSunYaw()
map:GetSunPitch()
map:SetSunAngle(Yaw,Pitch)

Damit kann man eine map erstellen und auch die beleuchtung ändern.
Das mapscript aus dem letzten worklog beitrag sieht nun so aus:

Code: [AUSKLAPPEN]

function on_mapGenerate(map)
    print ("------------------- START MAP GENERATE -----------------------")

    if map == nil then
        print ("map was nil :(")
    else
         -- map generierungs script
        print("creating map: flatworld")
        -- Die größe der map ermitteln:
        local sx = map:GetSizeX()
        local sy = map:GetSizeY()
        local sz = map:GetSizeZ()

        -- eine bodenplatte erstellen aus erde (1):
        for x = 0, sx, 1 do
            for z = 0, sz, 1 do
                map:SetBlock(x,0,z,1)
            end   
        end

        -- nun ein paar türme in der landschaft verteilen:
        for count = 0, 400, 1 do -- 400 türme setzen
            --zufällige position
            local rx = math.random(0,sx)
            local rz = math.random(0,sz)
            --zufällige turmhöhe zwischen 1 und 5
            local height = math.random(0,5)
            --zufällige block id zwischen 1 und 10 woraus der turm wird
            local block = math.random(1,5)
            --diesen turm bauen
            for thisheight = 0 ,height,1 do
                map:SetBlock(rx,thisheight,rz,block)
            end
        end
    end

    print ("------------------- END MAP GENERATE ------------------------")
end


Das ganze zu machen war ein bischen tricky, also mit der object übergabe an eine funktion.
Dafür habe ich dieses type angelegt

Code: [AUSKLAPPEN]

Type LuaFunctions {expose static noclass}
   
   'gibt die map zurück für den namen, oder nil wenn es keine gibt.
   Method GetMapForName:map(mapname:String)
      Local smap:map = ActualScenario.GetMapForName(mapname).LuaInterfaceMap
      Return(smap)
   End Method

End Type


das noclass sagt dem gluecode generator, das dieses type in lua nicht existieren, und die methoden dann in lua als funktionen auftauchen.

um das oben gesehene lua dann zu starten und auch die funktion aufzurufen bedarf es dann nurnoch dem in der erstellungsmethode der map (also in bmx):

Lua.DoString("on_mapGenerate(GetMapForName(~q" + Self.Name + "~q))")

Gute nacht!

Erste schritte mit luajit

Samstag, 12. Mai 2012 von AnniXa
Heute nacht hatte ich dann noch etwas zeit, um mich mal mit Lua herumzuärgern.

Meine Funktion welche einfach ein lua file ausführen soll sieht so aus:

Code: [AUSKLAPPEN]

   Function RunLuaFile(file:String)      
      lua_dofile(luastate, file)
      lua_getfield(luastate, LUA_GLOBALSINDEX, "debug")
      lua_getfield(luastate, -1, "traceback")
      lua_remove (luastate, -2)
      
      If (lua_pcall(luastate, 1, -1, -1)) <> 0 Then
         Print "LUA ERROR:" + lua_tostring(luastate, -1)
      End If
   End Function


soweit funktioniert sie auch gut, die habe ich aus irgendeinem sample abgeschaut.

das einzigste problem war, das es fehler ausgibt obwohl alles zu gehen scheint.

eine datei mit diesem inhalt:
Code: [AUSKLAPPEN]
print("test")


gab das aus:
Code: [AUSKLAPPEN]

test
LUA ERROR:attempt to call a nil value
stack traceback:


Hm, komisch^^
scheinbar gehts, test wird geprintet, aber irgendwie gibt es angebloch noch ein "attempt to call a nil value" ?
hm vieleicht hat das " am ende vom print ja noch heimlich seine freunde gerufen, so weit war ich schon am herumprobieren das ich die Äpfel in meinem kühlschrank umsoritert habe um zu sehen ob es einen einfluss hat.

egal ob ich es mit luaL_loadstring oder als datei mit dofile oder mit dostring oder sogar mit keinem apfel im kühlschrank machte, immer kam das dabei heraus.

Dann hab ich aber den fehler gefunden, und zwar lag es an meinem lua init dingsie
ich verwendete zwar
luaL_openlibs(luastate)
nicht aber:
luaopen_base(luastate)

aufjedenfall geht es nun =)

In den anleitungen die ich gelesen habe wurde immer nur das eine oder das andere verwendet, ich hab nun einfach beides und es geht.

Dies sind nun meine Funktionen die ich benutze
Code: [AUSKLAPPEN]

   Global luastate:Byte ptr
   Global State:Int = 0
   
   'lua VM erstellen
   Function Init()
      Deinit() 'es kann nur eine vm geben.
      luastate = luaL_newstate()
      State = 1
      luaL_openlibs(luastate)
      luaopen_base(luastate)
   End Function
   
   'lua VM schliesen
   Function Deinit()
      If State = 1 Then lua_close(luastate)
      State = 0
   End Function
   
   'summary: führt eine string als lua aus.
   Function RunLua(Script:String)
      lua_dostring(luastate, Script)
            
      'irgendetwas wichtiges machen das man für die error info braucht:
      lua_getfield(luastate, LUA_GLOBALSINDEX, "debug")
      lua_getfield(luastate, -1, "traceback")
      lua_remove (luastate, -2)
      
      'ausführen und ggf fehlermeldung ausgeben
      If (lua_pcall(luastate, 1, -1, -1)) <> 0 Then
         Print "LUA ERROR:" + lua_tostring(luastate, -1)
      End If
   End Function
   
   'summary: lädt eine datei und führt sie aus
   Function RunLuaFile(file:String)
      lua_dofile(luastate, file)
      
      'irgendetwas wichtiges machen das man für die error info braucht:
      lua_getfield(luastate, LUA_GLOBALSINDEX, "debug")
      lua_getfield(luastate, -1, "traceback")
      lua_remove (luastate, -2)
      
      'ausführen und ggf fehlermeldung ausgeben
      If (lua_pcall(luastate, 1, -1, -1)) <> 0 Then
         Print "LUA ERROR:" + lua_tostring(luastate, -1)
      End If
   End Function


so ganz hab ich das zwar immernoch nicht geschnallt, was das alles macht:

lua_getfield(luastate, LUA_GLOBALSINDEX, "debug")
lua_getfield(luastate, -1, "traceback")
lua_remove (luastate, -2)

aber irgendwann werde ich schon dahintersteigen^^

Immerhin hab ich nach einer weile herausgefunden das ich ja schon bei dofile die ausführung gemacht habe und der pcall am ende eigentlich quatsch war.

dofile scheint wohl einfach eine kombination aus
luaL_loadfile und lua_pcall zu sein?

so Funktioniert es nun:
(malsehen wie lange^^)

Code: [AUSKLAPPEN]

   'summary: lädt eine datei und führt sie aus
   Function RunLuaFile(file:String)
   
      luaL_loadfile(luastate, file)
         
'      'irgendetwas wichtiges machen das man für die error info braucht:
      lua_getfield(luastate, LUA_GLOBALSINDEX, "debug")
      lua_getfield(luastate, -1, "traceback")
      lua_remove (luastate, -2)
      
      'ausführen und ggf fehlermeldung ausgeben
      If (lua_pcall(luastate, 1, -1, -1)) <> 0 Then
         Print "LUA ERROR:" + lua_tostring(luastate, -1)
      End If
      
   End Function


Ein paar einfach funktionen habe ich nun schon gewrappt (nennt man das so bei lua?):
getmapsize() returnt 3 werte welche die map größe angeben, welche in der .map datei angegeben ist
setblock(x,y,z,blockID) setzt einen block an position XYZ
getblock(x,y,z) gibt zurück welcher block sich gerade an xyz befindet.

das ist ja schonmal ein anfang oder?
Dieses kleine map erzeugungs script habe ich zum testen geschrieben:
Code: [AUSKLAPPEN]

-- map generierungs script
print("creating map: flatworld")
-- Die größe der map ermitteln:
local sx,sy,sz = getmapsize()

-- eine bodenplatte erstellen aus erde (1):
for x = 0, sx, 1 do
    for z = 0, sz, 1 do
        setblock(x,0,z,1)
    end   
end

-- nun ein paar türme in der landschaft verteilen:
for count = 0, 400, 1 do -- 400 türme setzen
    --zufällige position
    local rx = math.random(0,sx)
    local rz = math.random(0,sz)
    --zufällige turmhöhe zwischen 1 und 5
    local height = math.random(0,5)
    --zufällige block id zwischen 1 und 10 woraus der turm wird
    local block = math.random(1,15)
    --diesen turm bauen
    for thisheight = 0 ,height,1 do
        setblock(rx,thisheight,rz,block)
    end
end


nachdem ich dieses script ins map file eingetragen habe:
source=test.lua

und ich dann im editor auf "Lua ausführen" geklickt habe, präsentierte sich mir folgendes bild:

user posted image

Das fand ich toll, angemessen um nun beruhigt schlafen zu gehen Smile


Blocktechnik

Freitag, 11. Mai 2012 von AnniXa
Heute habe ich mal einen versuch gewagt die ganze Struktur hinter meinem Blocksystem zu überarbeiten und dafür ein kleines tool zu schreiben um die "blocksets" zu bearbeiten, und ein älteres tool nochmal ein wenig zu überarbeiten.

Was ist ein blockset?
Ein blockset ist ein steuerfile (ini abart) in welchem gespeichert ist wie die blöcke aussehen.
Hiermit sind nicht die mesh daten selbst gemeint, sondern eher eine art "compilation" wie diese dargestellt werden.

Es ist schwer das in sinvoller reihenfolge zu erklären, aber ich versuchs einfach mal =)

Ein block, den man in der blockmap sehen kann besteht aus mehreren komponenten/werten:
+ Blockmesh
+ MaterialID
+ Texturverschiebung
+ BlockFamily

Diese werden dann zusammengefast und daraus ermittelt wie die surface´s welche die map darstellen zusammengesetzt werden müssen.

Dies ist ein tatsächlicher blockaufbau:
Code: [AUSKLAPPEN]

[BLOCK:131]
name=erde mit grass
mesh0=block_1f
tsy0=0.1250
tsx0=0.0
mesh1=bush
tsy1=0.0
tsx1=0.0
family=ground


mesh0 und mesh1? also 2 meshes?
Sozusagen ja, jeder materialID kann ein mesh zugeordnet werden.

Idea die Material ID

Dies sind nur ein paar zeilen im steuerfile die angeben wie das material aussieht,
in dem .mat file befinden sich weitere infos wie texturen, shader einstellungen, und so weiter (dies ist von leadwerks)
Code: [AUSKLAPPEN]

[MATERIAL:0]
file=default.mat
clipping=true
texfilter=nearest


anhand von MATERIAL:X wird das material unter der ID X registriert.
Wenn ein block dieses material verwendet, hat er einen eintrag als meshX= verwendet der block dieses material nicht gibt es diesen eintrag einfach nicht.

das clipping=true gibt an, ob blöcke die mit diesem material gebaut werden später eine physix body bekommen, bzw ob ihre triangles in den clipping tree aufgenommen werden.

Normalerweise wird es wohl nur 2 material IDs geben, eine für den boden, wände etc, alles was clipping hat, und eine für alles was kein clipping hat (büsche, und son zeug).

Aber theoretisch kann man auch z.B. eine dritte einbauen wenn man möchte das einige teile von blöcken einen glüh effekt haben (via einen shader dann) oder was man immer auch machen möchte.

Idea das Blockmesh,
Ein blockmesh bastelt man einfach in Blender zusammen, und exportiert es als .ply, mit einem kleinen speziellen konverter wird dieses dann in ein eigenes 3d format namens .blo umgewandelt.
Warum das sein muss, und man nicht einfach direkt .ply oder gmf oder sonst ein anderes 3d format direkt nutzen kann liegt daran das in dem .blo noch weitere extra werte gespeichert werden, die indem konverter gesetzt werden müssen. Z.B. muss für Tri´s die sich am "blockrand" befinden ein side indicator eingegeben werden, damit tris die man eh nie sehen würde nachher beim zusammenbauen der surface ausgefiltert werden können.

Dies ist der sogenannte konverter:

user posted image

Dieses ding ist sehr improvisiert, aber es tut seinen job.

anhand der eintrages im steuerfile:
mesh0=block_1f
mesh1=bush
Ist also nun bekannt das dieser block das material 0 für block_1f.blo verwendet.
und das material 1 für bush.blo verwendet wird.

Idea texturverschiebung?

da ich es beknackt finden würde für jedes mögliche block ein eigenes .blo zu machen nur um die uv map anzupassen, gibt es die möglichkeit die gesamte UV map eines blockes einfach zu verschieben.
Das heist in blender muss man die UV map immer oben in der linken ecke erstellen:

user posted image

Dies ist ein block mit 3 seitentexturen (oben,alle 4 seiten, unten) (wie bei minecraft z.B. dirt)

durch
Code: [AUSKLAPPEN]

tsy0=0.1250
tsx0=0.0

wird die UV map aber nun nach unten verschoben um 0.1250 einheiten

das sieht dann so aus:

user posted image

Verschieben wir sie noch einmal um 0.0625 einheiten weiter nach unten sieht es schon ganz anders aus:

user posted image

(0.0625 entsprechen 64 pixel in meiner 1024x1024 textur) die werte werden in float angegeben damit sie unabhänig von der textur auflösung sind und man verschiedene textur auflösungen verwenden kann.

Dies klappt mit jeder erdenklichen form die man in blender baut, also es müssen nicht immer blöcke sein, theoretisch geht es mit jeder form (zuhoch sollte der tri count aber nicht gehen) wenn die textur clever aufgebaut ist, kann man so unzälige blöcke erstellen mit nur einer textur.
Natürlich ist es klug die uvmaps so anzuordnen das sie entweder immer in einem raster passen (64x64 pixel in diesem fall) oder aber wenn wie bei dem graß block über 3, dann auch andere texturen auser nur graß entsprechend anzuordnen, wie es z.B. bei dem mesh "mauer mit holz" der fall ist.
Diese beiden verwenden das gleiche blockmesh, nur ihre UV texturen sind anders verschoben. (wie oben in den bildern zu sehen)

Idea blockfamily:
die block family erlaubt es blöcke zu sortieren, z.B. könnte man eine family "Dungeonwand" erstellen, und alle blöcke welche zu dungeon wand gehören dort einsortieren.
Nun könnte man einfach sagen "setze dungeonwand an xyz" und es wird aus der family nach bestimmten kriterien eine dungeonwand ausgewählt, wahlweise abhänig von den nachbarblöcken (als sich verbindende wände etc, oder zufall, wie man mag) das ganze ist aber noch nicht ganz fertig.

Idea voll viel -.-

All diese vielen und komplizierten informationen werden wie beschrieben in einer abart ini datein gehalten,
heute habe ich mich dran gemacht und ein kleines tool geschrieben, um diese ini dateien zu bearbeiten.
es ist noch nicht ganz fertig, aber so sieht es aus:

user posted image

Hier kann ich nun bequem die blöcke aus der liste auswählen und sie bearbeiten, ihre family einstellen, und welche meshes sie für welche material ID verwenden und wie die jeweiligen UVmaps verschoben sind

Der dort erstellte stachelblock sieht dann im map editor so aus:

user posted image

Die stacheln haben in disem fall kein clipping, da sie zu Material:1 gehören.
es wäre auch unklug solche schon relativ complexen mesh daten in den clipping tree zu aufzunehmen.

Soviel zu diesem thema Smile

Ein Editor

Donnerstag, 10. Mai 2012 von AnniXa
Arrow Ein Editor?!

Heute Nachmittag und abend habe ich mich dran gemacht einen ersten Aufbau für einen Editor zu machen.
Bisher wurde alles über ini files geregelt und die "Map" hardcoded generiert (also der array mit den blockdaten).

Also dachte ich mir das ich einfach mal einen editor baue, der diese ini dateien ausliest und die werte bearbeiten kann und sie wieder speichern kann, sowie erstmal eine möglichkeit die map blockdaten zu bearbeiten und aus einem file zu lesen.

Für eine Spätere lua map generierung habe ich auch vorgesorgt und das im gui eingeplant.

Arrow Das Scenario system

Dies ist sehr von dem Spiel "clonk" inspiriert, ein Scenario ist ein ordner, in dem alles organisiert wird.
In diesem ordner befindet sich ein Steuerfile (scenario.scn) in welchem die Grundeigenschaften des Scenarios eingestellt sind.

Also dinge wie beschreibung, name etc

Code: [AUSKLAPPEN]

[GENERAL]
name=test
desc=Dies ist ein test
[MAPS]
startmap=test1


Ini verwende ich gern weil es damit sehr leicht möglich ist fix neue werte und so weiter hinzuzufügen, und andererseits diese auch schnell und einfach mit einem texteditor zu bearbeiten sind.

Wie man sieht gibt es auch einen eintrag "startmap" dazu kommen wir nun.
In einem Scenario ordner gibt es einen unterordner "maps", ein scenario kann also mehrere verschiedene maps beinhalten.
Ob und wie diese zur verwendung kommen hängt vom Scenario selbst ab, ein spieler kann durch Trigger auf eine andere map gesetzt werden, oder aber es kann vor dem start eine map ausgesucht werden.
Dies alles muss später in LUA geschrieben werden, standartmäsig wenn es keine lua funktion für den start gibt, wird man auf der map unter "startmap" anfangen.

ein map file ist auch wieder eine ini struktur
Code: [AUSKLAPPEN]

[GENERATOR]
source=test1.bm
sizex=128
sizey=8
sizez=128
[DISPLAY]
name=test eins
[BLOCK]
blockset=kerker.bsi
[SPAWN:0]
name=Entry
posx=10
posy=3
posz=10
[AMBIENT]
r=196
g=196
b=196
[SUN]
sun=true
yaw=25
pitch=45
r=255
g=255
b=255


Dies ist schon etwas mehr, unter generator kann eine map source eingestellt werden, jeh nach datei typ wird entweder eine map aus einem file geladen (.bm was soviel heissen soll wie binarymap)
oder später dann auch ein lua script ausgeführt, dies passiert bei .lua

Dann gibt es noch einträge für blockset (ein weiteres ini file, in welchem die eigenschaften wie texturierung, form, verhalten und gruppierungen der blöcke etc verwaltet werden, dazu später einmal mehr, da dies aus einer älteren blockmap version stammt kann es sein das ich dies nochmal ändern werde.)
sowie einträge für die spawnpoints und die lichteinstellung der map (ambient licht, sonnenwinkel, sonnenfarbe)

All diese daten wurden vom server bereits auch schon eingelesen und entsprechend verarbeitet bzw an die clienten übertragen.

Desweiteren befinden sich im maps ordner auch die .bm und später auch die .lua files für die jeweiligen maps.
Dann gibt es noch einen ordner namens "remote" in dem sich individuelle meshdaten, textur daten und so weiter befinden, der inhalt dieses ordners wird bei bedarf (also wenn die dateien fehlen oder die md5 summen nicht stimmen) an die clienten übertragen wichtig hierbei ist das die ini, .bm und .lua dateien NICHT an den spieler übertragen werden.


Arrow Und nun ein editor ?

Nun habe ich angefangen dafür ein Editor zu schreiben, in dem man ein scenario ordner auswählt, und dessen daten ggf geladen und angezeigt werden und teilweise auch schon bearbeitet werden können.
Als wirklich irgendwie nervig hat sich hierbei maxgui herausgestellt, ich hab es leider versäumt von anfang an eine gescheite verwaltung der gadgets und events hinzukriegen, so das ich nun ziemlich gemeine if/case bäume und tonnenweise globale variablen habe.
Also wenn ich den editor in 2 wochen nochmal überarbeiten möchte, werde ich ihn dann wohl eher neu schreiben müssen weil ich nicht mehr durchblicke Sad
Aber da dies auch erstmal nur ein Quick & Dirty editor ist der an einem tag entstanden ist, finde ich das soweit erstmal okay.

Bei editoren ist immer die frage, wie man eine gute bedienung hinbekommt, ich habe mich für 2 steuerungs methoden entschieden.
1. Numpad steuerung, diese steuermethode hatte ich bereits im älteren versionen, mit dem ziffernblock kann man einen cursor steuern, blöcke setzen und so weiter, und auch mit der maus blöcke setzen.
2. Ego/mouse view, mit WASD kann man sich ähnlich wie in einem shooter bewegen, mit rechter maustaste gedrückt halten die sicht drehen und mit der linken maustaste blöcke setzen.

Bei der zweiten methode ist es etwas umständlicher wenn mal blöcke in die luft setzen möchte, weil es mit glUnproject arbeitet und wenn nichts in der luft ist kann man da auch nichts treffen Smile
Als kleine abhilfe kann man die Umschalttaste gedrückt halten, dann wird der blöck über dem unter der maus gewählt

Zudem gibt es noch 2 extra cursor, die man mit den tasten 1 und 2 setzen kann.
(bei der numpad steuerung werden sie an die numpad cursor position gesetzt, ansonsten an die maus position)

Mit den 2 extra cursor´s kann man extra funktionen ausführen wie z.B. einen bereich füllen oder kopieren,
wer das plugin für bukkit/hmod "WorldEdit" kennt weis woher die inspiration dafür gekommen ist =)
Bis jetzt geht jedoch nur füllen,leeren, kopieren und einfügen.
wobei einfügen sich immer am roten cursor orientiert

Dies alles zu machen war nicht schwer, da ich das meiste schonmal irgendwann gemacht habe, und nun nurnoch die types und funktionen zusammen bringen musste.

Wer sich einen ersten eindruck davon verschaffen möchte kann sich den spaß hier herunterladen:

http://mapleinfo.de/editor_test.zip

Benutzung:
Ein scenario muss geladen werden (ein neues erstellen geht (noch) nicht).
Dazu im menu auf File->Scenario laden, und dann im ornder "/scen/test" die scenario.scn auswählen.
Danach kann man unten umschalten auf den tab "maps" und dort die map test1.map auswählen (doppelklick) und eine map dafür erstellen und diese bearbeiten.

Speichern und Laden etc sollte alles funktionieren soweit ich es ausgetestet habe Smile

Vieleicht findet ja jemand einen Fehler oder bug und/oder hat Verbesserungsvorschläge.

Ansonsten gibt es hier ein paar Bildchen:

user posted image
Ein smiley macht ja gute laune so heist es Smile


user posted image
Dank der kopieren / einfügen Funktionen mit dem tShematic type auch mehrfach.


user posted image
Abendliche Stimmung kann man mit den Lichteinstellungen verbreiten.

Das wars erstmal für heute =)

Was so das sein?

Mittwoch, 9. Mai 2012 von AnniXa
Wenn man "Block" liest, denkt man ja immer gleich an Minecraft.
Der Vergleich mit Minecraft ist aber hier nur teilweise gültig, wenngleich es etwas damit zu tun hat.

Es wird leider etwas viel Text, und viele Bilder auch, daher habe ich die Bilder als URL eingefügt, damit niemand gezwungen ist alle zu laden.

Arrow Geschichte

Als damals so 2009 oder so die ersten Minecraft Dinger auftauchten Hatte ich mir überlegt ein vergleichbares Blockmap System zu schreiben.
(das war damals glaube ich noch irgendeine beta obwohl es noch nicht die betas waren die es dann später gab oder so, also noch ohne Survival, einfach auf einer 256x256x256 (oder so) großen Map mit nem creative mode spielen).


Damals noch in B3D und kurz darauf dann in Blitzmax mit MiniB3d.

meine erste Interpretation hat so ausgesehen:

http://mapleinfo.de/mystuff/in...c1a2a7.png
http://mapleinfo.de/mystuff/in...4c029a.png

Da ich jedoch keinen weiteren Verwendungszweck dafür hatte, habe ich damit Erstmal nichts weiter gemacht und mich anderen Interessanteren Dingen zugewendet, z.B. Lieber Minecraft zu spielen als vergeblich versuchen es zu Kopieren ;D

Nach einer weile dann hatte ich mit einem freund (phillipk) vor ein Spiel zu machen, unter Verwendung dieser "engine", aber wir waren da wohl beide noch etwas zu unerfahren und wollten wohl zuviel (das gute alte mmorpg gemischt mit shooter und aufbau elementen) so das wir irgendwann uns zwischen zigtausend Zeilen dürftig Auskommentierten Code und vielen verschiedenen Dateien und eigenen kuriosen dateiformaten verirrt haben.
Es gab Probleme mit der Netzwerkübertragung, VBO bugs, gui Probleme und sonstige viele andere nerverein das wir beschlossen hatten es auf Eis zu legen und uns vorerst mehreren Kleineren Projekten zuzuwenden. =)

so hat das damals ausgesehen das projekt:
http://mapleinfo.de/mystuff/in...243ae6.png
http://mapleinfo.de/mystuff/in...7eb86c.png
Die block engine war damals jedoch schon recht vielseitig, wenn auch etwas undynamisch und sehr viel Hardcoded mit nahezu gigantischen IF/case bäumen.
Die netzwerk library war tibit.tnet, die wie wir leider nachher erst wusten so einige bugs und macken aufwies.

Question Und jetzt?

Inzwischen habe ich und auch phillipk für fast alle Probleme die es damals gab voneinander Unabhänige Einzellösungen geschrieben, und diese möchte ich nun zu einem Funktionierendem Spiel zusammenfügen.

Die einzelnen "Prototypen" die ich im laufe der zeit so geschrieben habe möchte ich euch gern Vorstellen:

Ann2d:
Ann2d ist ein Ersatz für max2d, da ich einige Dinge dort nervig fand, insbesondere mit Schriftarten und so weiter und ich einige extra Funktionen haben wollte.
Es ist in OpenGL geschrieben und kann alles fast was max2d kann und noch vieles mehr, und ist teilweise schneller, vorallem beim zeichnen großer texte, da diese auf wunsch beim erstellen einmalig als openGL array zum zeichnen mit DrawArray oder gar auch als VBO erstellt werden.
Eingefärbte Texte, mit Bitmapfonts, schriftformatierungen (größe, kursiv etc) sind damit möglich.

AnnGui:
Anngui baut auf ann2d auf und bietet Fenster, Buttons, Textfelder, Listen, Fortschrittsbalken und all den ganzen kram den man in einem gui so braucht.
Auch hier werden die fenster als DrawArray oder VBO erstellt.
Ann2d und Anngui gehen in normalem OpenGL, MiniB3D, Leadwerks und Ogre3d, ich denke ohne probleme auch in jeder anderen openGL basierten umgebung.

Bilder von kleineren Projekten mit Ann2d und Anngui gibt es hier:
http://mapleinfo.de/mystuff/in...bf2991.jpg
http://mapleinfo.de/mystuff/in...04b944.jpg
http://mapleinfo.de/mystuff/in...f89087.png

Lobby:
eine auf RakNet aufbauende Netzwerklobby inklusive chat, synchronisation von datei Ordnern, userlevel, einem system für server commands (/kick /start u.s.w.) und einem sehr flexiblem vote system (jeder server command kann mit /vote davor abgestimmt werden)
Ebenso wie ein flexibles server/game setting system.
das ganze sieht in etwa so aus:
http://mapleinfo.de/mystuff/in...b12ac9.png
http://mapleinfo.de/mystuff/lobby.png
Die Fenster und gui Elemente sind wie ihr sicher ahnen könnt mit AnnGui gemacht^^

Blockmap v3
Immernoch im grunde das selbe grundprinzip wie das erste blockmap system damals, nur etwas komplexer als z.B. bei minecraft, dafür aber nicht mit endlosen maps.
Mit Texturen die tilebar sind, Komplexeren meshes für die blöcke, blockToEntity und EntityToBlock transformationen, blockkategorien (blöcke aus der selben kategorie verbinden sich miteinander etc.) und viele andere spielerein.
Vor einigen wochen habe ich das ganze auch von MiniB3d zu Leadwerks portiert.

die sieht in dann so aus:
http://mapleinfo.de/mystuff/in...48139a.png
die texturen sind immernoch die selben Very Happy daher sieht das nicht wirklich neu aus, das einzigste neue ist der schattenwurf durch Leadwerks.

Sowie einige andere kleiner helferlein:
Iniloader - lädt datein im ini format aus (von Phillipk)
guiloader - lädt anweisungen für anngui fenster aus einem ini file (von phillipk)
tann3d - hängt 2d elemente (bilder und texte) an 3d objekte (entitys)
settingshandler - hält und verwaltet nicht nur Einstellungen, sondern auch gleich die informationen welche Einstellungen möglich sind, und kann Gui Fenster bauen wo man diese einstellen kann, und bietet Schnittstellen diese auszulesen und zu setzen, sowie diese mit raknet oder bnetex zu synchronisieren.

Idea Kombination!

Das ganze habe ich nun Gestern und Heute zu einem ersten nutzbaren klumpen Zusammengepappt.
Man kann nun einen Server aufmachen und die Leute können sich dort einloggen.
Jeh nachdem welche dateien für die aktuelle Spielwelt benötigt werden werden diese an die Clienten gesendet sofern nötig (vorher gibt es einen abgleich mit Md5 Prüfsummen wenn es die datei schon gibt ob updates/änderungen nötig sind).
Dabei werden falls nötig die kompletten mapdaten übertragen (texturen, mesh, mapfile etc).
Wenn man synchron ist und der server ein spiel am laufen hat kann man beitreten und "mitspielen".
Wobei ein spiel wirklich noch nicht vorhanden ist, man kann auf einer welt umherrennen und hüpfen und sich mit "eiern" beballern.
Es gibt weder eine schadensberechnung noch eine HP anzeige.

Testen konnte ich es bereits auf Localhost, im lan und auch schon 2 mal über internet.
Bisher funktionierte es ganz gut.
Ein paar Bilder von einem Localhost test:
http://mapleinfo.de/mystuff/synctest.png
http://mapleinfo.de/mystuff/synctest2.png
Erläuterung zu den bildern:
die bunten kugeln sind die Spieler^^
das lange ding unter den kugeln ist der Zeiger der anzeigt in welche Richtung der Spieler gerade zielt, auch das wird grob synchronisiert.
Gesteuert wird von oben mit einer WASD steuerung, und mit der maus zielen und schiesen.

Rolling Eyes Was wird nun daraus?

Geplant ist daraus ein spiel zu machen das sich vom gameplay in etwa an dem spiel "egoboo" orientiert.
http://www.youtube.com/watch?v=6lLAXr5Rl6E

Jedoch soll es hier nur über einen dedizierten Server laufen, auf welchem mittels LUA ein teil der spiellogik ausgelagert wird.
So das man verschiedene Spielmodi wie z.B. Deathmatch oder coop dungeons mit lua schreiben kann.
Wie weit das gehen wird steht noch in den Sternen, aufjedenfall soll aber die map erstellung mit Lua möglich sein, um so z.B. dynamische Dungeons zu ermöglichen oder einfach eine Map aus einem file laden, sowie die erstellung von Auslöser events (wenn personX block XYZ betritt lua script ausführen).

Warum das ganze?
Ich habe gerade viel zeit und Langeweile, das Wetter könnte auch besser sein also was soll ich sonst machen?
Das des Projekt wirklich mal etwas wird halte ich für unwahrscheinlich, allein weil ich schon keine lust und wohl auch nicht genug Fähigkeiten habe schöne models/animationen/texturen etc zu machen.

Und da ich in dieser Community schon viel gelernt habe, dachte ich mir das ich es mal wieder mit einem Worklog versuche und so vielleicht ein bisschen etwas zurückzugeben und ausserdem fällt einem oft die Lösung ein wenn man ein Problem versucht zu erklären =)