Hallo ich möchte mit linexy() oder line() einen Tacho machen, den man aber auch bewegen kann. Kann mkir da irgndwie jemand helfen??
danke schonmal im Voraus
Tacho
Also einen analogen Tacho mit Zeigern? Dann solltest du dich mit Sinus, Cosinus und Tangents auskennen. Diese wirst du brauchen zur Berechnung wie lang der Zeiger in bestimmten Winkellagen sein soll.
Dazu zeichne dir mal auf, wie der Zeiger liegen könnte. Etwa so:
Der Strich nach oben rechts ist der Zeiger, unten ist die horizontale Achse. Das "a" ist der Winkel unter dem Zeiger. Die vertikale Linie rechts ist eine gedankliche Linie von Zeigerspitze zur horizintalen Achse.
Schon hast du ein rechtwinkliges Dreieck welches du berechnen kannst. Du brauchst also den Winkel a und musst wissen wie lang der Zeiger ist (solltest du dir vorher überlegen, versteht sich) und kannst dann errechnen wo wie weit die Zeigerspitze nach rechts gehen muss.
Das geht dann so:
umgestellt nach der X-Strecke ergibt sich:
Somit musst du den cosinus() des Winkels berechnen und z ist die Länge des Zeigers, dann erhälst du schonmal die erste koordinate für die Linie des Zeigers. Um nun noch die Höhe zu erhalten, könnte man den Sinus nehmen:
umgestellt nach der Y-Strecke ergibt sich:
Schon hast du auch diese Strecke. Dein Zeiger müsste dann so angezeigt werden:
line(0,0, X-strecke, Y-strecke)
Alles aber setzt vorraus dass du den Winkel des Zeigers kennst. Das sollte aber kein Problem sein. Wenn der Halbkreis 180 Grad sind, und du etwa 200 Km/h als volle halbe Drehung anzeigen willst, und der Tache jetzt auf 100 Km/h steht, sind das also 90 Grad, also ist der Winkel dann 90 Grad groß.
Das war jetzt ein Beispiel für den positiven Halbkreis des Tachos. Wenn es ein kompletter Kreis werden soll, musst du mein Muster von oben noch übertragen auf den unteren Kreis. Da legst du wieder ein Dreieck an und kannst per Sinus und Cosinus die Seiten (also die Kooridnaten des Zeigers) berechnen.
Dazu zeichne dir mal auf, wie der Zeiger liegen könnte. Etwa so:
Code: Alles auswählen
/|
/ |
/ |
/ |
/ |
z / |
/ |
/\ |
/ \ |
______/_a_)_____|
Schon hast du ein rechtwinkliges Dreieck welches du berechnen kannst. Du brauchst also den Winkel a und musst wissen wie lang der Zeiger ist (solltest du dir vorher überlegen, versteht sich) und kannst dann errechnen wo wie weit die Zeigerspitze nach rechts gehen muss.
Das geht dann so:
Code: Alles auswählen
cos(a) = X-Strecke / zCode: Alles auswählen
X-Strecke = cos(a) * zCode: Alles auswählen
sin(a) = Y-Strecke / zCode: Alles auswählen
Y-Strecke = sin(a) * zline(0,0, X-strecke, Y-strecke)
Alles aber setzt vorraus dass du den Winkel des Zeigers kennst. Das sollte aber kein Problem sein. Wenn der Halbkreis 180 Grad sind, und du etwa 200 Km/h als volle halbe Drehung anzeigen willst, und der Tache jetzt auf 100 Km/h steht, sind das also 90 Grad, also ist der Winkel dann 90 Grad groß.
Das war jetzt ein Beispiel für den positiven Halbkreis des Tachos. Wenn es ein kompletter Kreis werden soll, musst du mein Muster von oben noch übertragen auf den unteren Kreis. Da legst du wieder ein Dreieck an und kannst per Sinus und Cosinus die Seiten (also die Kooridnaten des Zeigers) berechnen.
ich habe mal eine analog Uhr gemacht.
(jaja, heute würde ich das resize und das ruckeln anders machen, aber für zum zeigen wie nen Tacho geht langt es hoffe ich)
(jaja, heute würde ich das resize und das ruckeln anders machen, aber für zum zeigen wie nen Tacho geht langt es hoffe ich)
Code: Alles auswählen
; Variablen und Konstanten initialisieren
#version="(c) oppi 2003, V1.70"
#appname="ANACLOX"
#ininame="anaclox.ini"
Global width, height, winx, winy
Global box.l,s, PI2.f, PI.f, xm, ym, radius
Global tickcol.l, seccol.l, mincol.l, hcol.l, backcol.l, boxcol.l, jewcol.l, txtcol.l
Global tid.l, info$, font.l,s.l,os.l
Global flags.l
PI2=ATan(1)*8
PI=ATan(1)*4
Structure xy
xa.l
ya.l
xe.l
ye.l
xb.l
yb.l
xc.l
yc.l
xf.l
yf.l
EndStructure
Dim ticks.xy(60)
Dim secs.xy(60)
Dim mins.xy(60)
Dim hrs.xy(60)
Dim M$(12)
M$(1)="JAN"
M$(2)="FEB"
M$(3)="MAR"
M$(4)="APR"
M$(5)="MAY"
M$(6)="JUN"
M$(7)="JUL"
M$(8)="AUG"
M$(9)="SEP"
M$(10)="OCT"
M$(11)="NOV"
M$(12)="DEZ"
;- GUI Konstanten
#win=0
#clock=0
#set=0
#OnTop=0
#ShowDay=1
#ShowMonth=2
#ShowYear=3
#ShowInfo=4
#setInfo=5
#default=8
#ver=9
#quit=10
#seccol=11
#mincol=12
#hrscol=13
#jewcol=14
#txtcol=15
#backcol=16
#boxcol=17
#tickcol=18
Procedure LoadPrefs(ininame.s)
OpenPreferences(ininame)
info$ =ReadPreferenceString("info",#version)
width =ReadPreferenceLong("width",300)
height =ReadPreferenceLong("height",300)
winx =ReadPreferenceLong("winx",GetSystemMetrics_(#SM_CXSCREEN)/2-width/2)
winy =ReadPreferenceLong("winy",GetSystemMetrics_(#SM_CYSCREEN)/2-height/2)
boxcol =ReadPreferenceLong("boxcol",$FFFFFF)
backcol=ReadPreferenceLong("backcol",$FFFFFF)
tickcol=ReadPreferenceLong("tickcol",$AAAAAA)
jewcol =ReadPreferenceLong("jewcol",$00FFFF)
seccol =ReadPreferenceLong("seccol",$0000FF)
mincol =ReadPreferenceLong("mincol",$00FF00)
hcol =ReadPreferenceLong("hcol",$FF0000)
txtcol =ReadPreferenceLong("txtcol",$111111)
flags =ReadPreferenceLong("flags",1+2+16)
ClosePreferences()
EndProcedure
Procedure savePrefs(ininame.s)
CreatePreferences(ininame)
WritePreferenceString("info",info$)
WritePreferenceLong("width",WindowWidth())
WritePreferenceLong("height",WindowHeight())
WritePreferenceLong("winx",WindowX())
WritePreferenceLong("winy",WindowY())
WritePreferenceLong("boxcol",boxcol)
WritePreferenceLong("backcol",backcol)
WritePreferenceLong("tickcol",tickcol)
WritePreferenceLong("jewcol",jewcol)
WritePreferenceLong("seccol",seccol)
WritePreferenceLong("mincol",mincol)
WritePreferenceLong("hcol",hcol)
WritePreferenceLong("txtcol",txtcol)
WritePreferenceLong("flags",flags)
ClosePreferences()
EndProcedure
Procedure resetPrefs(ininame.s)
CreatePreferences(ininame)
ClosePreferences()
LoadPrefs(ininame)
EndProcedure
Procedure DrawClock()
xm=WindowWidth()/2 : ym=WindowHeight()/2
If ym<xm : radius=ym*0.98 : Else : radius=xm*0.98 : EndIf
font = LoadFont(0, "comic sans ms", radius*0.06)
;- Koordinaten berechnen
a.f=PI2 : t=0
While a >= 0
ticks(t)\xa=Sin(a+PI)*(radius*0.91)+xm
ticks(t)\ya=Cos(a+PI)*(radius*0.91)+ym
ticks(t)\xb=Sin(a+PI+PI/40)*(radius*0.89)+xm
ticks(t)\yb=Cos(a+PI+PI/40)*(radius*0.89)+ym
ticks(t)\xc=Sin(a+PI-PI/40)*(radius*0.89)+xm
ticks(t)\yc=Cos(a+PI-PI/40)*(radius*0.89)+ym
ticks(t)\xf=Sin(a+PI)*(radius*0.89)+xm
ticks(t)\yf=Cos(a+PI)*(radius*0.89)+ym
ticks(t)\xe=Sin(a+PI)*(radius*0.87)+xm
ticks(t)\ye=Cos(a+PI)*(radius*0.87)+ym
secs(t)\xa=Sin(a+PI)*(radius*0.10)+xm
secs(t)\ya=Cos(a+PI)*(radius*0.10)+ym
secs(t)\xe=Sin(a+PI)*(radius*0.84)+xm
secs(t)\ye=Cos(a+PI)*(radius*0.84)+ym
secs(t)\xf=Sin(a+PI)*(radius*0.75)+xm
secs(t)\yf=Cos(a+PI)*(radius*0.75)+ym
mins(t)\xa=Sin(a+PI)*(radius*0.10)+xm
mins(t)\ya=Cos(a+PI)*(radius*0.10)+ym
mins(t)\xb=Sin(a+PI+PI/40)*(radius*0.60)+xm
mins(t)\yb=Cos(a+PI+PI/40)*(radius*0.60)+ym
mins(t)\xc=Sin(a+PI-PI/40)*(radius*0.60)+xm
mins(t)\yc=Cos(a+PI-PI/40)*(radius*0.60)+ym
mins(t)\xf=Sin(a+PI)*(radius*0.60)+xm
mins(t)\yf=Cos(a+PI)*(radius*0.60)+ym
mins(t)\xe=Sin(a+PI)*(radius*0.80)+xm
mins(t)\ye=Cos(a+PI)*(radius*0.80)+ym
hrs(t)\xa=Sin(a+PI)*(radius*0.10)+xm
hrs(t)\ya=Cos(a+PI)*(radius*0.10)+ym
hrs(t)\xb=Sin(a+PI+PI/20)*(radius*0.50)+xm
hrs(t)\yb=Cos(a+PI+PI/20)*(radius*0.50)+ym
hrs(t)\xc=Sin(a+PI-PI/20)*(radius*0.50)+xm
hrs(t)\yc=Cos(a+PI-PI/20)*(radius*0.50)+ym
hrs(t)\xf=Sin(a+PI)*(radius*0.50)+xm
hrs(t)\yf=Cos(a+PI)*(radius*0.50)+ym
hrs(t)\xe=Sin(a+PI)*(radius*0.70)+xm
hrs(t)\ye=Cos(a+PI)*(radius*0.70)+ym
a-PI2/60
t+1
Wend
;- Ziffernblatt
box = CreateImage(0, 2*xm,2*ym)
StartDrawing(ImageOutput())
Box(0, 0,2*xm, 2*ym,boxcol)
Circle(xm,ym,radius,tickcol)
Circle(xm,ym,radius*0.95,backcol)
Circle(xm,ym,radius*0.09,tickcol)
For t=0 To 59
If t=0 Or t=15 Or t=30 Or t=45
LineXY(ticks(t)\xa,ticks(t)\ya,ticks(t)\xb,ticks(t)\yb,tickcol)
LineXY(ticks(t)\xb,ticks(t)\yb,ticks(t)\xe,ticks(t)\ye,tickcol)
LineXY(ticks(t)\xe,ticks(t)\ye,ticks(t)\xc,ticks(t)\yc,tickcol)
LineXY(ticks(t)\xc,ticks(t)\yc,ticks(t)\xa,ticks(t)\ya,tickcol)
FillArea(ticks(t)\xf,ticks(t)\yf,tickcol,jewcol)
ElseIf t=5 Or t=10 Or t=20 Or t=25 Or t=35 Or t=40 Or t=50 Or t=55
Circle(ticks(t)\xf,ticks(t)\yf,radius*0.02,jewcol)
DrawingMode(4)
Circle(ticks(t)\xf,ticks(t)\yf,radius*0.02,tickcol)
DrawingMode(0)
Else
LineXY(ticks(t)\xa,ticks(t)\ya,ticks(t)\xe,ticks(t)\ye,tickcol)
EndIf
Next
StopDrawing()
EndProcedure
Procedure tick(value.l)
Repeat
s=Second(Date())
If s<>os
m=Minute(Date())
h=Hour(Date())
If h > 12 : h=h-12 : EndIf
h=h*5+m/12
If h > 60 : h=h-60 : EndIf
d$=""
UseImage(0)
StartDrawing(ImageOutput())
DrawingMode(0)
Circle(xm,ym,radius*0.85,backcol)
Circle(xm,ym,radius*0.09,tickcol)
If flags&16
FrontColor(Red(txtcol),Green(txtcol),Blue(txtcol))
BackColor(Red(backcol),Green(backcol),Blue(backcol))
DrawingFont(font)
l=TextLength(info$)
Locate(xm-l/2,ym+radius*0.40)
DrawText(info$)
EndIf
If flags&2 : d$=Str(Day(Date())) : EndIf
If flags&2 And flags&4 : d$=" "+d$ : EndIf
If flags&4 : d$=M$( Month(Date() ))+d$ : EndIf
If (flags&2 Or flags&4) And flags&8 : d$+", " : EndIf
If flags&8 : d$+Str(Year(Date())) : EndIf
If d$
DrawingFont(font)
dl=TextLength(d$)
dh=TextLength("Mx")
Box(xm-dl/2*1.5,ym-radius*0.62,dl*1.5,dh*1.5,jewcol)
DrawingMode(4)
Box(xm-dl/2*1.5,ym-radius*0.62,dl*1.5,dh*1.5,tickcol)
DrawingMode(0)
Locate(xm-dl/2,ym-radius*0.60)
FrontColor(Red(txtcol),Green(txtcol),Blue(txtcol))
BackColor(Red(jewcol),Green(jewcol),Blue(jewcol))
DrawText(d$)
EndIf
; ;- neue Zeiger malen
LineXY(mins(m)\xa,mins(m)\ya,mins(m)\xb,mins(m)\yb,mincol)
LineXY(mins(m)\xb,mins(m)\yb,mins(m)\xe,mins(m)\ye,mincol)
LineXY(mins(m)\xe,mins(m)\ye,mins(m)\xc,mins(m)\yc,mincol)
LineXY(mins(m)\xc,mins(m)\yc,mins(m)\xa,mins(m)\ya,mincol)
FillArea(mins(m)\xf,mins(m)\yf,mincol,mincol)
LineXY(hrs(h)\xa,hrs(h)\ya,hrs(h)\xb,hrs(h)\yb,hcol)
LineXY(hrs(h)\xb,hrs(h)\yb,hrs(h)\xe,hrs(h)\ye,hcol)
LineXY(hrs(h)\xe,hrs(h)\ye,hrs(h)\xc,hrs(h)\yc,hcol)
LineXY(hrs(h)\xc,hrs(h)\yc,hrs(h)\xa,hrs(h)\ya,hcol)
FillArea(hrs(h)\xf,hrs(h)\yf,hcol,hcol)
LineXY(secs(s)\xa,secs(s)\ya,secs(s)\xe,secs(s)\ye,seccol)
Circle(secs(s)\xf,secs(s)\yf,radius*0.03,seccol)
StopDrawing()
SetGadgetState(0,box)
os=s
; Delay(800); ein bischen warten, damit repeat until nicht soviel loopt
EndIf
Delay(1)
ForEver
EndProcedure
Procedure ToggleOnTop()
If GetMenuItemState(#set,#OnTop)
SetWindowPos_(WindowID(),#HWND_TOPMOST,0,0,0,0,#SWP_SHOWWINDOW|#SWP_NOMOVE|#SWP_NOSIZE)
Else
SetWindowPos_(WindowID(),#HWND_NOTOPMOST,0,0,0,0,#SWP_SHOWWINDOW|#SWP_NOMOVE|#SWP_NOSIZE)
EndIf
EndProcedure
;-main
LoadPrefs(#ininame)
box = CreateImage(0, width,height)
;-create window
OpenWindow(#win,winx,winy,width,height,#PB_Window_MinimizeGadget | #PB_Window_MaximizeGadget|#PB_Window_SystemMenu | #PB_Window_SizeGadget | #PB_Window_TitleBar,#appname)
CreateGadgetList(WindowID(0))
ImageGadget(#clock,0,0,width,height,box)
CreatePopupMenu(#set)
MenuTitle(#appname+" settings")
MenuItem(#OnTop,"always on top")
SetMenuItemState(#set,#OnTop,flags&1)
ToggleOnTop()
MenuItem(#ShowDay,"show day")
SetMenuItemState(#set,#ShowDay,flags&2)
MenuItem(#ShowMonth,"show month")
SetMenuItemState(#set,#ShowMonth,flags&4)
MenuItem(#ShowYear,"show year")
SetMenuItemState(#set,#ShowYear,flags&8)
MenuItem(#ShowInfo,"show info")
SetMenuItemState(#set,#ShowInfo,flags&16)
OpenSubMenu("change colors")
MenuItem(#seccol,"seconds")
MenuItem(#mincol,"minutes")
MenuItem(#hrscol,"hours")
MenuItem(#jewcol,"jewels")
MenuItem(#txtcol,"text")
MenuItem(#tickcol,"border")
MenuItem(#backcol,"background")
MenuItem(#boxcol,"box")
CloseSubMenu()
MenuItem(#setInfo,"change info")
MenuBar()
MenuItem(#default,"set defaults")
MenuBar()
MenuItem(#quit, "close")
MenuItem(#ver,#version)
DisableMenuItem(#ver,1)
;-draw clock
DrawClock()
tid=CreateThread(@tick(),0)
;SetWindowCallback(@SizeCallback())
;event loop
Repeat
EventID = WaitWindowEvent()
Select EventID
Case #PB_Event_SizeWindow
PauseThread(tid)
winx=WindowX() : winy=WindowY()
height=WindowHeight() : width=WindowWidth()
If height<50 : winy-(50-height) : height=50 : EndIf
MoveWindow(winx,winy) : ResizeWindow(width,height)
os=s-1 : DrawClock()
ResumeThread(tid)
Case #WM_SIZE
; PauseThread(tid)
; winx=WindowX() : winy=WindowY()
; height=WindowHeight() : width=WindowWidth()
; If height<50 : winy-(50-height) : height=50 : EndIf
; MoveWindow(winx,winy) : ResizeWindow(width,height)
; os=s-1 : DrawClock()
; ResumeThread(tid)
Case #WM_RButtonDown
popx.l=WindowX()+WindowMouseX()
popy.l=WindowY()+WindowMouseY()
DisplayPopupMenu(0,WindowID(0),popx,popy)
; Case #PB_EventGadget
; GadgetID = EventGadgetID()
; Select GadgetID
;
; EndSelect
Case #PB_EventMenu
MenuID = EventMenuID()
Select MenuID
Case #quit
Case #OnTop
SetMenuItemState(#set,#OnTop,GetMenuItemState(#set,#OnTop)!1)
ToggleOnTop()
Flags!1
Case #ShowDay
SetMenuItemState(#set,#ShowDay,GetMenuItemState(#set,#ShowDay)!1)
Flags!2
Case #ShowMonth
SetMenuItemState(#set,#ShowMonth,GetMenuItemState(#set,#ShowMonth)!1)
Flags!4
Case #ShowYear
SetMenuItemState(#set,#ShowYear,GetMenuItemState(#set,#ShowYear)!1)
Flags!8
Case #ShowInfo
SetMenuItemState(#set,#ShowInfo,GetMenuItemState(#set,#ShowInfo)!1)
Flags!16
Case #setInfo
Repeat
info$=InputRequester(#appname+" info text edit","your text has: "+Str(Len(info$))+" chars, max. 30 chars are allowed",info$)
Until Len(info$)<30
Case #default
resetPrefs(#ininame)
; setwindowpos_(WindowID(),#HWND_TOP,winx,winy,width,height,#SWP_SHOWWINDOW)
PauseThread(tid)
MoveWindow(winx,winy) : ResizeWindow(width,height)
SetMenuItemState(#set,#OnTop,Flags&1)
SetMenuItemState(#set,#ShowDay,Flags&2)
SetMenuItemState(#set,#ShowMonth,Flags&4)
SetMenuItemState(#set,#ShowYear,Flags&8)
SetMenuItemState(#set,#ShowInfo,Flags&16)
os=s-1 : DrawClock()
ResumeThread(tid)
ToggleOnTop()
Case #seccol
seccol=ColorRequester()
Case #mincol
mincol=ColorRequester()
Case #hrscol
hcol=ColorRequester()
Case #jewcol
jewcol=ColorRequester()
PauseThread(tid) : os=s-1 : DrawClock() : ResumeThread(tid)
Case #txtcol
txtcol=ColorRequester()
Case #tickcol
tickcol=ColorRequester()
PauseThread(tid) : os=s-1 : DrawClock() : ResumeThread(tid)
Case #backcol
backcol=ColorRequester()
PauseThread(tid) : os=s-1 : DrawClock() : ResumeThread(tid)
Case #boxcol
boxcol=ColorRequester()
PauseThread(tid) : os=s-1 : DrawClock() : ResumeThread(tid)
EndSelect
EndSelect
Until EventID = #PB_EventCloseWindow
savePrefs(#ininame)
CloseWindow(0)
PB / jaPBe jeweils aktuellste Version, seit 3.62 dabei, XP sp3 de/en & W7 en
Dann braucht es aber ein 3D-Sprite welches nicht mehr auf Linux und Co. läuft. Und außerdem, Sinus und Cosinus sind Grundwissen wenn es um Programmierung geht. In vielen Dingen braucht man sowas. Schau mal hier, da kannst du es relativ schnell lernen:
http://robsite.de/php/pureboard/viewtop ... ight=sinus
http://robsite.de/php/pureboard/viewtop ... ight=sinus
-
Kaeru Gaman
- Beiträge: 17389
- Registriert: 10.11.2004 03:22
...der link von sunny ist echt gut...da bleiben eigentlich keine fragen offen...
...das beispiel von wichtel finde ich auch nett... muss man halt erstmal durchsteigen...
von mir noch ein tipp: ich erzeuge gern vorher ein array für die werte, das lässt sich in performance-kritischen situationen schneller abfragen, als die sin/cos-funktionen:
der kreis ist hier zweimal im array, damit man auch von startwerten >0 mittels einer schleife auslesen kann...
das array-feld Sinus(80) enthält hier eben den sinus von 80°
(ich weiss garnicht mehr, warum ich damals ein STEP 1 gesetzt hatte, kann man glaubich auch weglassen... gab da irgendeine ungenauigkeit vorher...
)
...das beispiel von wichtel finde ich auch nett... muss man halt erstmal durchsteigen...
von mir noch ein tipp: ich erzeuge gern vorher ein array für die werte, das lässt sich in performance-kritischen situationen schneller abfragen, als die sin/cos-funktionen:
Code: Alles auswählen
#pi.f = 3.14159265
; define Calculation Arrays
Dim Sinus.f(720)
Dim Cosin.f(720)
For r=0 To 319 Step 1
Sinus(r) = Sin(#pi*r/180)
Sinus(r+360) = Sin(#pi*r/180)
Cosin(r) = Cos(#pi*r/180)
Cosin(r+360) = Cos(#pi*r/180)
Next rdas array-feld Sinus(80) enthält hier eben den sinus von 80°
(ich weiss garnicht mehr, warum ich damals ein STEP 1 gesetzt hatte, kann man glaubich auch weglassen... gab da irgendeine ungenauigkeit vorher...
Der Narr denkt er sei ein weiser Mann.
Der Weise weiß, dass er ein Narr ist.
Der Weise weiß, dass er ein Narr ist.