Gravity Well Game (Source Included)

BlitzMax Forums/BlitzMax Programming/Gravity Well Game (Source Included)

dw817(Posted 2015) [#1]
While I think I'm fairly good at math, this is just one type of calculation I could not figure out.

I don't know if any of you remember the original Space Wars game from yesteryear. One of the most interesting features was the star in the middle if you configured the game so it had gravity.

Not only did it pull the ships in but you could circle around it and create a perfect orbit.

While I have the engine complete for moving the ship and gravity from the middle, it's not perfect. To move, use the LEFT and RIGHT arrow keys to rotate. Hold down the UP arrow key to thrust.

What do you think you could do to improve the gravity ?

' Gravity Well (based on Space Wars) by David W (dw817)
' 12/14/15
' Can you improve the gravity to create a sustained orbit ?

Strict
Graphics 1024,768
SetBlend alphablend
Global testplay=1

Global heldkey[256],rot,i,r,ang#,x1#,y1#,xa#,ya#,t#

DrawLine 0,20,10,0
DrawLine 10,0,20,20
DrawLine 20,20,10,12
DrawLine 10,12,0,20
Global play1:TImage=CreateImage(20,26)
GrabImage play1,0,0
MidHandleImage play1
SetLineWidth 2
DrawLine 6,14,10,26
DrawLine 10,26,14,14
SetLineWidth 1
Global play1z:TImage=CreateImage(20,26)
GrabImage play1z,0,0
MidHandleImage play1z

rot=0

Repeat
  Cls
  For i=0 To 359 Step 45
    r=Rand(128,255)
    SetColor r,r,r
    SetRotation i
    DrawLine 512,369,512,359
  Next
  SetColor 255,255,255
  SetRotation 0
  If key(37)
    rot:-5
  ElseIf key(39)
    rot:+5
  EndIf
  ang#=rot
  SetRotation ang#+90.0
  If key(38)
    DrawImage play1z,x1#,y1#
    xa#=xa#+Cos(ang#)*t#
    ya#=ya#+Sin(ang#)*t#
    t#=t#+.01
  Else
    DrawImage play1,x1#,y1#
    If t#>0
      t#=t#-.00001
    EndIf
    xa#=xa#/1.1
    ya#=ya#/1.1
  EndIf
  SetRotation 0
  ang#=ATan2(369.0-y1#,512.0-x1#)
  If Abs(512.0-x1#)<256.0 And Abs(369.0-y1#)<185.0
    xa#=xa#+Cos(ang#)*(512.0-Abs(512.0-x1#))/512.0
    ya#=ya#+Sin(ang#)*(369.0-Abs(369.0-y1#))/369.0
  EndIf
  If xa#<-10.0
    xa#=-10.0
  ElseIf xa#>10.0
    xa#=10.0
  EndIf
  If ya#<-10.0
    ya#=-10.0
  ElseIf ya#>10.0
    ya#=10.0
  EndIf
  x1#=x1#+xa#
  y1#=y1#+ya#
  If x1#<0
    x1#:+1024.0
  ElseIf x1#>=1024.0
    x1#:-1024.0
  EndIf
  If y1#<0
    y1#:+736.0
  ElseIf y1#>=736.0
    y1#:-736.0
  EndIf
  Flip
  Flip
Until KeyDown(27)
End

Function key(k)
Local r=0
  If k=107 Then Return
  If KeyDown(k)=1
    heldkey[k]=heldkey[k]+1
  Else
    heldkey[k]=0
  EndIf
  If heldkey[k]=1 Or heldkey[k]=10 Or heldkey[k]>30 Then r=1
  If heldkey[k]>0 And k>=33 And k<=40 And testplay=1 Then r=1
  Return r
EndFunction



Matty(Posted 2015) [#2]
Calculate the distance of your ship from each gravity well (planet etc). call this 'radius'.
Apply a force as an additive effect upon the acceleration of the ship(s) in the direction pointing at the gravity well/planet where the magnitude falls off inversely proportional to the radius squared. That will give you a more realistic effect. If a planet has larger mass then increase the effect of gravity in proportion to the mass of the planet.

Note - you can have multiple gravity wells, planets etc and see unusual effects.

Basically acceleration due to gravity = - constant / radius^2 with the effect in the direction towards the centre of the planet.


dw817(Posted 2015) [#3]
Hmm ... I think basically I tried this earlier, Matty. I had worse results than what I have now with the ship unable to escape the gravity effect even by coming slightly near.

What in the CODE would you TYPE to implement what you described ?


Casaber(Posted 2015) [#4]
Nice, and also I think Iīve seen something that uses that other way to do things, here;

' g = -GM/(r*r)
		
Strict
Const G# = 10.0			' Or whatever
Const dt# = 1.0/60.0	' Fixed 60Hz
Const MAX_PLANETS = 10
Graphics(640, 480, 0)

Type Body
	Field x#, y#, vx#, vy#, M#
	Field size#

 Method Draw()
	  DrawOval(x-size, y-size, size*2, size*2)
 EndMethod	
EndType

Local Sun:Body = New Body
Sun.x = GraphicsWidth()/2.0
Sun.y = GraphicsHeight()/2.0
Sun.vx = 0.0
Sun.vy = 0.0
Sun.M = 10000.0
Sun.size = 16.0

Local Planet:Body[MAX_PLANETS]
For Local i=0 Until MAX_PLANETS
	Planet[i] = New Body
	Planet[i].x = RndFloat()*GraphicsWidth()
	Planet[i].y = RndFloat()*GraphicsHeight()
	Planet[i].vx = (RndFloat()-0.5)*25.0
	Planet[i].vy = (RndFloat()-0.5)*25.0
	Planet[i].M = 1.0
	Planet[i].size = 4.0
Next

While Not KeyHit(KEY_ESCAPE)
 Cls()
 Sun.Draw()
	' Apply the sun's gravity to each of our planets
	' We ignore the effect the other planets have on the sun and on each other
	For Local p:Body = EachIn Planet
		' Euler physics
		p.x :+ p.vx*dt
		p.y :+ p.vy*dt
		' g = -GM/(r*r)		
		Local rx# = p.x-Sun.x
		Local ry# = p.y-Sun.y
		Local r# = Sqr(rx*rx + ry*ry)
		If r>Sun.size	' Don't do it if it's too close
			Local g# = -G*Sun.M/(rx*rx + ry*ry)
			Local gx# = rx/r * g
			Local gy# = ry/r * g
			p.vx :+ gx*dt
			p.vy :+ gy*dt
		EndIf
		p.Draw()
	Next
	Flip
Wend




dw817(Posted 2015) [#5]
Your code is pretty neat, Casabar. But how do you achieve orbit ? I know in Star Trek they always talk about orbiting a planet. An orbit if done correctly (I think ?) is where you get just at the right point of gravity and fall towards the planet while circling it.

By doing so, you never actually hit the planet and can keep a perfect loop around it (much like how we orbit the sun).

I know when I played Space Wars, one tactic I would use against my enemy is to find the perfect orbit around the sun and then I would shoot when he came close. By orbiting I made a difficult target for my opponent.

BTW, to have different random planets for your program, add this code at the top:
SeedRnd MilliSecs()



Casaber(Posted 2015) [#6]
Good call with the SeedRnd.

Iīm not that good with all this space gravity but Iīve thought about that aswell.
What about if you let each planetoid affect eachother exactly once?

like this?

Strict
SeedRnd MilliSecs()
Const G# = 10.0
Const dt# = 1.0 / 60.0
Const MAX_PLANETS = 100
Graphics 640, 480, 0

Type Body
	Field x#, y#, vx#, vy#, M#
	Field size#

 Method Draw()
	  DrawOval x-size, y-size, size*2, size*2
 EndMethod	
EndType

Local Planet:Body[MAX_PLANETS]
For Local i=0 Until MAX_PLANETS
	Planet[i] = New Body
	Planet[i].x = RndFloat()*GraphicsWidth()
	Planet[i].y = RndFloat()*GraphicsHeight()
	Planet[i].vx = (RndFloat()-0.5)*25.0
	Planet[i].vy = (RndFloat()-0.5)*25.0
	Planet[i].M = 1.0
	Planet[i].size = 4.0
Next

' Remake planet 0 to be the sun
	Planet[0].x = GraphicsWidth()/2.0
	Planet[0].y = GraphicsHeight()/2.0
	Planet[0].vx = 0
	Planet[0].vy = 0
	Planet[0].M = 10000.0
	Planet[0].size = 16.0
	
While Not KeyHit(KEY_ESCAPE)
Cls

' Affect each planetoid with each planetoid once (the sun being one of those bodies)
' Note This also does once with itself of course, Iīm not that clear about if this will mess things up, or doesnīt matter , or even sets things straight.
For Local p:Body = EachIn Planet
        For Local i=0 Until MAX_PLANETS
		p.x :+ p.vx * dt
		p.y :+ p.vy * dt
		Local rx# = p.x - Planet[i].x
		Local ry# = p.y - Planet[i].y
		Local r# = Sqr(rx * rx + ry * ry)
		If r > Planet[i].size
	 	        Local g# = -G * Planet[i].M / (rx * rx + ry * ry)
			Local gx# = rx / r * g
			Local gy# = ry / r * g
			p.vx :+ gx * dt
			p.vy :+ gy * dt
		EndIf
        Next
        p.Draw()
Next

Flip
Wend


Still there is no perfect orbit in this example but some planetoid always end up orbiting for awhile I guess it needs more than randomness.

It seem like orbiting is just a matter of precision. Iīm still wondering though if orbit is a thing that lasts forever or if itīs just a very slow death that needs constant stearing to avoid it.

http://www.qrg.northwestern.edu/projects/vss/docs/space-environment/1-what-causes-an-orbit.html

I hope someone that knows more than I about this can fill things in for you !


dw817(Posted 2015) [#7]
That was an excellent observation, Casaber ! And yes, you do have some planetary bodies that end up in a distant orbit in your next code. I need to see what math you are using here and see if it can be applied correctly to the game.

Interesting link and information on ORBITS too. Lots of factors make it possible (or impossible as the case might be).

I never have really understood pointers very well, but it seems to me you are creating a gravity based on this calculation:

r# = Sqr(rx * rx + ry * ry)

I need to sit down and play with a calculator of sorts to see what type of reaction and pattern is occurring here.

Thanks for posting your galaxy program ! It certainly does have quite a bit to offer involving the complexities of a star's gravity.


Casaber(Posted 2015) [#8]
Just wanted to say I got a seemingly perfect orbit that lasted after I posted, but after few minutes the
sun had moved along with it (still perfect orbit though).

So I guess small masses has too much control over big matter in this code somehow.
But the code has the essentials right I'm sure it just need a tweak somewhere by a space genius.


Casaber(Posted 2015) [#9]
Check this one out it seem to do it right out of the box, http://www.blitzbasic.com/codearcs/codearcs.php?code=2746

Blitzmax version

Import "bbtype.bmx"
Import "bbvkey.bmx"

' parameters
scrX	= 800		' screen width
scrY	= 600		' screen height
scrD	= 32		' color depth
scrT	= 2			' windows / fullscreen

pn		= 10		' number of planets
ps		= 3			' size of planets
zoom	= 200		' zoom factor (1=far, 250=near, 200=inner system, 5=complete)
tracers	= 1			' planet tracers on/off
sunmove = 1			' correct sun movement on/off
sunmass#= 1.0		' sun mass (1=standard)
TIM#	= 0			' reset time factor
TIMINT#	= 0.5		' increase x sun day per cycle, higher values means precision loss!
					' ex. >10 mercury gets lost

' gauss gravitional constant
K1# = .01720209895
K2# = K1# * K1#

' fields
Global X#[pn+1], Y#[pn+1], Z#[pn+1], VX#[pn+1], VY#[pn+1], VZ#[pn+1], MASS#[pn+1], ro[pn+1], gr[pn+1], bl[pn+1]
Global name$[pn+1], oldx#[pn+1], oldy#[pn+1], DEG#[pn+1], MU#[pn+1], SEMI#[pn+1], ECCEN#[pn+1]

' read planet data
Global pla$[pn+1,11+1]
RestoreData planetdata
For p=0 To pn-1
	For q=0 To 11
		ReadData pla$(p,q)
		name$(p)=pla$(p,0)							' Name
		X#(p)=Float(pla$(p,1))								' X-Position
		Y#(p)=Float(pla$(p,2))								' Y-Position
		Z#(p)=Float(pla$(p,3))								' Z-Position
		VX#(p)=Float(pla$(p,4))							' Speed X
		VY#(p)=Float(pla$(p,5))							' Speed Y
		VZ#(p)=Float(pla$(p,6))						' Speed Z
		MASS#(p)=Float(pla$(p,7))*10^Int(pla$(p,8))	' Mass
		ro(p)=Float(pla$(p,9))								' Red
		gr(p)=Float(pla$(p,10))							' Green
		bl(p)=Float(pla$(p,11))						' Blue
	Next
Next

' Object Data from 01/01/2000
#planetdata
'    Name              POS X         POS Y         POS Z             Vx             Vy             Vz   Mass*10^X      R     G     B
DefData "Sonne"   ,   0.0000000 ,   0.0000000 ,   0.0000000 ,  0.000000000 ,  0.000000000 ,  0.000000000 , 1.991 , 30 , 255 , 255 ,   0
DefData "Merkur"  ,  -0.1778023 ,  -0.3863251 ,  -0.1879025 ,  0.020335410 , -0.007559570 , -0.006147710 , 3.191 , 23 , 255 ,  64 ,   0
DefData "Venus"   ,   0.1787301 ,  -0.6390267 ,  -0.2987722 ,  0.019469170 ,  0.004915870 ,  0.000978980 , 4.886 , 24 , 255 , 192 , 128
DefData "Erde"    ,  -0.3305873 ,   0.8497269 ,   0.3684325 , -0.016483420 , -0.005365460 , -0.002326460 , 5.979 , 24 ,   0 ,   0 , 255
DefData "Mars"    ,  -1.5848092 ,  -0.3648638 ,  -0.1244522 ,  0.003821510 , -0.011241840 , -0.005259630 , 6.418 , 23 , 255 ,   0 ,   0
DefData "Jupiter" ,   4.1801700 ,  -2.5386080 ,  -1.1900210 ,  0.004106423 ,  0.006125327 ,  0.002525539 , 1.901 , 27 , 128 , 255 ,   0
DefData "Saturn"  ,  -4.6197080 ,  -8.2374610 ,  -3.2033610 ,  0.004647751 , -0.002328957 , -0.001161564 , 5.684 , 26 , 255 , 255 , 128
DefData "Uranus"  ,  -3.7245900 , -17.1975200 ,  -7.4791700 ,  0.003833665 , -0.000845721 , -0.000424809 , 8.682 , 25 ,   0 , 255 , 255
DefData "Neptun"  ,   1.9138100 , -27.9215500 , -11.4762000 ,  0.003118271 ,  0.000233303 ,  0.000017967 , 1.027 , 26 ,   0 , 128 , 255
DefData "Pluto"   , -23.2285900 , -18.5272000 ,   1.2167500 ,  0.002066577 , -0.002488884 , -0.001397200 , 1.080 , 24 , 128 , 128 , 128

' Normalize Mass To sun
For I = 1 To pn-1
	MASS#(I) = MASS#(I) / MASS(0)
Next
MASS#(0) = sunmass#

' Create reduced mass in gauss units
For I = 1 To pn-1
	MU#(I) = K2# * (1 + MASS#(I))
Next

' init screen
Graphics scrX,scrY

' Main loop
While Not VKeyHit(1)
	
	' increase time by factor
	TIM# = TIM# + TIMINT#
	
	' draw tracers
	For i=0 To pn-1
		If tracers Then SetColor 32,32,32 Else SetColor 0,0,0
		DrawOval(scrX/2+oldx#(i),scrY/2+oldy#(i),ps,ps)
	Next
	
	' calculations And output
	
' calc New speed

' NewV
For I = 0 To pn-1
	
	AX# = 0
	AY# = 0
	AZ# = 0
	For J = 0 To pn-1
		If (J = I) Then Goto skip
		XJI# = X#(J) - X#(I)
		YJI# = Y#(J) - Y#(I)
		ZJI# = Z#(J) - Z#(I)
		R# = Sqr(ZJI# * ZJI# + YJI# * YJI# + XJI# * XJI#)
		R3# = R# * R# * R#
		COEFF# = K2# * MASS#(J) / R3#
		AX# = COEFF# * XJI# + AX#
		AY# = COEFF# * YJI# + AY#
		AZ# = COEFF# * ZJI# + AZ#
#skip
	Next	
	VX#(I) = VX#(I) + AX# * TIMINT#
	VY#(I) = VY#(I) + AY# * TIMINT#
	VZ#(I) = VZ#(I) + AZ# * TIMINT#
Next

' calc New positions And draw planets
'NewP
For i=0 To pn-1
	
	' calc New position
	X#(i) = X(i) + VX#(i) * TIMINT#
	Y#(i) = Y(i) + VY#(i) * TIMINT#
	Z#(i) = Z(i) + VZ#(i) * TIMINT#
	
	' Include zoom factor
	sx#=X#(i)*zoom
	sy#=Y#(i)*zoom
	
	' correct sun movement
	If i=0 And sunmove=1 Then
		sunx#=sx#
		suny#=sy#
	EndIf
	
	' New position with zoom And sun movement
	sx#=sx#-sunx#
	sy#=sy#-suny#
	
	' save old position For tracers
	oldx#(i)=sx#
	oldy#(i)=sy#
	
	' draw planets
	SetColor ro(i),gr(i),bl(i)
	DrawOval(scrX/2+sx#,scrY/2+sy#,ps,ps)
Next

	DrawRect 0,0,150,42
	SetColor 255,255,255	
	DrawText "Days:  "+Int(TIM#),0,0
	DrawText "Years: "+TIM#/365.25,0,10
	DrawText "Time:  "+TIMINT#,0,20
	DrawText "Zoom:  "+zoom,0,30
	' Keyboard shortcuts
	' ------------------
	' Arrows up/down		Zoom in/out
	' Arrows Left/Right		speed increase/decrease
	' Space					Tracers
	' F1					inner system
	' F2					complete system
	' F3					Double sun mass
	' F4					half sun mass
	' F5					earth = 0.2 sun masses :-)
	kp=0
	If VKeyDown(200) Then zoom=zoom+1;If zoom>250 Then zoom=250
	If VKeyDown(208) Then zoom=zoom-1;If zoom<1 Then zoom=1
	If VKeyDown(203) Then TIMINT#=TIMINT#-.5;If TIMINT#<.5 Then TIMINT#=.5
	If VKeyDown(205) Then TIMINT#=TIMINT#+.5;If TIMINT#>25 Then TIMINT#=25
	If VKeyHit(57) Then tracers=1-tracers;Cls
	If VKeyDown(59) Then zoom=200;Cls
	If VKeyDown(60) Then zoom=5;Cls
	If VKeyDown(61) Then MASS#(0)=2
	If VKeyDown(62) Then MASS#(0)=0.5
	If VKeyDown(63) Then MASS#(3)=.2
	Flip 1
Wend
End



dw817(Posted 2015) [#10]
I am getting a "FILE NOT FOUND" for the first 2-lines, Casaber. It's not your fault, but I wish people who post source that requires external libraries would always include a URL link in their above comments.

Like the frame routine I posted recently, I will always have a link to the data or images needed to run my programs.


Casaber(Posted 2015) [#11]
I did the conversion on the spot from BB to Blitzmax.
Blitmax creates 2 files at that point.

Iīve trashed all the files now
Just forget the above post I guess itīs not very compact or concise code to use.


if you want those includes you can just try to importart anything from bb into bmax and there will be created two files


Casaber(Posted 2015) [#12]
These are the two Standard BMAX includes for the above and also anything else imported from bb.

bbvkey.bmx

' virtual key support for legacy Blitz apps

Global VKEY[]=[..
0,KEY_ESCAPE,KEY_1,KEY_2,KEY_3,KEY_4,KEY_5,KEY_6,KEY_7,KEY_8,KEY_9,KEY_0,..
KEY_MINUS,KEY_EQUALS,KEY_BACKSPACE,KEY_TAB,KEY_Q,KEY_W,KEY_E,KEY_R,KEY_T,..
KEY_Y,KEY_U,KEY_I,KEY_O,KEY_P,KEY_OPENBRACKET,KEY_CLOSEBRACKET,KEY_RETURN,..
KEY_LCONTROL,KEY_A,KEY_S,KEY_D,KEY_F,KEY_G,KEY_H,KEY_J,KEY_K,KEY_L,..
KEY_SEMICOLON,KEY_QUOTES,KEY_TILDE,KEY_LSHIFT,KEY_BACKSLASH,..
KEY_Z,KEY_X,KEY_C,KEY_V,KEY_B,KEY_N,KEY_M,KEY_COMMA,KEY_PERIOD,KEY_SLASH,..
KEY_RSHIFT,KEY_NUMMULTIPLY,KEY_ALT,KEY_SPACE,KEY_CAPSLOCK,..
KEY_F1,KEY_F2,KEY_F3,KEY_F4,KEY_F5,KEY_F6,KEY_F7,KEY_F8,KEY_F9,KEY_F10,..
KEY_NUMLOCK,KEY_SCROLL,KEY_NUM7,KEY_NUM8,KEY_NUM9,KEY_NUMSUBTRACT,KEY_NUM4,..
KEY_NUM5,KEY_NUM6,KEY_NUMADD,KEY_NUM1,KEY_NUM2,KEY_NUM3,KEY_NUM0,..
KEY_NUMDECIMAL,KEY_NUMSLASH,KEY_F11,KEY_F12,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,..
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,..
KEY_EQUALS,0,0,KEY_MEDIA_PREV_TRACK,0,0,0,0,0,0,0,0,KEY_MEDIA_NEXT_TRACK,0,0,..
KEY_ENTER,KEY_RCONTROL,0,0,KEY_VOLUME_MUTE,0,KEY_MEDIA_PLAY_PAUSE,0,..
KEY_MEDIA_STOP,0,0,0,0,0,0,0,0,0,KEY_VOLUME_DOWN,0,KEY_VOLUME_UP,0,..
KEY_BROWSER_HOME,KEY_DECIMAL,0,KEY_NUMDIVIDE,0,KEY_SCREEN,..
0,0,0,0,0,0,0,0,0,0,0,0,0,KEY_PAUSE,0,KEY_HOME,KEY_UP,KEY_PAGEUP,0,..
KEY_LEFT,0,KEY_RIGHT,0,KEY_END,KEY_DOWN,KEY_PAGEDOWN,KEY_INSERT,KEY_DELETE,..
0,0,0,0,0,0,0,KEY_LWIN,KEY_RWIN,0,0,0,0,0,0,0,0,KEY_BROWSER_SEARCH,..
KEY_BROWSER_FAVORITES,KEY_BROWSER_REFRESH,KEY_BROWSER_STOP,KEY_BROWSER_FORWARD,..
KEY_BROWSER_BACK,0,KEY_LAUNCH_MAIL,KEY_LAUNCH_MEDIA_SELECT]

Function VKeyDown(key);Return KeyDown(VKEY[key]);End Function
Function VKeyHit(key);Return KeyHit(VKEY[key]);End Function

'currently unsupported in BlitzMax

Function Locate( x,y );Return 0;End Function
Function MouseZSpeed();Return 0;End Function
Function FreeBank(bank);Return 0;End Function
Function LoopSound(sound);Return 0;End Function
Function ChannelPitch(channel,hz);Return 0;End Function
Function PlayCDTrack( track,mode=0 );Return 0;End Function
Function SoundVolume( sound,volume# );Return 0;End Function


bbtype.bmx
' BBType adds legacy Type functionality to BlitzMax Type

Type TBBType

	Field _list:TList
	Field _link:TLink

	Method Add(t:TList)
		_list=t
		_link=_list.AddLast(Self)
	End Method

	Method InsertBefore(t:TBBType)
		_link.Remove
		_link=_list.InsertBeforeLink(Self,t._link)
	End Method

	Method InsertAfter(t:TBBType)
		_link.Remove
		_link=_list.InsertAfterLink(Self,t._link)
	End Method

	Method Remove()
		_list.remove Self
	End Method

End Type

Function DeleteLast(t:TBBType)
	If t TBBType(t._list.Last()).Remove()
End Function

Function DeleteFirst(t:TBBType)
	If t TBBType(t._list.First()).Remove()
End Function

Function DeleteEach(t:TBBType)
	If t t._list.Clear()
End Function

Function ReadString$(in:TStream)
	Local	length
	length=ReadInt(in)
	If length>0 And length<1024*1024 Return brl.stream.ReadString(in,length)
End Function

Function HandleToObject:Object(obj:Object)
	Return obj
End Function

Function HandleFromObject(obj:Object)
	Local h=HandleToObject(obj)
	Return h
End Function



Casaber(Posted 2015) [#13]
I agreee about including libraries frameworks images sounds and datafiles, often those are missing. Itīs a living hell when youīre learning.


dw817(Posted 2015) [#14]
Got it running now, Casaber. What what an amazing little program ! You can definitely see perfect planetary orbits in this one.

Truly this is something I'll have to experiment with. Thanks for sharing !

Now ... does this mean I can take any BlitzBasic program and it'll run in BlitzMAX once selecting "Import BB Project" ?


Casaber(Posted 2015) [#15]
Sortof, take this one for instance, Import the .bb in the original link and youīll notice it does most but not everything for you.
I would say it does 90-100 % of the job, it's kind of sucks in amazingly simple commands sometimes such as oval, text etc.

So you have to make them into drawoval, drawtext etc, but ya. As long as the original donīt use setbuffer or something
extremly messy then itīs a breeze to convert most things I would say. This one was a 2 minute affair to convert for me.


dw817(Posted 2015) [#16]
Phew ! Which ... brings up the age old argument, which is better, BlitzBASIC or BlitzMAX.

I chose BlitzMAX because it is very smooth in graphics when you use FLIP() and the fact you can embed binary files directly into the .EXE.

I don't know if BlitzBASIC can do any of this.


Casaber(Posted 2015) [#17]
With Win10 I find that both has reached the same in smoothness when you use FLIP (this is true with Microsoft's own devices , I guess MS go for what Apple does and match hardware with software very well, and they do it even better than Apple.

Apple has always been extremely nice, but not perfectly smooth, 99% for sure, but not as iOS. Now Win10 has reached the "iOS level". Both with DX7 and openGL. This is what I like.

I guess each flavor of API has their own effectiveness in implementation in Blitz products (overhead calls etc). And could be better implemented in each Blitz Research product,
but both are SO GOOD now. There's certainly more power underneath that you could unlock, for sure. (Things like less BEGIN END in OpenGL, and probably similiar things with DX7 aswell).

Personally I find Blitzmax with Opengl to be most effective if you need extreme things, so I think Microsoft is not that biased towards DX12 anymore. Which I much approve on.

About embeddeding I'm not sure if you could manipulate the inner workings easly of Blitz3D I've not gone that far to try that.
But you could at least easly stick binarys inside the exe at distribution as DATA statements,
and create needed fiies at runtime. But ya security and customisibility that those external temporary files exposeis a doubleedged sword,
you might not want curious users to dig and be able to affect those files.


dw817(Posted 2015) [#18]
I am using a program called ASPACK to compress my final runtimes, Casaber.

It's really quite thorough and even adds the benefit of encryption. Well worth the cost. (looking at site), well it USED to be worth the cost. Wow, talk about buttering their bread. :(

Anyways, I like the fact that BlitzMAX embeds the files and ASPACK can compress and encrypt the lot of it. My version is very OLD compared to what's out there now, but I'm content with it.

I was actually working towards making a program that after compilation let you attach and remove binary encrypted files from an EXE of your choice. Today - I don't know if there is such an interest for it.

Chris told me I should just keep my external files encrypted and not worry about trying to shove every piece of data into the single main runtime EXE.

... back to BlitzBASIC. It does seem like there is quite a bit more support for it than BlitzMAX. The last time I tried the Blitzmax demo though, I found it lacking the nice IDE of BlitzMAX and it staggered when it ran programs.

I have a new computer and OS - perhaps today it will run better. I can always check and see - and if so, purchase and switch over to it and the larger community.


Casaber(Posted 2015) [#19]
BlitzMAX did the same for me back then, it was HORRIBLE, opengl have been HELL 2005-2014 for me. I would never touch it back then, not a chance.
It was a snail, at best it had tearing and god knows what.

I donīt know all those ppl who used opengl and thought it was a good idea, windows have never embraced opengl very well in my opinion till this very moment.
I guess they used extreme graphic cards and those manufacturers had opengl and it was a nicesche in this time, good cards = opengl, shitty cards = dx, i donīt know...

So under this time, you always had power but you never got to see it, ("shitty" cards did have alot of power trust me). It was just out of reach, no API talked properly.
With Opengl I guess you had alot of good things going on but the OS didnīt handle it as it should all the way, so either way you didnīt get what you wanted.
The best you could do was to overpower things and hope for the best.

Now things changed the other way around. OS actually make good use of opengl (this is deeper than drivers in my opionion)
and now Blitzmax can ride this wave, it works like a charm suddenly.


dw817(Posted 2015) [#20]
Well now, this brings some concern, Casaber. Are you saying then that not everyone has OpenGL but they DO have DirectX ? And that BlitzMAX only and exclusively uses OpenGL ?

Or ... is it better than that now and OpenGL is a finer system than DirectX ?


Brucey(Posted 2015) [#21]
On Windows you can choose to use DX or OpenGL.


LT(Posted 2015) [#22]
Uh, been using OpenGL for years with no problems. Always found it MUCH easier than DX. And if you want to run on anything other than Windows, you have no choice.


dw817(Posted 2015) [#23]
Hi Brucey, LT.

I know I've been selecting OpenGL for my game emulators and seem to have less problems than DirectX. DirectX can and will and has crashed in the past.

No problems with OpenGL. Does BlitzBasic/Blitz3D not use OpenGL then ?


Casaber(Posted 2015) [#24]
I could make it clearer about my experience

2001-2005 DX7 worked 99% smooth, opengl did perform awful
2005-2014 everything performed awful, (I think opengl got abit better, but as I did not ever got the strength to go on with DX9 and 11 during this time, I never felt ANYTHING worked)

2015 Now, DX7, opegngl and of course DX9/11 works better ever before in Win10. This is whatIīve been waiting for. Coding to be fun and ya, you know, good experience.


Casaber(Posted 2015) [#25]
And if you use only things that all those API offers, Drawing images and simpler things, then it doesnīt matter now, which one you pick.
Features is everything now, Itīs not about "which ones are the better drivers, matching drivers, which-api-is-smoother-on-which-machine?"

Everything works fine. OpengGL is of course nice in that the whole world uses it, Windows and XBOXone being the only exceptions that uses both Opengl AND something else,
and they too use opengl exetremly fine now from what I gather. So my pick is Opengl bc you reach everywhere.
I could use Blitz3d as my prototyping tool and release things with it and get perfect finish on the final results (on Win10 that is, not 8.x and not 7).

And that's great. You can pick.


Casaber(Posted 2015) [#26]
With fine i mean 60fps perfect an no micro stuttering or hickups every 5 minutes.


Casaber(Posted 2015) [#27]
I can even transfer large and extreme amounts of files to/from USB now while getting perfect smooth graphics, and NOT get stuttering graphics, I find that amazing.

Before that was a NONO.
Playing video at the same time MAY induce some micro stuttering but extremely low I have had a hard time to even notice it I had to go to great length to be sure.

Thatīs about where Win10 have gone now. Ya? Itīs great. Happy as can be.


dw817(Posted 2015) [#28]
Can you read and write individual pixels in BlitzBASIC and/or Blitz3D ?
Also have the ability of loading or saving PNGs easily ?

Remember in BlitzMAX they have, "SavePixmapPNG()"

I am understanding BlitzBASIC does allow for MCI media access, yet I haven't seen any especially easy code for it yet.

In GFA, it's

A$=MCI$("open song.mid alias mid")
A$=MCI$("play mid")
input A$
A$=MCI$("stop mid")
A$=MCI$("close mid")
P=Val(MCI$("status mid position"))
L=Val(MCI$("status mid length"))

These are just a few elements critical and essentially useful for the types of code I write in accessing images and audio.


Casaber(Posted 2015) [#29]
Use arrays of integers in B3D as your main buffer. Thatīs the way to do it, and keep serious track of RGBA in that array.
Use writepixelfast to write those, never ever ever read pixels. Itīs deadslow and it have always been, and itīs not needed,
It's the Akilles heal of modern computers, nothing kills performance more.

If you do it like this you can write about half a million or actually 50.000 - 500.000 pixels each 60 fps frame(each 12 microseconds) depending on what memeoryspeed youe'v got.

I think it's okay and safe to assume 1Ghz+ today, and buses are 1Ghz+ aswell so the only thing is memory speed DDR2 (still lives in some cheap things)
versus DDR3 makes a difference how many pixels you can write. DDR3 I know gives half a million per 12 micrseconds. Itīs okay, itīs useful.


Casaber(Posted 2015) [#30]
PNG is the only format I've ever used together with Blitz3D or anything, so yup.
You can load and save and you can easly read pixel values. Itīs just not good for realtime use.

About MCI Iīm not sure. Iīve succesfully used it sometime to play MIDI files, I know that. But I donī+t remember how exactly. I think it was something like mciSendString?


Casaber(Posted 2015) [#31]
I see your main problem you need details how to get BACK the result of something you asked the MCI for. Hmm Iīm not that good with MCI, I shall try in my Win7 emu to do some B3D tinkering.


Casaber(Posted 2015) [#32]
Itīs tough to grasp MCI, it seem so unstabled and dated in their pages, but if
GFA can handle it should be perfectly possible.

I tried without declaratives to reach far and wide into the OS of hell.
To ask for e.g. MIDI tempo or position should be possible aswell, but i ned some sleep now. For a couple of hundred years.


sound$ = "song.mid"
writeMCIstring("open " +sound$ + " type sequencer alias mid")
writeMCIstring("play mid")
WaitKey
writeMCIstring("stop mid")
writeMCIstring("close mid")

Function writeMCIstring(command$)
	command$ = command$ + Chr$(0)
	bank = CreateBank(Len(command$))
	For i = 1 To Len(command$)
		PokeByte bank, i - 1, Asc(Mid$(command$, i, 1))
	Next
	CallDLL "winMM.DLL", "mciExecute", bank
	FreeBank bank
End Function




Casaber(Posted 2015) [#33]
You do need a midi file for this code to actually work.

So I provide - a midi

http://s000.tinyupload.com/index.php?file_id=04958622303685137609

You also need ears.

I cannot provide those.

PS
I matched the source with yours, so you feel more like home with exprimentation, yourself.

CallDLL some might consider bad vs e.g. declarations, but it does work well it seem to me. Of course declarations is nice. I just did it this way bc it was so clean and neat.

As CallDLL takes a secondary bank as a parameter for answers the next step would be
trying to find the banksize that MCI would like to put its answers back in and read
them as a simple string.


Casaber(Posted 2015) [#34]
You know... I wanted to help ya? I had a hard time to grasp though how to tell the bastard API to give something back. A REALLY HARD TIME. So I thought - okay decalaration time? IF it is simple, and it was.

create a winmm.decls
; this IS a declaration, so sorry for that, it needs 2 line of text though so it is not too clumpsy

; winmm.decls
; .lib "winmm.dll" ; this is a standard windows file
; mciExecute%(Text$)
; mciSendString%(Command$,ReturnString*,ReturnLength%,Callback):"mciSendStringA"


This is code, it plays midi, it finds its length etc, ya, its good.
It IS a mess, because I should be in bed, but I know this is what you want and you understand how to make this into a beutiful castle.
And that is what counts.

sound$ = "song.mid"
Retbank = CreateBank(12) ; Retbank,12,0 each call is not needed, it's just needed when you need answers back, 12 means 12 bytes, no bank is needed otherwise

; playing
mciSendString("open " +sound$ + " type sequencer alias mid",Retbank,12,0)
mciSendString("play mid",Retbank,12,0) ; or you could do this mciSendString("play mid from 240 to 290",Retbank,12,0)

; Uncomment this to change the time format
; mciSendString("set mid time format milliseconds",Retbank,12,0) ; When we want everything to be about milliseconds instead of PPQN



; THIS SECTION I DEDICATE TO MUMBO JUMBO WHICH HAS NO VALUE AND NOT NEEDED TO READ TO USE THIS CODE
;
; This is about seeking and play commands
; note that multiple PLAY commands does not affect playback, but they do work as a needed resume after a SEEK command.
; mciSendString("seek mid to 240",Retbank,12,0)
; mciSendString("play mid",Retbank,12,0)

; This is about advanced play commands (you could just STOP and PLAY to resume though so you donīt need to dive into these to have resume working) but they do exist for some reason.
; So ya, there are two more advanced PLAY commands
; mciSendString("play mid wait",Retbank,12,0) ; synchronous playback
; mciSendString("play mid notify",Retbank,12,0) ; asyncronous playback
; And they give you additional commands:
; mciSendString("pause mid",Retbank,12,0)
; mciSendString("resume Mid",Retbank,12,0) 
;
; You could just use PLAY and STOP
;
; MUMBO JUMO IS OVER, SO VERY SORRY THAT THE WORLD IS AN COMPLEX AND UNPERFECT PLACE



; get length
mciSendString("status mid length",Retbank,12,0)
Print PeekStr(retbank,11,0)
WaitKey

; get where we are in the song
mciSendString("status mid position",Retbank,12,0)
Print PeekStr(retbank,11,0)
WaitKey

; how get tempo
mciSendString("status mid tempo",Retbank,12,0)
Print PeekStr(retbank,11,0)
waitkey

; And important is to be able to set things aswell

; how set tempo
mciSendString("set mid tempo 10",Retbank,12,0)
waitkey

; stopping
mciSendString("stop mid",Retbank,12,0)
mciSendString("close mid",Retbank,12,0)
End

Function PeekStr$(Tbank,Size=64,Offset=0)
  Local NewStr$ = ""
  For count = offset To (offset+size-1)
    newchr = PeekByte(Tbank,count)
    If newchr = 0 Then Exit
    newstr$ = newstr$ + Chr$(newchr)
  Next
  Return Newstr$
End Function



Casaber(Posted 2015) [#35]
Play MIDI example to show how to set/get tempo and set/get position

winmm.decls
; .lib "winmm.dll"
; mciExecute%(Text$)
; mciSendString%(Command$,ReturnString*,ReturnLength%,Callback):"mciSendStringA"


sound$ = "song.mid"
Retbank = CreateBank(12)

; play
mciSendString("open " +sound$ + " type sequencer alias mid",Retbank,12,0)
mciSendString("play mid",Retbank,12,0) ; or you could do this mciSendString("play mid from 240 to 290",Retbank,12,0)

; Lets use milliseconds instead of PPQN when we talk about time
; mciSendString("set mid time format milliseconds",Retbank,12,0) 

; get length
mciSendString("status mid length",Retbank,12,0)
length = PeekStr(retbank,11,0)

; get tempo
mciSendString("status mid tempo",Retbank,12,0)
tempo = PeekStr(retbank,11,0)

Repeat
Cls
; get position in song
mciSendString("status mid position",Retbank,12,0)  ;  I ask the position alot, more than I should, I am an evil herbivore. 
position = PeekStr(retbank,11,0)

Text 10,10,"Length : "+ Str$(length)
Text 10,30, "Tempo : " + Str$(tempo)
Text 10,50,"Position : " + Str$(position)
Text 10,100," Press left mb to change tempo and skip"

If MouseDown(1) And nomore = False
tempo = 120 : mciSendString("set mid tempo "+Str$(tempo),Retbank,12,0)
mciSendString("set mid tempo 240",Retbank,12,0) : mciSendString("seek mid to 240",Retbank,12,0)
mciSendString("play mid",Retbank,12,0) : nomore = True
endif

Delay 1
VWait
Until MouseDown(2)

; stop
mciSendString("stop mid",Retbank,12,0)
mciSendString("close mid",Retbank,12,0)
End

Function PeekStr$(Tbank,Size=64,Offset=0)
  Local NewStr$ = ""
  For count = offset To (offset+size-1)
    newchr = PeekByte(Tbank,count)
    If newchr = 0 Then Exit
    newstr$ = newstr$ + Chr$(newchr)
  Next
  Return Newstr$
End Function



dw817(Posted 2015) [#36]
Hmm ... Casaber, all of this code is just for BlitzBASIC, right ? Is there no way to play a MIDI and retrieve the position of an already playing MIDI so both POSITION and LENGTH can all be read in BlitzMAX ?

That would really be a gem if it could be done, and to my knowledge NO-ONE has written an example code for this yet so you would be the first.

And MIDI could be substituted for a Windows Audio (WMA) additionally. You get great quality and great compression, about 3x better than OGG when you save at a variable BITRATE, Quality 10.

Also, where can I download COMPILED versions (not source) of Blitz3D, BlitzPlus, and BlitzBasic ?


Casaber(Posted 2015) [#37]
Download them here? Just register yourself and download all for free, the codes for all products is on the SHOP link above.

Yes it is Blitz3D.

For BLITZMAX version, I could pave the road until pointers are needed for input, is that okay?
CALLING AN BLITZMAX EXPERT, ANYONE? :)

Are BlitzMAX lacking string pointers?! This was not an easy task if you donīt know every little dark corner Windows API, pointers, and BMAX.

Extern "win32"
Function mciSendString(pstrCommand$z,lpstrReturnStr:Byte Ptr,wReturnLen:Int,CallBack:Int)="mciSendStringA@16"
End Extern

Graphics 640,480
sound$ = "song.mid"

' play
mciSendString "open " +sound$ + " type sequencer alias mid",Ret$,12,0 ' or 'mciSendString "open "+sound$+" alias Mid",ret$,12,0
mciSendString "play mid",Ret$,0,0' or mciSendString "play mid from 240 to 290",Ret$,0,0

' change timeformat into milliseconds instead of PPQN
'mciSendString "set mid time format milliseconds",Ret$,12,0

' set tempo
mciSendString "set mid tempo 120",Ret$,0,0

' set position
mciSendString "seek mid to 240",Ret$,0,0
mciSendString "play mid",Ret$,0,0

WaitKey

' THESE ARE PROBLEMATIC AS I HAVE NOT YET FOUND THE HOW TO GET THE POINTERS BACK WITH DATA, ITS SO CLOSE TO A SOLUTION ITS JUST SILLY
' probably something with varptr

' get length
' mciSendString("status mid length",Ret$,12,0)

' get tempo
' mciSendString("status mid tempo",Ret$,12,0)

' get position in song
' mciSendString("status mid position",Ret$,12,0)



' stop
mciSendString "stop mid",Ret$,0,0
mciSendString "close mid",Ret$,0,0
End



dw817(Posted 2015) [#38]
Very sweet code, Casaber ! :)

It plays MIDI now, but yes, with no way to return position.

Ultimately I need POSITION and LENGTH so I can determine when to LOOP playing the music.

BTW, I did what you said and registered (registration does not appear in Firefox), so I used Google Chrome.

Tried out BlitzPlus first, and yes, it has the same problem.

Can't change IDE colors.

It appears as if it does not task the CPU too much. Was trying Birdie's demo, "3dfingy.bb"

Am going to investigate the other languages now that I can download them (maybe).

Couldn't find the free registration code for Blitz3D.
Blitz Basic for download or description is not even listed on the main page ?


Casaber(Posted 2015) [#39]
all codes are the same all caps and FREE and their name

The code for BlitzBASIC is FREEBLITZ3D (BlitzBASIC is 100% the same as BLITZ3D thatīs why it is not there anymore, the 3D commands are just thrown ontop and you just ignore that bonus set of instructions)


Casaber(Posted 2015) [#40]
If you need MIDI, I'll say, use Blitz3D or BlitzPlus and be happy. It works a treat.
Blitzplus should also work with the above code??

You could equally well use BlitzMAX but, ya, it needs tinkering. Probably not much but itīs not a well documented area so you need luck with help with WIN API and BlitzMAX specifics.


Casaber(Posted 2015) [#41]
Itīs certainly not impossible, itīs just not been done, this is really close I can assure you. But... isnīt this a drag to try find things just to get midi music? I took me a whole night to just manage come this far haha.

mp3 and ogg are amazing for music, maybe you can do a online library and download the one you need if you need so much music that you find midi makes a difference?

Than youīre supporting Apple too ;) hint hint (to hell with WIN32 specficis and .NET)


Casaber(Posted 2015) [#42]
hmmm now i remember why plus does not work with the code, B2D and and Plus has no declaration. B3D added 3D AND declaration. ya. bummer.


Casaber(Posted 2015) [#43]
You COULD try this if you love BlitzPlus very much
But I canīt help you much with Plus more than this.

sound$ = "song.mid"
writeMCIstring("open " +sound$ + " type sequencer alias mid")
writeMCIstring("play mid") ; etc exact same strings as in every example works here

Function writeMCIstring(command$)
	command$ = command$ + Chr$(0)
	bank = CreateBank(Len(command$))
     bank2 = CreateBank(12)
	For i = 1 To Len(command$)
		PokeByte bank, i - 1, Asc(Mid$(command$, i, 1))
	Next
	CallDLL "winMM.DLL", "mciExecute", bank, bank2
	; FreeBank bank : FreeBank bank2

        ; read results in bank2 here !!!!!!!!! it should leave something there to be read

End Function




dw817(Posted 2015) [#44]
Actually I'm interested in playing this 4-hour .OGG I prepared, Casaber.

Current BlitzMAX does not do it, it says it runs out of memory. But using the MCI code you wrote above (for playing if not reading the position of the media), it does work ! Provided that the audio is MID or WMA.

Because MCI does not read or play OGGs apparently, I tried.

The code you wrote will not play from a path either, I tried:
"c:\david\music\n2o soundtrack\n2o01.wma"

But if the song is in the same directory as the program, it works and plays fine.

And no, I'm not liking BlitzPLUS, I can't change the IDE colors.
Normally I use WHITE background, black text (well really dark purple $200020).
and font COURIER NEW at 15 (yes, I like to see what I'm typing) :)

And I can't use CTRL ARROW KEYS to navigate to and from each project. Looks like BlitzMAX is here to stay. If the LENGTH and POSITION can be read, that will make it a cinch to start importing WMA audio.


Casaber(Posted 2015) [#45]
On 2nd thought I think callDLL is broken. I think my ideas was great in theory though (if the command would work as they should).


Casaber(Posted 2015) [#46]
Iīm surprised that BlitzMAX cannot stream long oggs? i need to check that later on.

There's no other ways than MCI? Me thinks MCI is a convoluted way to make music happen and
If you need perfect sync in your loop later on you might get very dissapointed what MCI has to offer.
You will probably hear clicks when it loops around.


dw817(Posted 2015) [#47]
Well, if there's a way to do it. I had just finished converting over epic.ogg from it's WAV to a .WMA, and sure enough, your good MCI program plays the .WMA just fine, in high quality, and despite being over =4= hours long !

BlitzMAX crashes with a nasty message.

Casaber, that's too good to pass up that your program plays a 4-hour music file. Got to figure out a way of reading the LENGTH and POSITION from an MCI$ - or, as you mentioned, maybe there is some other way of loading, playing, and figuring the length and position of a media a different way rather than MCI ?


Casaber(Posted 2015) [#48]
remember that mid in all code above is just an identifier of an object nothing to do with mid

and that *sequencer* is the type assigned to that object.

Sequencer is the type used for midis, and for audio the type should just be changed into

WaveAudio instead of Sequencer, try change that and see, it might work right out of the box for audio aswell, I guess tempo does NOT belong to anything related to pure audio though, But length and position might work asis.

Some other ideas other than MCI, could be um maybe go external using VLC ? But i know nothing about that and personally I would not like that solution, itīs too external. But VLC is common so maybe it should be left as an idea.

Or you could split up those 4 hours into say 16 15min parts I guess would be possible? But then you need good control over things again to get quailty results, hmm don't tell me that BlitzMAX has also problems dealing with looping and knowing when an audiochannel is no longer used?

WHY is all the FOCUS in languages on GRAPHICS WHILE AUDIO GETS THE ATTENTIONSPAN of a fruitfly.
Video and audio seem underdeveloped.

I shall look into BlitzMax Audio, everyone seem to go for things like BASS etc so I have really no high hopes now :s


Casaber(Posted 2015) [#49]
I know now!!!

and... this should work for both mid and audio?

instead of play mid (and remember mid is just an ID it could be anything)

instead of PLAY MID, use PLAY MID REPEAT, ppl have had it worked, I havenīt tried it yet bc I donīt have anything to try it with right now. It feels right to me.

If it works then you have the perfect quick solution and a better quailty loop.

Itīs not documented for MID but still good option for audio I guess. Thatīs so weird and bad to not support mid in un uniform way.

If this does not work, what about relaying on your timing, set up a blind but reliable enough timer and just shoot in the dark (just retrig with seek and play every 4 hour). 4 hours without drifting should not be impossible. Iīts orthodox but if you have the timing I would find this a good quick solution.


dw817(Posted 2015) [#50]
Hi Casaber:

I did find that BlitzMAX can and will embed that fat 4-hour song directly in the executable, but no it can't use INCBIN with MCI$ to play it.

I'm not familiar with any of the audio libraries available for BlitzMAX. Can you suggest one that would handle this dilemma of music position and length ?

I don't think VLC is such a good idea. When I wrote S2 years ago, I used RealPlayer to play .RM music. It worked, it was invisible, but it required RealPlayer to be installed.

There are powerful libraries available for MID, for instance, you can use what is called a a SOUNDFONT. Using the program, "VirtualMIDISynth" (Freeware) you can choose a considerably finer set of output instruments.

I am using "Chaos_V20.sf2" for instance at 11mb. There are great BIG sf2 files, for instance for just piano, such as "FarfisaGrandPiano_S1.sf2" at 384mb.

So - MIDI is by no means dead. If you need help with soundfonts or VirtualMidiSynth, let me know and I'll link the lot of it to a downloadable package for you.

You really should hear MIDI with the Chaos instruments, so much better than the default system instruments.


Casaber(Posted 2015) [#51]
Soundfonts are nice ya, whatever happened to them? I know they bring lot of power and quality when rightly used. It would be so much more fun to have alive sounds instead of trigging dead samples. I would love to discover a BlitzMAX library that handled midis, oggs/mp3/wav better, soundfonts and position and everything audio.


Casaber(Posted 2015) [#52]
OpenAL then? It seem to be the API to go for in audio? OpenGL and OpenAL haha.

It's poweful enough to code soundontplayer in ! for iOS even !
e.g. https://github.com/hollance/SoundBankPlayer

I like this :)


Casaber(Posted 2015) [#53]
I would definitly keep things like DX, .NET, external players, and other prooeritary, and allaround libraries such as BASS, and local API's to an absolute minimum.

OpenGL and OpenAL are the two things you can rely on now.

I tried BlitzMAX together with openAL now and GOD it is... very okayish.


Casaber(Posted 2015) [#54]
I managed to get pretty much glitchfree live audio synthesis going on. Got a sinus at least, programmatically.

A few microseconds lag though, which I hate, but Itīs.. itīs playable.
It should DEFINTLY be able to buffer your 4 hour long music somehow in turns, and without glitching.

Try it yourslelf, I'm all new to it just now so I need time to learn it properly myself.


Casaber(Posted 2015) [#55]
I found this on the forum now. This is something to dig into.

http://www.blitzmax.com/Community/posts.php?topic=95529

https://en.wikibooks.org/wiki/BlitzMax/Modules/Audio/OpenAL_1.1

To bad it is abit glitchy on OSX :( it works just fine otherwise on other platforms.
With OSX it also works great amazing speed and everything, but it has glitches.

I wonder why OpenAL seem to be lacking on ONE platform (I mean even web has its OpenAL variant), but Android is the single one lacking complete support.
There ppl seem to go for shitty things like FMOD etc instead. They are desperate for audio to work in other words.

Android is allround the shittiest system now It needs an overhaul as Windows did.
Still, OpenAL seem so nice. Curious about why Android hasnīt got it though. Maybe it doesnīt have what it takes yet.


dw817(Posted 2015) [#56]
I am trying the link you listed but am not finding an EXE or .BMX source, Casaber ?

Any luck on finding a BMX library or code to read the length and position of an MCI$ - or if there is some other way to do it with a plugin ?


Casaber(Posted 2015) [#57]
So sorry I have been having problems sleeping and keeping up with Christmas so havenīt got to that point.
I will certainly check into this as soon as I can. If you're in a hurry and if youīre using only Windows I would suggest that you split your audio i
nto parts and use OpenAL to make sure they are played perfectly chained. I would guess it will take 30 lines of code or so with OpenAL, tops.

OSx will give you clicks if you use the same naive solution there, but I think you can hide it using crossfading and use more than one channel,
until that bug is fixed. I just donīt know if it's a BlitzMAX, OpenAL, or OSX bug. Itīs a too serious bug to be inside OSX and OpenAL
Iīm thinking becuase it would defeat everything they work for.

On Windows you could do it pretty much however you like it using OpenAL and it still would work, but I would probably use more than one channel
and crossfading there aswell, simply becuase, it would not be much more code, 2-3 more lines maybe,
and it would make things all cross platform glitchfree, so it would be worth it.


Casaber(Posted 2015) [#58]
You know what? I found something.

I will call this trick playing-4-hours-of-music-looping-without-an-effort-on-the-Windows-platform. (mp3s does not count as WaveAudio but as mpegvideo). Ogg i donīt have time to couble check which one it count as. If any. MCI might be non-oggable? Try both WaveAudio and MPEGVIDEO on ogg, or use an mp3.

(Again remember "mid" is just an ID/handle in the code, nothing to do with mid)

Extern "win32"
Function mciSendStringA(cmd$z,resultbuffer:Byte Ptr=Null,buffersize=0,hwndcallback=0)
End Extern

sound$ = "birds.mp3"
mciSendStringA "open " +sound$ + " type mpegvideo alias mid"
mciSendStringA "seek mid to 0"
mciSendStringA "play Mid repeat"
WaitKey

'mciSendStringA "Pause Mid"
'mciSendStringA "resume Mid"

mciSendStringA "stop Mid"
mciSendStringA "close Mid"



Casaber(Posted 2015) [#59]
Repeat does NOT work with MIDI unfortunlty (Microsoft's idea, not mine).


dw817(Posted 2015) [#60]
This is good. Here is some earlier archived GFA code I wrote for a jukebox.
 IF @MyExist(SongPath$ + "\" + F$ + ".mid")
    Z$ = MCI$("open " + SongPath$ + "\" + F$ + ".mid alias mid")
  ELSE
    Z$ = MCI$("open c:\temp\" + F$ + ".mid alias mid")
  ENDIF
  Pica 10
  Z$ = MCI$("set mid time format ms")
  Pica 10
  Z$ = MCI$("play mid from 0 repeat")
  Pica 10
  Playing$ = F$


But you are saying it won't repeat MIDI ? Hmm ... Well, back in Windows 98 it did ...

Still, an interesting discovery you found, Casaber. Most RPG Maker music is under 2-minutes in any case. I have a whole treasure trove to work with all converted to OGG. Lots of coding still yet to be done ...

Take a break if you want. Christmas is just around the corner and while I'm not wrapping presents, I do need to get them all in order.

NEVER forget the secret energy food of a good programmer:



Yes, it is coffee. :) Happy Holidays.



Casaber(Posted 2015) [#61]
You know what?
Your words got me thinking...

Extern "win32"
Function mciSendStringA(cmd$z,resultbuffer:Byte Ptr=Null,buffersize=0,hwndcallback=0)
End Extern

Graphics 640,480
sound$ = "song.mid" ' MID OR MP3.. it doesnīt matter :)

mciSendStringA "open " + sound$ + " type mpegvideo alias sploit" ' notice mpegvideo being forced as type
mciSendStringA "play sploit from 0 repeat"

WaitKey


Iīm abit stubborn, I got it working fully, the data back now works below, I have no use for it but you probably have.
You can play HOURS of MP3s and MIDIs all you like, automatic repeat, but you also have set position, get position, and ability to
get the length (everything goes for both mp3s and mids).

Extern "win32"
Function mciSendStringA(cmd$z,resultbuffer:Byte Ptr=Null,buffersize=0,hwndcallback=0)
End Extern

Graphics 640,480
sound$ = "birds.mp3" ' MID or MP3.. it doesn't matter :)

mci "open " + sound$ + " type mpegvideo alias sploit" ' notice mpegvideo being forced as type
mci "play sploit from 0 repeat"

waitkey

'Quick reference of some practical MCI commands
'mci "set sploit time format ms" ' use milliseconds instead of PPQN
'Print "Song length is " + mci("status sploit length")
'Print "position is " + mci("status sploit position")
'mci "seek sploit to 20" ' remember a seek needs a play afterwards
'mci "play sploit"
'mci "pause sploit"
'mci "resume sploit"
'mci "stop sploit"
'mci "close sploit"

Function mci:String(msg$)
Local answer$
Local retmsg:Byte Ptr = MemAlloc(128)
Local a = mcisendstringa(msg$,retmsg,128)
answer$ = String.FromCString(retmsg)
MemFree(retmsg)
Return answer$
EndFunction



MERRY CHRISTMAS !!


dw817(Posted 2015) [#62]
Was just experimenting with it, Casaber.



O U T S T A N D I N G !

Works perfectly for MID, OGG, Mp3, and WMA, and ability to seek or read position !

You DO realize you are the ONLY one that has managed to solve this for BlitzMAX ! I would very much like to see your work highlighted and recognized as the BEST (and likely only) way to play media effectively in BlitzMAX.

Now to check something ... yep. You need quotes if you are going to load a media file from a different directory. Make this one change and your program is truly PERFECT !

sound$ = "rpg 2014\$item3.mid" ' MID or MP3.. it doesn't matter :)
sound$=chr$(34)+sound$+chr$(34)
mci "open " + sound$ + " type mpegvideo alias sploit" ' notice mpegvideo being forced as type


Now, I know you may be thinking you're still not very fond of MCI because of its clunky interface, but - it's worth it I think you'll find in the long run.

Add this command to a long list of available ones for MCI. :)

mci "setaudio sploit volume to 50"


Yep ! You can change volume too so you can have neat fade ins and fade outs. I need to pull out my OLD help files for MCI access to see what all is available now that you've opened the door to it.

No, it doesn't work with INCBIN, but that would be crazy if it did. :D

You can do this, however:
incbin "n2o.wma"
CopyFile "incbin::n2o.wma","n2o.wma"


And then play it normally.

THANK YOU BIG TIME for solving this media problem !!


Brucey(Posted 2015) [#63]
the BEST (and likely only) way to play media effectively in BlitzMAX.

It doesn't seem to work on my Mac...


Casaber(Posted 2015) [#64]

It doesn't seem to work on my Mac...



@Brucey No worries, as it says above "I will call this trick playing-4-hours-of-music-looping-without-an-effort-on-the-Windows-platform."

It's not supposed to work on MacOSX as It uses MCI which makes it Windows only.

@dw817 Nice, extra nice to hear it works with OGG aswell :) Your welcome.
I mixed together your ideas into one now, if you know other commands feel free to add them.

' --------------------------------------------------------------------
' Play MID, OGG, MP3, or WMA of any length
' With the ability to repeat, set or read position, get length etc.
' For the Windows platform
' ---------------------------------------------------------------------

Extern "win32"
Function mciSendStringA(cmd$z,resultbuffer:Byte Ptr=Null,buffersize=0,hwndcallback=0)
End Extern

Graphics 640,480
sound$ = "birds.mp3" ' MID or MP3 etc.. it doesn't matter :)
sound$=chr$(34)+sound$+chr$(34)
mci "open " + sound$ + " type mpegvideo alias sploit" ' notice mpegvideo being forced as type
mci "play sploit from 0 repeat"

waitkey

'Quick reference of some practical MCI commands
'mci "set sploit time format ms" ' use milliseconds instead of PPQN
'Print "Song length is " + mci("status sploit length")
'Print "position is " + mci("status sploit position")
'mci "seek sploit to 20" ' remember a seek needs a play afterwards
'mci "play sploit"
'mci "pause sploit"
'mci "resume sploit"
'mci "stop sploit"
'mci "close sploit"
’mci "setaudio sploit volume to 50”

Function mci:String(msg$)
Local answer$
Local retmsg:Byte Ptr = MemAlloc(128)
Local a = mcisendstringa(msg$,retmsg,128)
answer$ = String.FromCString(retmsg)
MemFree(retmsg)
Return answer$
EndFunction

’Nice way to pack inside exe
’incbin ”birds.mp3"
’CopyFile ”incbin::birds.mp3”,”birds.mp3”




dw817(Posted 2015) [#65]
Hi Brucey:

* I did not know that BlitzMAX would run on any other computer platform ! Here's a question. If I make an EXE here, outside of using MCI, does it run correctly on your Macintosh ?

Casaber, I'm already writing up libraries with your media player routine for my main engine. Both you and Tom Toad will be figured nicely in the credits (he helped me with a much better way of reading the keyboard for normal keystrokes). I anticipate this project to take me a year to write.

Which - is better than the last. The RPG Maker I wrote in GFABasic took me a bit longer than 10-years. :)

And I think you're right, MCI may be something very unique and original, only to Windows. I know I used it during Windows 3.1 playing unvarnished MIDI, so it's a long time function indeed - nice to know it still works on modern day Windows !



Additionally your routine WILL play movies ! I tried it out on a quick 22mb .MKV cartoon. It opens up a window frame to play it and I have no doubt MCI can control every aspect of that window.

Now the trick might be to somehow write a program in BlitzMAX to install or uninstall a soundfont to improve default MIDI play.


Casaber(Posted 2015) [#66]
@dw817 Sounds interesting and amazing, 10 years? haha you sound like me. I really like when people are passionate about something, thatīs how you get quality stuff going !!
Blood and sweat are what is needed.

I noticed too it could play movies and even fullscreen but I had problems understanding how it worked asynchronsly
(it basically locked up my computer until the movie was over and of course I used an 1 hour movie haha,
I had to press ctrl alt del or tab to even get out of it and then close it down). It handles mp4 and mkv very well, not pure avis though oddly enough, only compressed.

I think its because AVIs has itīs own type, so it could be used if you really wanted by changing to AVI type in that one line.

About compiler compability.. I know that BlitzMax exists as a compiler for all major desktops Apple OSX & MS Windows (even Linux).
You have to run the specific BlitzMax compiler on that particiular platform and it will compile to whatever executable filetype that platform uses.

Windows spits out .exe files, Apple uses .app files, Linux Iīm not familiar with but the same goes there. You can't crosscompile I think?
The pros here might be able to do some crosscompiling between Linux and Windows but Apple I donīt think is possible (If you manage it youīre all cutting edge and perhaps a black magic wizard).
I simply use Windows to create exe and OSX to create app and I donīt worry about trying to crosscompile anything.

Itīs nice with being multiplatform, thatīs why I talked about OpenAL so much ;) It would keep everything neat and you would not need to change any code for the different platforms.
But Windows is a powerful platform by itself so ya MCI has big value.

One thing I would like to learn now is how to write nice text, Iīm going past bitmap fonts and Iīm thinking using Freetype.
I *think* BlitzMax has cross platform support for it already? Or at least via addon? These kind of things make me prefer Blitzmax over Monkey,
which is very nice as BlitzMax but you have to start from scratch with everything and sometimes Monkey itself is not the best tool to actually do that.

I noticed Brucey is the one whoīs working on BlitzNG that will add also mobile platforms such as Google Android and Apple iOS to the mix? Exciting stuff to become mobile.

@Brucey Your doing amazing work.
If there will be a compiler change later on I will certinaly have a hard time to decide between BlitzMaxNG or Monkey2.
Will BlitzNG have Freetype easly available? Then you get my strong vote ;) With an easy installer ontop of that my vote will go through the roof haha.

Now I will truly truly take a WELL needed Holiday break.



* Merry Christmas !! *