Vererbung und Create()
Übersicht

Soul ReaverBetreff: Vererbung und Create() |
![]() Antworten mit Zitat ![]() |
|
---|---|---|
So ich hab mich mal ein Bisschen mit BlitzMax gespielt und stehe vor jenem Problem:
Ich habe einen Typ "TButton"... Dann gibt es noch die Typen "TExitButton" "TSaveButton" usw., die alle von "TButton" erben: Code: [AUSKLAPPEN] Type TButton 'Hier gibt es ein paar Methoden, Fields und auch eine abstrakte Methode End Type Type TExitButton Extends TButton 'Hier gibt es eine Methode, die sich bei allen Buttons unterscheidet und folgende Funktion: Function Create:TExitButton(,x,y,width,height,value:String) Local t:TExitButton=New TExitButton t.x=x t.y=y t.width=width t.height=height t.value=value Return t End Function End Type Und diese Createfunktion habe ich in jedem Button (außer in "TButton"), obwohl sie immer dasselbe tut. Das schmerzt sehr. Da dachte ich mir, dass ich die Funktion schon "TButton" definiere, doch dann würde ja immer eine Instanz von "TButton" entstehen wenn ich z.B. "TExitButton.Create()" aufrufen würde... Irgendwelche Ideen? |
||
![]() |
Mr.HydeNewsposter |
![]() Antworten mit Zitat ![]() |
---|---|---|
Ich verstehe nicht ganz, warum du für jeden Button-Typ eine eigene Unterklasse erstellst. Speicher doch einfach in der Super Klasse was für eine Art Button es ist und behandel ihn danach. Dann brauchst du auch nicht für jeden eine eigene Methode bzw Funktion und nur für das, was nicht in der Super Klasse abgedeckt werden kann, erstellst du Unterklassen. Mir fällt jetzt aber nichts ein, was das sein sollte. | ||
BBP News RSS | Chaos Interactive | Watanien 2 Screens, Infos und Download | Watanien 2 Worklog | PuzzleMasters
http://abgeordnetenwatch.de - http://www.regierungs-beratung.de - Der Regierung auf die Finger schauen |
Soul Reaver |
![]() Antworten mit Zitat ![]() |
|
---|---|---|
Naja, natürlich könnte ich das so regeln, doch das wäre nicht sehr elegant. Dann würde die Methode, in der ein Klick behandelt wird, sehr lang werden, da ich ja noch mehr Buttons einbauen werde. Meine Struktur finde ich einfach viel übersichtlicher, als eine 1-Seiten Methode... | ||
![]() |
Mr.HydeNewsposter |
![]() Antworten mit Zitat ![]() |
---|---|---|
Hehe, das wäre sehr viel eleganter, weil du so ohne weiteres Buttons mit diversen Zwecken hinzufügen kannst. Den Event, den ein Button auslöst verwaltet man ja nicht in der Button Klasse sondern Beispielweise in der Eventklasse und wenn die von der Buttonklasse gesendet bekommt "Event-Exit_Game" dann macht die das und nicht, wie du das vor hast, der Button. So ist das extrem unübersichtlich und er Vorteil von OOP vollständig verspielt. | ||
BBP News RSS | Chaos Interactive | Watanien 2 Screens, Infos und Download | Watanien 2 Worklog | PuzzleMasters
http://abgeordnetenwatch.de - http://www.regierungs-beratung.de - Der Regierung auf die Finger schauen |
AvaGast |
![]() Antworten mit Zitat |
|
---|---|---|
Und noch eleganter ist meiner Ansicht nach ein einfacher, direkter Funktionspointer, der beim click aufgerufen wird ... ![]() |
||
![]() |
Jolinah |
![]() Antworten mit Zitat ![]() |
---|---|---|
Hier ein Beispiel mit einem Funktionszeiger:
Code: [AUSKLAPPEN] Type TButton
Field Click(button:TButton, mousebutton:Int, x:Int, y:Int) Method Update() If MouseOver() And MouseDown(1) And (Not Self.clicked) Then Self.clicked = True If Click <> Null Then 'Event bzw. Callback aufrufen Click(Self, 1, MouseX(), MouseY()) EndIf EndIf End Method ... End Type Local button1:TButton = TButton.Create(10, 10, 100, 20, "Ok") button1.Click = button1_Click Local button2:TButton = TButton.Create(10, 10, 100, 20, "Ok") button2.Click = button2_Click .... Function button1_Click(button:TButton, mousebutton:Int, x:Int, y:Int) Notify("Exit") End Function Function button2_Click(button:TButton, mousebutton:Int, x:Int, y:Int) Notify("Save") End Function ... So kannst du beliebig viele Buttons machen die etwas unterschiedliches auslösen. Aber um auf die eigentliche Frage bzw. das Problem zurück zu kommen: Das hat mich auch schon genervt... wär toll wenn der Konstruktor in BMax Parameter akzeptieren würde. |
||
- Zuletzt bearbeitet von Jolinah am Di, Feb 17, 2009 20:07, insgesamt einmal bearbeitet
![]() |
DaysShadow |
![]() Antworten mit Zitat ![]() |
---|---|---|
@ Ava: meinst du sowas?
Code: [AUSKLAPPEN] Function ButtonFunction()
'bla Button macht das was er machen soll EndFunction Type TButton Field FuncPtr() Method CallFunction() FuncPtr() EndMethod EndType Local button:TButton = New TButton button.Script = ButtonFunction button.CallFunction() ' oder eben auch button.FuncPtr() funzt ja genauso Edit: hehe, zwei mit ungefähr der gleichen idee ^^ ich bin ebenfalls auf das Problem gestoßen und hatte auch schon vor, das mit den Funktionszeigern zu erledigen, aber umgesetzt habe ich es noch nicht...hat man denn die selben Probs auch in C++ z.B? Ich erwäge nämlich ernsthaft mich von BB zu verabschieden ^^ |
||
Blessed is the mind too small for doubt |
AvaGast |
![]() Antworten mit Zitat |
|
---|---|---|
Jap, genau sowas in der Richtung meinte ich.
Naja, und was euer Create-Problem betrifft, so kann man sich einen Grossteil des gleichbleibenden Inhalts in einer Vererbung ersparen, wenn man diese Funktion lediglich ein Objekt erstellen lässt und anschliessend eine Setup-Method des übergeordneten Objektes mit den übergebenen Parametern aufruft. Okay, das erspart oft nur wenig Schreib- bzw. Kopierarbeit, aber es garantiert, dass man bei einer Veränderung sehr viel weniger Aufwand hat und sehr viel weniger Fehler produzieren kann. Mich hat euer "Problem" aber bisher nie wirklich gestört, da ich mir in der Regel eh für jedes Objekt eine eigenständige Funktion á la CreateButton:TButton ( parameter:blah ) "auslagere". ^^ |
||
![]() |
BtbN |
![]() Antworten mit Zitat ![]() |
---|---|---|
In C++ hat man solche probleme erstmal garnicht, weil man keine Buttons hat. Bei Qt ist es über ein Eventsystem geregelt, welches aber so in BMax nicht umsetzbar ist, da es in Bmax meines wissens nach nicht möglich ist eine Method anhand ihres Namens aufzurufen. Wenn das mittels refraction(o.ä.) doch möglich ist, liesse sich ein solches system zumindest ansatzweise auch in bmax umsetzen. | ||
![]() |
XeresModerator |
![]() Antworten mit Zitat ![]() |
---|---|---|
Es ist möglich, BtbN ![]() Eins der Beispiele des Reflection Moduls: Code: [AUSKLAPPEN] Strict
Type TMyType Method Update( t# ) Print "TMyType.Update:"+t End Method End Type Local obj:TMyType=New TMyType Local id:TTypeId=TTypeId.ForObject( obj ) Local update:TMethod=id.FindMethod( "Update" ) update.Invoke obj,[String( .25 )] |
||
Win10 Prof.(x64)/Ubuntu 16.04|CPU 4x3Ghz (Intel i5-4590S)|RAM 8 GB|GeForce GTX 960
Wie man Fragen richtig stellt || "Es geht nicht" || Video-Tutorial: Sinus & Cosinus THERE IS NO FAIR. THERE IS NO JUSTICE. THERE IS JUST ME. (Death, Discworld) |
![]() |
Firstdeathmaker |
![]() Antworten mit Zitat ![]() |
---|---|---|
Also ich habe es immer mit einem Message-System gelöst, das ich Function-Pointer nicht so dolle finde wenn ich alles schön OOP halten möchte:
Alle Menü's, Button's etc. sind von einer Hauptklasse TGUI oder so abgeleitet, welche eine Methode besitzt, welche Messages Empfangen und verarbeiten kann. Code: [AUSKLAPPEN] Type TGUI abstract Method recvMsg(msg:TMessage) abstract end type Type field id:string field content:object end type Wenn man jetzt einen Button erstellt, kann man diesem ein Target und eine Message übergeben, welche er an dieses schicken soll wenn er geklickt wurde. Das Zielobjekt sollte dann in der recvMsg-Methode allerdings auf diese Message regieren ![]() z.B.: Code: [AUSKLAPPEN] Type Menueobject Extends TGUI Method init() Local b:TButton = New TButton b.onClickMsg = New TMessage b.onClickMsg.id = "end" b.onClickTarget = self End Method Method recvMsg(msg:TMessage) Select msg.id Case "end" End End Select End Method End Type Type Button Extends TGUI Field onClickMsg:TMessage Field onClickTarget:TGUI Method logic() If mouseover() And mouseclick() logicClick() End Method Method logicClick() onClickTarget.recvMsg(onClickMsg) End Method Method recvMsg(msg:TMessage) End Method End Type |
||
www.illusion-games.de
Space War 3 | Space Race | Galaxy on Fire | Razoon Gewinner des BCC #57 User posted image |
AvaGast |
![]() Antworten mit Zitat |
|
---|---|---|
Zitat: Also ich habe es immer mit einem Message-System gelöst, das ich Function-Pointer nicht so dolle finde wenn ich alles schön OOP halten möchte
Also diese Aussage verstehe ich nun gar nicht O_o Ich finde ein solches Massagesystem in diesem Bezug unnötig und umständlich und unnötig umständlich (*g*). Es löst auf grossen Umwegen etwas, dass sich auf einem anderem Wege sehr viel einfacher, schneller und effektiver abhandeln lässt ![]() ![]() |
||
Dreamora |
![]() Antworten mit Zitat ![]() |
|
---|---|---|
MessageSysteme sind extrem mächtig und sie lösen einige der Probleme die 10'000 vererbungen und Unterklassen überhaupt erst erzeugen.
Speziell wenn man das MessageSystem mit einem Komponenten System (also gekapselte Funktionalität die man an eine Trägerklasse anhängen kann) kombiniert, erreicht man damit eine einfachheit im design die nicht wirklich zu übertreffen ist. Als kleines Gedankenbeispiel: Du hast eine Kriegerklasse, die kann angreifen Der Krieger hat eine peitsche und flügel Wenn du das ganze nun animieren willst, sagen wir "Angriff!", verlagt das, dass der krieger sich bewusst ist, was er überhaupt am körper haben kann (nicht im sinn vom item type, aber im sinn von welcher slot etc) und das zu compile zeit, und das dann anweist zu animieren. Das ist nicht sonderlich flexibel, denn so sind die slots fix definiert, wenn du mehr brauchst musst du den code ändern und recompilen. Jetzt nehmen wir das ganze mal als Komponenten - Message System. Hier haben wir einen Krieger mit einem Komponentenmanager. Das wars. Der Komponentenmanager, unabhängig vom Krieger, enthält die Animationsdaten des Kriegers, aber auch die Peitsche und die Flügel Wenn jetzt der Krieger angreift kann etwas von aussen oder der Krieger selbst, dem Komponentenmanager die Nachricht "Angriff!" durchgeben ohne zu wissen was sie in der blackbox damit macht. Dennoch werden brav alle dinge korrekt ausgeführt denn der komponentenmanager broadcasted diese Message an alle angehängt Komponenten. Für kleine spielereien mag der weg des hardcodings ja noch funktionieren. Aber schon ein tile based RPG mit ein wenig scripting und flexibilität profiert bereits in extremem Masse davon das man flexible moderne OO Ansätze nutzt um solche Dinge zu lösen und nicht mit "Höhlenmalereien" (reine Verarbung und ähnliche Ansätze die so seit mehr als einem Jahrzehnt nicht mehr wirklich genutzt werden an orten wo man interesse daran hat geld zu sparen, wegen der erheblichen Folgekosten die ihr Unterhalt mit sich bringt) versucht eine Lösung aufzuzeichnen. |
||
Ihr findet die aktuellen Projekte unter Gayasoft und könnt mich unter @gayasoft auf Twitter erreichen. |
![]() |
Firstdeathmaker |
![]() Antworten mit Zitat ![]() |
---|---|---|
@ Ava: Seh ich total anders, hab mal den zwischenstand einer kleinen GUI angehängt um das zu verdeutlichen.
Ich hab ein Basis-GUI Element, von dem alle anderen GUI-Elemente abgeleitet werden. Dabei unterscheide ich zwischen Basiselementen (Abstract) und Finalen, welche jeweils static Konstruktoren bekommen. Die Types TMessage und TAction sind Kommunikationsobjekte. Über TAction kann man Aktionen definieren, wie z.B. bei einem Button wenn er geklickt wurde. Diese Actions können alles mögliche machen, aber vor allem kann man über die Action TGUI_SendMessageAction dem Button den Befehl geben, eine Message an ein anderes GUI_Element zu schicken (hier das Menü). Über die Messages können sich die GUI-Elemente untereinander abstimmen. (Man könnte in meinem Beispiel genausogut eine Action erstellen, welche einen Funktionspointer übergeben bekommt und diesen dann ausführt.) Ein Menü (TGUI_MainMenue) ist wiederum eine Ableitung aus der Basisklasse TGUI_Element, nur dass hier die processMessage() methode implementiert wurde. Ich finde die Klasse TGUI_MainMenue übrigens nicht sehr kompliziert, man sieht doch relativ gut was sie macht, oder? Lauffähiges Beispiel: Code: [AUSKLAPPEN] 'TEST Graphics 800,600 Global GUI:TGUI_Element = New TGUI_MainMenue Repeat GUI.Process() Cls GUI.render() Flip Until AppTerminate() End Type TGUI_MainMenue Extends TGUI_Element Final Method New() elementType = "MainMenue" TGUI_Message.Create("InitRoot" , Self , Self).send() End Method Method processMessage(m:TGUI_Message) Super.processMessage(m) Select m.id Case "end" End Case "InitRoot" Self.removeChildren() TGUI_RectButton.CreateSimple(300 , 270 , 200 , 30 , "Start" , "InitStart" , Self) TGUI_RectButton.CreateSimple(300 , 300 , 200 , 30 , "Options" , "InitOptions" , Self) TGUI_RectButton.CreateSimple(300 , 330 , 200 , 30 , "End" , "end" , Self) Case "InitStart" Self.removeChildren() TGUI_RectButton.CreateSimple(300 , 300 , 200 , 30 , "Back" , "InitRoot" , Self) Case "InitOptions" Self.removeChildren() TGUI_RectButton.CreateSimple(300 , 270 , 200 , 30 , "SFX" , "InitSfx" , Self) TGUI_RectButton.CreateSimple(300 , 300 , 200 , 30 , "Back" , "InitRoot" , Self) Case "InitSfx" Self.removeChildren() TGUI_RectButton.CreateSimple(300 , 300 , 200 , 30 , "Back" , "InitOptions" , Self) End Select End Method End Type '############ IMPLEMENTATION OF TGUI_Action ############### Type TGUI_SendMessageAction Extends TGUI_Action Final Field id:String Field source:TGUI_Element Field target:TGUI_Element Field content:Object Method process() TGUI_Message.Create(id,source,target,content).send() End Method 'Functions Function Create:TGUI_SendMessageAction(id:String , source:TGUI_Element , target:TGUI_Element , content:Object = Null) Local a:TGUI_SendMessageAction = New TGUI_SendMessageAction a.id = id a.source = source a.target = target a.content = content Return a End Function End Type '############ IMPLEMENTATIONS OF TGUI_Element ############### Rem bbdoc: A simple button with 2 different images and a "on Click" action. End Rem Type TGUI_ImageButton Extends TGUI_Element Final Field image:TImage[2] Method New() elementType = "ImageButton" End Method Method setImage(off:TImage , on:TImage) image[0] = off image[1] = on calcButtonSize() End Method Method calcButtonSize() Local w:Float = Max(ImageWidth(image[0]) , ImageWidth(image[1]) ) Local h:Float = Max(ImageHeight(image[0]) , ImageHeight(image[1]) ) Self.setSIze(w,h) calcSize() End Method Field onClickAction:TGUI_Action Method setOnClickAction(action:TGUI_Action) Self.onClickAction = action End Method Field mouseOver:Byte Method process() Super.process() mouseOver = overElement(MouseX() , MouseY() ) If mouseOver And MouseHit(1) processClick() EndIf End Method Method processClick() If onClickAction onClickAction.process() End Method Method render() Super.render() SetColor 255,255,255 DrawImage Self.image[mouseOver],Self.position[0],Self.position[1] End Method 'Functions Function CreateSimple:TGUI_ImageButton(x:Float,y:Float,image0:TImage , image1:TImage , cmd:String , parent:TGUI_Element) Local b:TGUI_ImageButton = New TGUI_ImageButton Local a:TGUI_Action = New TGUI_SendMessageAction b.setPosition(x,y) b.setImage(image0 , image1) b.setOnClickAction(TGUI_SendMessageAction.Create(cmd , b , parent , Null) ) b.setParent(parent) Return b End Function End Type Rem bbdoc: A very simple Button, with options for text and colors and a onClick action End Rem Type TGUI_RectButton Extends TGUI_Element Final Field text:String Field overColor:TColor = New TColor Field basicColor:TColor = New TColor Field textColor:TColor = New TColor Method New() elementType = "RectButton" overColor.setInt($FFFFFFFF) basicColor.setInt($FF90909090) textColor.setInt($FF000000) End Method Field onClickAction:TGUI_Action Method setOnClickAction(action:TGUI_Action) Self.onClickAction = action End Method Field mouseOver:Byte Method process() Super.process() mouseOver = overElement(MouseX() , MouseY() ) If mouseOver And MouseHit(1) processClick() EndIf End Method Method processClick() If onClickAction onClickAction.process() End Method Method render() Super.render() If mouseOver overColor.Apply() Else basicColor.Apply() EndIf DrawRect position[0] , position[1] , size[0] , size[1] textColor.Apply() DrawText Self.text,position[0] + (size[0] - TextWidth(text))/2,position[1] + (size[1] - TextHeight(text))/2 End Method 'Functions Function CreateSimple:TGUI_RectButton(x:Float,y:Float,width:Float,height:Float,text:String, cmd:String , parent:TGUI_Element) Local b:TGUI_RectButton = New TGUI_RectButton Local a:TGUI_Action = New TGUI_SendMessageAction b.setPosition(x,y) b.setSize(width,height) b.setOnClickAction(TGUI_SendMessageAction.Create(cmd,b,parent,Null)) b.setParent(parent) b.text = text Return b End Function End Type '################ BASIC TYPES OF GUI ############################### Type TGUI_Element Abstract 'Big Main Methods Method process() processView() processChildren() processMessages() End Method Method render() renderChildren() End Method Method remove() setParent(Null) End Method 'Id Field id:String = "NoName" Field elementType:String = "Element" Method setId(id:String) Self.id = id End Method 'Parent / Child Field parent:TGUI_Element Field parentLink:TLink Field children:TList = New TList Method setParent(p:TGUI_Element) If Self.parentLink RemoveLink(Self.parentLink) Self.parent = p If p<>Null Self.parentLink = p.children.addlast(Self) End Method Method addChildren(c:TGUI_Element) If c = Null Return c.SetParent(Self) End Method Method processChildren() For Local c:TGUI_Element = EachIn children c.process() Next End Method Method renderChildren() For Local c:TGUI_Element = EachIn children c.render() Next End Method Method removeChildren() For Local c:TGUI_Element = EachIn children c.remove() Next End Method Method setViewDirtyChildren() For Local c:TGUI_Element = EachIn children c.viewDirty = True Next End Method 'View Field position:Float[2] 'upper left corner of element DONT WRITE THIS Field size:Float[2] 'outer size of element DONT WRITE THIS Field size_inner:Float[2]'inner size of element DONT WRITE THIS Field viewDirty:Byte 'means, next turn, everything needs an update Field border_abs:Float[4] 'element border size, 0=left 1=upper 2=right 3=lower Field size_abs:Float[2] 'this is the "normal outer size the user should see and manipulate" Field size_rel:Float[2] 'rel to parent Field position_abs:Float[2] 'this is the "normal position the user should see and manipulate" Field position_rel:Float[2] 'rel to parent size Field position_handleAbs:Float[2] Field position_handleRel:Float[2] Rem bbdoc: set absolute position of this element End Rem Method setPosition(x:Float , y:Float) position_abs[0] = x position_abs[1] = y position_rel[0] = 0 position_rel[1] = 0 viewDirty = True End Method Rem bbdoc: sets absolute outer size End Rem Method setSize(w:Float , h:Float) size_abs[0] = w size_abs[1] = h size_rel[0] = 0 size_rel[1] = 0 viewDirty = True End Method Rem bbdoc: sets inner size of element (changes also outer size!) End Rem Method setInnerSize(w:Float , h:Float) size_abs[0] = w + border_abs[0] + border_abs[2] size_abs[1] = h + border_abs[1] + border_abs[3] size_rel[0] = 0 size_rel[1] = 0 viewDirty = True End Method Rem bbdoc: set border sizes in pixel End Rem Method setBorder3(w:Float) setBorder2(w , w ) End Method Rem bbdoc: set border sizes in pixel w = side, h=up&down End Rem Method setBorder2(w:Float , h:Float) setBorder(w , h , w , h) End Method Rem bbdoc: set border sizes in pixel l=left, u=up, r=right, d=down End Rem Method setBorder(l:Float , u:Float , r:Float , d:Float) Self.border_abs[0] = l Self.border_abs[1] = u Self.border_abs[2] = r Self.border_abs[3] = d viewDirty = True End Method Rem bbdoc: refreshes position and size if viewDirty flag is set. End Rem Method processView() If Not Self.viewDirty Return calcSize() calcPos() setViewDirtyChildren() Self.viewDirty = False End Method Method calcPos() position[0] = position_abs[0] + position_handleAbs[0] + position_handleRel[0]*Self.size[0] position[1] = position_abs[1] + position_handleAbs[1] + position_handleRel[1]*Self.size[1] If parent position[0]:+parent.position[0] + parent.border_abs[0] + parent.position[0] * position_rel[0] position[1]:+parent.position[1] + parent.border_abs[1] + parent.position[1] * position_rel[1] EndIf End Method Method calcSize() size[0] = size_abs[0] size[1] = size_abs[1] If parent size[0]:+ parent.size_inner[0] * size_rel[0] size[1]:+ parent.size_inner[1] * size_rel[1] EndIf size_inner[0] = size[0] - border_abs[0] - border_abs[2] size_inner[1] = size[1] - border_abs[1] - border_abs[3] End Method Method overElement:Byte(x:Float,y:Float) If x > position[0] And x < position[0] + size[0] If y > position[1] And y < position[1] + size[1] Return True EndIf EndIf Return False End Method 'Messages Field messages:TList = New TList Method recvMessage:TLink(msg:TGUI_Message) Return Self.messages.addlast(msg) End Method Method processMessages() For m:TGUI_Message = EachIn Self.messages processMessage(m) m.remove() Next End Method Method processMessage(m:TGUI_Message) End Method End Type Type TGUI_Message Final Field id:String Field source:TGUI_Element Field target:TGUI_Element Field content:Object Field _link:TLink Method send() _link = target.recvMessage(Self) End Method Method remove() If _link RemoveLink(_link) End Method Function Create:TGUI_Message(id:String , source:TGUI_Element , target:TGUI_Element , content:Object = Null) Local m:TGUI_Message = New TGUI_Message m.id = id m.source = source m.target = target m.content = content Return m End Function End Type Type TGUI_Action Abstract Method process() End Method End Type Type TColor Field a:Int Field r:Int Field g:Int Field b:Int Method New() a = 0 r = 255 g = 255 b = 255 End Method Function Create:TColor(alpha:Byte, RED:Byte, green:Byte, blue:Byte) Local c:TColor = New TColor c.Set(alpha:Byte, RED:Byte, green:Byte, blue:Byte) Return c End Function Function CreateInt:TColor(color:Int) Local c:TColor = New TColor c.SetInt(color) Return c End Function Method Set(alpha:Byte, RED:Byte, green:Byte, blue:Byte) Self.a = alpha Self.r = RED Self.g = green Self.b = blue End Method Method SetInt(color:Int) Self.a = color Shr 24 Self.r = ((color Shl 8) Shr 8) / $10000 Self.g = ((color Shl 16) Shr 16) / $100 Self.b = ((color Shl 24) Shr 24) End Method Method Apply() SetColor r, g, b SetAlpha (Float(a) / 255.0) End Method End Type Anmerkung: Die beiden Button-Types sind nur Beispielhaft, das ganze muss natürlich noch über Styleklassen variabel gemacht werden. Zudem braucht man noch ein richtiges State-System (um zwischen verschiedenen Programstates wie Menü, Spiel, Highscores umschalten zu können) sowie ein System um Frames über anderen einzuzeichnen, zu fokussieren etc. |
||
www.illusion-games.de
Space War 3 | Space Race | Galaxy on Fire | Razoon Gewinner des BCC #57 User posted image |
![]() |
Jolinah |
![]() Antworten mit Zitat ![]() |
---|---|---|
Message-Patterns find ich auch sehr schön, allerdings - aber das ist wohl Geschmackssache - würd ich mit Messages nicht das Standardverhalten eines Objektes quasi festlegen.
Vielleicht hab ich beim Überfliegen des Codes nicht alles verstanden, aber bei deiner Implementation vom MainMenue scheint das ja immer genau die gleichen Elemente zu enthalten, oder ist es so gedacht dass ein GUI-Benutzer sich so dann seinen eigenen Type für's Menu erstellt? Jedenfalls find ich persönlich Objekte wo man mit Methoden dynamisch Unterobjekte usw. hinzufügen kann viel schöner, als wenn der Type selber schon definiert welche Untermenüs erstellt werden etc., z.B: Code: [AUSKLAPPEN] Local menu:TGUI_MainMenue = new TGUI_MainMenue
Local itemFile:TGUI_MenuItem = menu.AddItem("Datei") itemFile.AddItem("Öffnen").setOnClickAction(...) ... Aber wie gesagt, das ist einerseits Geschmackssache und andererseits abhängig von der jeweiligen Anwendung/Verwendung ![]() |
||
![]() |
Firstdeathmaker |
![]() Antworten mit Zitat ![]() |
---|---|---|
Zitat: oder ist es so gedacht dass ein GUI-Benutzer sich so dann seinen eigenen Type für's Menu erstellt?
genau! Im Endeffekt hat man für jeden State einen eigenen Type: TMainMenueState TOptionState TGameState THighscoreState und ein einziges globales Type welches diesen ganzen Menüs nochmal übergeordnet ist. |
||
www.illusion-games.de
Space War 3 | Space Race | Galaxy on Fire | Razoon Gewinner des BCC #57 User posted image |
![]() |
Jolinah |
![]() Antworten mit Zitat ![]() |
---|---|---|
Ah ok, ich hätte jetzt für die Buttons noch eine Basisklasse gemacht (abgeleitet von TGUI_Element), da sich das MouseOver und Click wiederholt und das MainMenü wie oben erwähnt etwas genereller gestaltet, aber ansonsten find ich es wirklich gut. Ist eigentlich das woran ich gedacht hatte, hab es vorhin wahrscheinlich nur etwas zu schnell überflogen ![]() Je nach Situation wärs vielleicht auch noch praktisch wenn einem Event mehrere Actions zugeteilt werden könnten (damit man nicht 1 Action hat, die zuviel auf einmal macht, zur besseren Wiederverwendung/Aufteilung von Actions). Aber das liesse sich bei Bedarf ja ganz einfach über eine spezielle Action machen, die mehrere untergeordnete Actions enthält und ausführt. |
||
Übersicht


Powered by phpBB © 2001 - 2006, phpBB Group