Help, trying to modify the height of coloured bars

Monkey Targets Forums/HTML5/Help, trying to modify the height of coloured bars

MonkeyPlotter(Posted 2017) [#1]
That have been created within a list:

Import mojo

'Original code by Pakz.....
'Attempting to modify so can have Red,green and blue bars accessible within a list... 
'so that their height is modifiable.....

Global numbars:Int=3
        
Global xpos:Int=60

Global posi:Int=20

    'make colour specific heights
    Global redHeight:Int=30
    Global blueHeight:Int=60
    Global greenHeight:Int=90

Class bar
    Field y:Float
    Field height:Int
    Field yspeed:Float
    Field direction:String
    Field incr:Float,incg:Float
    Field incb:Float
    
    Field xhere:Int,yhere:Int
    Field incx:Int,incy:Int
    
   Field redCurrent:Float=100
   Field greenCurrent:Float=150
   field blueCurrent:Float=200
     
    Field thisHeight:Int=120

    
    Method New(ri:Int,gi:Int,bi:Int,xhere:Int,yhere:Int,thisHeight:Int)
        'height=Rnd(16,90)
        'y = Rnd(height,DeviceHeight()-height)
        'incr = 255/height
        incr = ri
        incg = gi
        incb = bi
        
        incx = xhere
        incy = yhere
        height = thisHeight
        'height=90
        If Rnd(10)<5 Then 
            direction="up"
        Else
            direction="down"
        End If
        yspeed = Rnd(1,4)
        
        'height of bar modification
        'If thisColour=1'red
        'height=redHeight
        
        'Endif
        
        'If thisColour=2'green
        'height=greenHeight
        
        'Endif
        
        'If thisColour=3'blue
        'height=blueHeight
        
        'endif
  
    End Method
    
    Method update()
	    'new code that'll change the HEIGHT of the bars
	    
	    'how do I make height equal to the current height var ????
	        
	    
	    If redCurrent > redHeight
	    	redHeight = redHeight+1
	    Else
	    	redHeight = redHeight-1
	    Endif
	    
	    If blueCurrent > blueHeight
	    	blueHeight = blueHeight+1
	    Else
	    	blueHeight = blueHeight-1
	    Endif
	    
	    If greenCurrent > greenHeight
	    	greenHeight = greenHeight+1
	    Else
	    	greenHeight = greenHeight-1
	    Endif
	    
	    'old code that changed the Position of the bars
	    'want to modify this so reflects individual r,g,b heights....
	        If direction = "down"
	            y+=yspeed
	        Else
	            y-=yspeed
	        End If
	        If y<0 Then direction = "down"
	        If y>DeviceHeight()-90 Then direction = "up"
	        
	     'need to invoke some similare new code to change the Height of each individual colour....
	        
	        
	        
	        
    End Method
    
    Method draw()
        Local ypos:Int=y
        
        Local r:Int,g:Int,b:Int,xhere:Int,yhere:Int, iheight:Int
          For Local n:Int=0 To 1
        
         'top half
          For Local i=0 Until height/2
              SetColor r,g,b
              'DrawLine 20,ypos+i,DeviceWidth(),ypos+i
              DrawLine 20+incx,40+incy+i+y,30+incx,40+incy+i+y
              r+=incr
              g+=incg
              b+=incb
          Next
          
          'bottom half
          For Local i=0 Until height/2
              SetColor r,g,b
              DrawLine 15+incx,35+incy+i,15+incx,35+incy+i        
              r-=incr
              g-=incg
              b-=incb
          Next
          Next
        
    End Method
    
End Class

Global mybar:List<bar> = New List<bar>

Class MyGame Extends App

    Method OnCreate()
        SetUpdateRate(60)
        'For Local i=0 Until numbars
        '    mybar.AddLast(New bar(Rnd(155,255)/45,Rnd(0.5,2),Rnd(0.2,2)))
        '   Next
        
        mybar.AddLast(New bar(250,5,5,30,redHeight,10))
        mybar.AddLast(New bar(5,250,5,60,blueHeight,20))
        mybar.AddLast(New bar(5,5,250,90,greenHeight,30))
        
        
    End Method
    
    Method OnUpdate()
    
    	'How to increment the Height on just the blue bar   ?
    	
    	
    	'How To Decrement the height on the RED bar   ?
    
    
        For Local i:=Eachin mybar
        'iterating through each bar
        
        	'mybar.thisHeight=+1
        
            i.update
            'xpos=xpos+90 makes no odds
        Next
        
            'xpos=60
    End Method
    
    Method OnRender()
          Cls 0,0,0           
        For Local i:=Eachin mybar
            i.draw	
        Next
        SetColor 255,255,255
        DrawText "Monkey-X - Pakz Copper Bars and Classes/Lists Example.",10,10
        DrawText "Modified slightly by MonkeyPlotter in a vain attempt at making red, green and blue bars",10,25
        DrawText "That can have their height individually modified. Work in Progress.....",10,50
        
        xpos=100
    End Method
    
End Class


Function Main()
    New MyGame()   

End Function




Gerry Quinn(Posted 2017) [#2]
Um... what are you trying to make them do?


dawlane(Posted 2017) [#3]
As what Gerry Quinn says "What are you trying to do?".
Are you trying to do a graphic equaliser?
Are you trying to create bouncing bars whose length may vary?
Are you trying to do the same as the last, but the bars having a rubber band effect?

If you are using a list container, you will need a way to identify that object in a list such as a unique number. If anything, a container type that allows indexing would be better.


Simonsuuri(Posted 2017) [#4]
I also didnt get how you want to use such action, (it does have effect what is good way to make it.)

but here is something what could be usefull....




I would change bar:Class New Method a litlle easier



dawlane(Posted 2017) [#5]
Here's a working example of a pseudo graphics equaliser.
' Use strict mode to trap any program errors
Strict

Import mojo

' Global variable to hold the very bottom limit
' This could be moved into the bar class as a normal field and calculated each time
' a new bar is created
Global bottomLine:Int = 100

' Set some constant limits.
' This makes it easier to change things without having to alter hundreds of lines of code
Const LIMIT:Int = 200
Const START:Int = 24
Const GRAVITY:Int = 4
Const COLUMNS:Int = 30
Const BAR_UPDATE_COUNT:Int = 9

' General storage for the colour of bar in Red, Green, Blue format.
' There's nothing to stop you from adding an alpha value to this
Class CRGB
	Field R:Int
	Field G:Int
	Field B:Int
	
	Method New(r:Int, g:Int, b:Int)
		Self.R = r
		Self.G = g
		Self.B = b
	End Method
End Class

' A basic rectangle to store the X/Y screen positions and it's width and height.
Class CRect
	Field X:Int
	Field Y:Int
	Field W:Int
	Field H:Int
	
	Method New(x:Int = 0, y:Int = 0, w:Int = 16, h:Int = 1)
		Self.X = x
		Self.Y = y
		Self.W = w
		Self.H = h
	End Method
End Class

' Bars are fixed width, this makes it easier to find a bar by a position/column number
Class CBar
	' Store the bar as a global list within the class. 
	Global barList:= New List<CBar>
	
	Field column:Int
	Field colour:CRGB
	Field rect:CRect
	Field originalY:Int
	
	' Create a new bar giving the column number and initial height.
	' You can override the RGB values with your own
	Method New(col:Int, height:Int, r:Int = 255, g:Int = 255, b:Int = 255)	
		Self.colour = New CRGB(r,g,b)
		Self.rect = New CRect()
		Self.column = col
		Self.CalculateHeight(height)
		Self.rect.X = CalculatePosition(col)
	End Method
	
	' Basically calculate the height and Y position from the bottom
	Method CalculateHeight:Void(height:Int)
		If height > LIMIT Then height = LIMIT
		Self.rect.H = height
		Self.rect.Y = bottomLine - Self.rect.H
	End Method
	
	' Calculate the column position
	Method CalculatePosition:Int(pos:Int)
		Return START + (pos * (Self.rect.W+4))
	End Method
	
	' Update the bar graphic height based on a gravity
	Method UpdateBar:Void()
		If Self.rect.Y < (bottomLine - GRAVITY)
			Self.CalculateHeight(Self.rect.H - GRAVITY)
		Else
			Self.CalculateHeight(GRAVITY)
		Endif
	End Method
	
	' A function to change the height of a bar based on its column number
	Function ChangeBar:Void(col:Int, height:Int)
		For Local i:= Eachin CBar.barList
			If i.column = col Then 
				i.CalculateHeight(height)
				i.originalY = bottomLine - height
			EndIf
		Next
	End Function
	
	' Set the colour of the bar and draw a rectangle
	Method Draw:Void()
		SetColor(Self.colour.R, Self.colour.G, Self.colour.B)
		DrawRect(Self.rect.X, Self.rect.Y, Self.rect.W, Self.rect.H)
		DrawLine(Self.rect.X, Self.originalY, Self.rect.X + Self.rect.W, Self.originalY)
	End Method
End Class

' Main Mojo App Class
Class CGame Extends App

	' Initialise the bottom line based on the device height and add a number of column
	Method OnCreate:Int()
		bottomLine = DeviceHeight() - bottomLine
		SetUpdateRate(60)
		
		For Local i:Int = 0 To (COLUMNS - 3) Step 3
			CBar.barList.AddLast(New CBar(i, Rnd(LIMIT), 255, 0, 0))
			CBar.barList.AddLast(New CBar(i+1, Rnd(LIMIT), 0, 255, 0))
			CBar.barList.AddLast(New CBar(i+2, Rnd(LIMIT), 0, 0, 255))
		Next
		Return 0
	End Method
	
	' Iterate the list for the bars.
	Method OnUpdate:Int()
		' First randomly change a set number of bars.
		For Local i:Int = 0 To BAR_UPDATE_COUNT
			CBar.ChangeBar(Rnd(COLUMNS),Rnd(LIMIT))
		Next
		
		' Now re-evaluate the bars in the list
		For Local i:= Eachin CBar.barList
			i.UpdateBar()
		Next
		Return 0
	End Method
	
	' Clear the screen and draw the bars in the list
	Method OnRender:Int()
		Cls(0,0,0)
		For Local i:= Eachin CBar.barList
			i.Draw()
		Next
		Return 0
	End Method
End Class

' Program entry point
Function Main:Int()
	New CGame()
	Return 0
End Function



MonkeyPlotter(Posted 2017) [#6]
Thank you for the feedback everyone, its really appreciated. Unfortunately I've discovered your replies 11 minutes before I have to get ready for work....

I was/am trying to present bars which will represent data which will change between 0 to 100 percent effort related to data which has been parsed and is being replayed against two other similar files. So, I suppose graphic equalizer is a good descriptor for it ;)

I know I could have achieved this without trying to use a list example... but I was keen to try and make that work.

I'm trying the examples quickly now ... mins to spare before popping of to the grindstone ;)

[EDIT] Awesome, right off to put my poached eggs on ;)




dawlane(Posted 2017) [#7]
I shall try to give you a bit of advise:
Trying to fit someone else's code to your needs doesn't always work, so you are better off starting from scratch.
Stick to the KISS (Keep It Simple Silly) principle. If you notice, I broke various parts into individual classes. I could have rolled everything into one class; e.g. colour,rectangle and code to manipulate it and made it a nightmare to maintain, but I chose to break them up to make it simpler; plus just in case I had use for the colour and rectangle class elsewhere. I could have just created the CBar class by extending the CRect class (a bar is a rectangle), but chose to make it a variable within the CBar class just to show whats going on.
Try to avoid using strings as method to locate objects as they use more memory. You are much better off defining a set of constant integer variables to do the task. Also unless you intend to change a global variable; then you should make it a constant for the same reason as not waste memory. A constant value should end up being hard coded into the program where as a standard variable would end up producing additional code in statements that evaluate an expression; think IF/THEN.

Below is another version of the code above, but using the Stack container and extending CRect. Note that there is a bug in the example below; I will let you find out where it is ;-)
' Use strict mode to trap any program errors
Strict

Import mojo

' Global variable to hold the very bottom limit
' This could be moved into the bar class as a normal field and calculated each time
' a new bar is created
Global bottomLine:Int = 100

' Set some constant limits.
' This makes it easier to change things without having to alter hundreds of lines of code
Const LIMIT:Int = 255
Const START:Int = 24
Const GRAVITY:Int = 4
Const COLUMNS:Int = 30
Const BAR_UPDATE_COUNT:Int = 9

' A basic rectangle to store the X/Y screen positions and it's width and height.
Class CRect
	Field X:Int
	Field Y:Int
	Field W:Int
	Field H:Int
	
	Method New(x:Int = 0, y:Int = 0, w:Int = 16, h:Int = 1)
		Self.X = x
		Self.Y = y
		Self.W = w
		Self.H = h
	End Method
End Class

' Bars are fixed width, this makes it easier to find a bar by a position/column number
Class CBar Extends CRect
	' Store the bar as a global list within the class. 
	Global barList:= New Stack<CBar>
	
	Field colour:Int[] = [255,255,255] ' Preload a simple array so that we don't have to resize it.
	Field originalY:Int
	
	' Create a new bar giving the column number and initial height.
	' You can override the RGB values with your own
	Method New(height:Int, r:Int = 255, g:Int = 255, b:Int = 255)	
		Self.colour[0] = r
		Self.colour[1] = g
		Self.colour[2] = b
		Self.CalculateHeight(height)
		Self.X = CalculatePosition(CBar.barList.Length())
	End Method
	
	' Basically calculate the height and Y position from the bottom
	Method CalculateHeight:Void(height:Int)
		If height > LIMIT Then height = LIMIT
		Self.H = height
		Self.Y = bottomLine - Self.H
	End Method
	
	' Calculate the column position
	Method CalculatePosition:Int(pos:Int)
		Return START + (pos * (Self.W+4))
	End Method
	
	' Update the bar graphic height based on a gravity
	Method UpdateBar:Void()
		If Self.Y < (bottomLine - GRAVITY)
			Self.CalculateHeight(Self.H - GRAVITY)
		Else
			Self.CalculateHeight(GRAVITY)
		Endif
	End Method
	
	' A function to change the height of a bar based on its column number
	Function ChangeBar:Void(col:Int, height:Int)
		' A Stack can be treated like an array
		Local bar:CBar = CBar.barList.Get(col)
		bar.CalculateHeight(height)
		bar.originalY = bottomLine - height
	End Function
	
	' Set the colour of the bar and draw a rectangle
	Method Draw:Void()
		SetColor(Self.colour[0], Self.colour[1], Self.colour[2])
		DrawRect(Self.X, Self.Y, Self.W, Self.H)
		DrawLine(Self.X, Self.originalY, Self.X + Self.W, Self.originalY)
	End Method
End Class

' Main Mojo App Class
Class CGame Extends App

	' Initialise the bottom line based on the device height and add a number of column
	Method OnCreate:Int()
		bottomLine = DeviceHeight() - bottomLine
		SetUpdateRate(60)
		
		For Local i:Int = 0 To (COLUMNS - 3) Step 3
			' Dealing with a Stack, so to add an element you have to push it
			CBar.barList.Push(New CBar(Rnd(LIMIT), 255, 0, 0))
			CBar.barList.Push(New CBar(Rnd(LIMIT), 0, 255, 0))
			CBar.barList.Push(New CBar(Rnd(LIMIT), 0, 0, 255))
		Next
		Return 0
	End Method
	
	' Iterate the list for the bars.
	Method OnUpdate:Int()
		' First randomly change a set number of bars.
		For Local i:Int = 0 To BAR_UPDATE_COUNT
			CBar.ChangeBar(Rnd(COLUMNS),Rnd(LIMIT))
		Next
		
		' Now re-evaluate the bars in the list
		For Local i:= Eachin CBar.barList
			i.UpdateBar()
		Next
		Return 0
	End Method
	
	' Clear the screen and draw the bars in the list
	Method OnRender:Int()
		Cls(0,0,0)
		For Local i:= Eachin CBar.barList
			i.Draw()
		Next
		Return 0
	End Method
End Class

' Program entry point
Function Main:Int()
	New CGame()
	Return 0
End Function



MonkeyPlotter(Posted 2017) [#8]
thanks again for additional help, played for an hour... too tired to carry on for now. Bit wearified, will play more at weekend ;).


MonkeyPlotter(Posted 2017) [#9]
Was it this slice of code:

' Set the colour of the bar and draw a rectangle
	Method Draw:Void()
		SetColor(Self.colour[0], Self.colour[1], Self.colour[2])
		DrawRect(Self.X, Self.Y, Self.W, Self.H)
		DrawLine(Self.X, Self.originalY, Self.X + Self.W, Self.originalY)
		
' Prevents stuff from being rendered in a blue hue after exiting this method
		SetColor(255,255,255)
	End Method


Thanks again Dawlane, this is proof that the BRL forums have by far the most helpful forum users in the Galaxy - I give you the 'power meter' (I confess, the logic under the math for the power meter is still a work in progress. However, I'm successfully parsing the Altitude with a view to dynamically showing the power exerted at any given point on a training ride. Undecided about introducing windspeed into the calculations... although knowing me I'll probably work that in too. Cheers again Dawlane. Incidentally, if it wasn't the Color, what was the 'bug' you envisaged?

You wouldn't believe it, but I did an OO course with the Open University erm.... 9 years ago. Its great to see a good working example of OO achieving the power meters - sure I could have done it 'serially' but I wouldn't have been as happy with that. Suffice to say, I'm not really consolidating that work during my daily job at the moment - working on Gliders ;)




dawlane(Posted 2017) [#10]
Was it this slice of code:
No.
It's to do with this and the number of columns that get displayed.
For Local i:Int = 0 To (COLUMNS - 3) Step 3
			' Dealing with a Stack, so to add an element you have to push it
			CBar.barList.Push(New CBar(Rnd(LIMIT), 255, 0, 0))
			CBar.barList.Push(New CBar(Rnd(LIMIT), 0, 255, 0))
			CBar.barList.Push(New CBar(Rnd(LIMIT), 0, 0, 255))
		Next
Both examples require that the number of columns have to be in sets of three. The first example would be a number columns short of the value chosen and ignore those bars as the identifier for those missing columns wouldn't be found. The second would cause a memory access violation trying to access columns that don't exist. A For loop is not the best solution when you need to add more than one different variation of the same object type.

The number of bars that you are using; then a list or stack container is over kill. You would be better off creating a bar class with all the necessary functionality and then creating three variables for each bar.


MonkeyPlotter(Posted 2017) [#11]
The number of bars that you are using; then a list or stack container is over kill. You would be better off creating a bar class with all the necessary functionality and then creating three variables for each bar.


Thanks for the enlightenment dawlane, its appreciated. My old grey matter is still able to grasp some concepts, just needs a bit more coffee to get it going ;)


MonkeyPlotter(Posted 2017) [#12]
Got two of my bars increasing in height in line with a height var being passed into a method, Yay, dynamic power meters to be implemented at the weekend - SWEET ;)


MonkeyPlotter(Posted 2017) [#13]
And here are the power bars in mall their glory: