PureBasic modules step-by-step by example (triangles!)

Share your advanced PureBasic knowledge/code with the community.
Mistrel
Addict
Addict
Posts: 3415
Joined: Sat Jun 30, 2007 8:04 pm

PureBasic modules step-by-step by example (triangles!)

Post by Mistrel »

Analyzing issues with PureBasic and how to improve it

Lets start with something simple. We'll create a window and draw a triangle.

Code: Select all

Define window.i

window=OpenWindow(#PB_Any,0,0,132,103,"",#PB_Window_SystemMenu|#PB_Window_ScreenCentered)

StartDrawing(WindowOutput(window))
FrontColor(#Black)
LineXY(65,7,113,91)
LineXY(113,91,17,91)
LineXY(17,91,65,7)
StopDrawing()

Repeat
Until WaitWindowEvent()=#PB_Event_CloseWindow
Great. But there is a problem. The points are hard-coded. And worse, we've had to type them twice (one for the end of one line and again for the start of another. So now if we want to move a point we have to analyze it closely. We can also forget moving the entire triangle around.

Great! Variables to the rescue!

Code: Select all

Define x1.l, y1.l, x2.l, y2.l, x3.l, y3.l

x1=65
y1=7
x2=113
y2=91
x3=17
y3=91

LineXY(x1,y1,x2,y2)
LineXY(x2,y2,x3,y3)
LineXY(x3,y3,x1,y1)
Now we have a bunch of variables that we can modify and the triangle line drawing will automatically update. But why have 6 variables when we only need one? This code can be further improved by using structures.

Code: Select all

Structure Triangle
  x1.l
  y1.l
  x2.l
  y2.l
  x3.l
  y3.l
EndStructure

Define triangle.Triangle

triangle\x1=65
triangle\y1=7
triangle\x2=113
triangle\y2=91
triangle\x3=17
triangle\y3=91

LineXY(triangle\x1,triangle\y1,triangle\x2,triangle\y2)
LineXY(triangle\x2,triangle\y2,triangle\x3,triangle\y3)
LineXY(triangle\x3,triangle\y3,triangle\x1,triangle\y1)
This is better. But what if we want multiple triangles? We'll need a procedure to both allocate and free the memory for the triangles. We'll have it return the structure so we can manipulate it just as easily as before.

And while we're at it, lets make a procedure to draw it as well.

Code: Select all

;-- Triangle

Structure Triangle
  x1.l
  y1.l
  x2.l
  y2.l
  x3.l
  y3.l
EndStructure

Procedure Triangle_new(x1.l, y1.l, x2.l, y2.l, x3.l, y3.l)
  Protected *triangle.Triangle=AllocateStructure(Triangle)
  
  *triangle\x1=x1
  *triangle\y1=y1
  *triangle\x2=x2
  *triangle\y2=y2
  *triangle\x3=x3
  *triangle\y3=y3
  
  ProcedureReturn *triangle
EndProcedure

Procedure Triangle_delete(*triangle.Triangle)
  FreeStructure(*triangle)
EndProcedure

Procedure Triangle_draw(*triangle.Triangle)
  LineXY(*triangle\x1,*triangle\y1,*triangle\x2,*triangle\y2)
  LineXY(*triangle\x2,*triangle\y2,*triangle\x3,*triangle\y3)
  LineXY(*triangle\x3,*triangle\y3,*triangle\x1,*triangle\y1)
EndProcedure

;--

Define window.i

window=OpenWindow(#PB_Any,0,0,132,103,"",#PB_Window_SystemMenu|#PB_Window_ScreenCentered)

Define *triangle.Triangle

*triangle=Triangle_new(65,7, 113,91, 17,91)

StartDrawing(WindowOutput(window))
FrontColor(#Black)
Triangle_draw(*triangle)
StopDrawing()

Repeat
Until WaitWindowEvent()=#PB_Event_CloseWindow
It looks like we have a lot of procedures now that have to do with triangles like Triangle_new(), Triangle_delete(), and Triangle_draw(). Lets put them into a module. I've also created an additional procedure and added a button to the window for creating random triangles when pressed.

Code: Select all

;-- Triangle
DeclareModule Triangle
  Structure Triangle
    x1.l
    y1.l
    x2.l
    y2.l
    x3.l
    y3.l
  EndStructure
  
  Declare new(x1.l, y1.l, x2.l, y2.l, x3.l, y3.l)
  Declare delete(*triangle.Triangle)
  Declare draw(*triangle.Triangle)
  Declare fromRandom(min.l, max.l)
EndDeclareModule

Module Triangle
  Procedure new(x1.l, y1.l, x2.l, y2.l, x3.l, y3.l)
    Protected *triangle.Triangle=AllocateStructure(Triangle)
    
    *triangle\x1=x1
    *triangle\y1=y1
    *triangle\x2=x2
    *triangle\y2=y2
    *triangle\x3=x3
    *triangle\y3=y3
    
    ProcedureReturn *triangle
  EndProcedure
  
  Procedure delete(*triangle.Triangle)
    FreeStructure(*triangle)
  EndProcedure
  
  Procedure draw(*triangle.Triangle)
    LineXY(*triangle\x1,*triangle\y1,*triangle\x2,*triangle\y2)
    LineXY(*triangle\x2,*triangle\y2,*triangle\x3,*triangle\y3)
    LineXY(*triangle\x3,*triangle\y3,*triangle\x1,*triangle\y1)
  EndProcedure
  
  Procedure fromRandom(min.l, max.l)
    ProcedureReturn new(Random(max,min),Random(max,min),Random(max,min),Random(max,min),Random(max,min),Random(max,min))
  EndProcedure
EndModule

;--

Procedure drawRandomTriangle(*oldTriangle, image)
  Protected *triangle.Triangle::Triangle
  
  Triangle::delete(*oldTriangle)
  *triangle=Triangle::fromRandom(10,92)
  
  FreeImage(image)
  
  DisableDebugger
  CreateImage(image,132,103,32,#PB_Image_Transparent)
  EnableDebugger
  
  StartDrawing(ImageOutput(image))
  DrawingMode(#PB_2DDrawing_AllChannels)
  FrontColor(RGBA(0,0,0,255))
  Triangle::draw(*triangle)
  StopDrawing()
EndProcedure

Define window.i
Define image.i
Define imageGadget.i
Define buttonGadget.i
Define event.i

window=OpenWindow(#PB_Any,0,0,132,136,"",#PB_Window_SystemMenu|#PB_Window_ScreenCentered)
image=CreateImage(#PB_Any,132,103,32,#PB_Image_Transparent)
imageGadget=ImageGadget(#PB_Any,0,0,132,103,ImageID(image))
buttonGadget=ButtonGadget(#PB_Any,5,109,122,23,"Random")

Define *triangle.Triangle::Triangle

*triangle=Triangle::new(65,7, 113,91, 17,91)

StartDrawing(ImageOutput(image))
DrawingMode(#PB_2DDrawing_AllChannels)
FrontColor(RGBA(0,0,0,255))
Triangle::draw(*triangle)
StopDrawing()

SetGadgetState(imageGadget,ImageID(image))

Repeat
  event=WaitWindowEvent()
  
  If event=#PB_Event_Gadget And EventGadget()=buttonGadget
    drawRandomTriangle(*triangle,image)
    SetGadgetState(imageGadget,ImageID(image))
  EndIf
Until event=#PB_Event_CloseWindow
You can see now how everything is self-contained in a module:

Code: Select all

Triangle::new(x1.l, y1.l, x2.l, y2.l, x3.l, y3.l)
Triangle::delete(*triangle.Triangle)
Triangle::draw(*triangle.Triangle)
Triangle::fromRandom(min.l, max.l)
Last edited by Mistrel on Thu Sep 16, 2021 4:00 pm, edited 3 times in total.
mestnyi
Addict
Addict
Posts: 995
Joined: Mon Nov 25, 2013 6:41 am

Re: PureBasic modules step-by-step by example (triangles!)

Post by mestnyi »

It only worked for me.

Code: Select all

;-- Triangle
DeclareModule Triangle
  Structure Triangle
    x1.l
    y1.l
    x2.l
    y2.l
    x3.l
    y3.l
  EndStructure
 
  Declare new(x1.l, y1.l, x2.l, y2.l, x3.l, y3.l)
  Declare delete(*triangle.Triangle)
  Declare draw(*triangle.Triangle)
  Declare fromRandom(min.l, max.l)
EndDeclareModule

Module Triangle
  Procedure new(x1.l, y1.l, x2.l, y2.l, x3.l, y3.l)
    Protected *triangle.Triangle=AllocateStructure(Triangle)
   
    *triangle\x1=x1
    *triangle\y1=y1
    *triangle\x2=x2
    *triangle\y2=y2
    *triangle\x3=x3
    *triangle\y3=y3
   
    ProcedureReturn *triangle
  EndProcedure
 
  Procedure delete(*triangle.Triangle)
    FreeStructure(*triangle)
  EndProcedure
 
  Procedure draw(*triangle.Triangle)
    LineXY(*triangle\x1,*triangle\y1,*triangle\x2,*triangle\y2)
    LineXY(*triangle\x2,*triangle\y2,*triangle\x3,*triangle\y3)
    LineXY(*triangle\x3,*triangle\y3,*triangle\x1,*triangle\y1)
  EndProcedure
 
  Procedure fromRandom(min.l, max.l)
    ProcedureReturn new(Random(max,min),Random(max,min),Random(max,min),Random(max,min),Random(max,min),Random(max,min))
  EndProcedure
EndModule

;--
 Global image=CreateImage(#PB_Any,132,103,32,#PB_Image_Transparent)

Procedure drawRandomTriangle(*oldTriangle, imageGadget)
  Protected *triangle.Triangle::Triangle
 
  Triangle::delete(*oldTriangle)
  *triangle=Triangle::fromRandom(10,92)
 
  ;DisableDebugger
  FreeImage(image)
  image = CreateImage(#PB_Any,132,103,32,#PB_Image_Transparent)
  ;EnableDebugger
 
  StartDrawing(ImageOutput(image))
  DrawingMode(#PB_2DDrawing_AllChannels)
  FrontColor(RGBA(0,0,0,255))
  Triangle::draw(*triangle)
  StopDrawing()
  
    SetGadgetState(imageGadget,ImageID(image))
  
  ProcedureReturn *triangle
EndProcedure

Define window.i
Define imageGadget.i
Define buttonGadget.i
Define event.i

window=OpenWindow(#PB_Any,0,0,132,136,"",#PB_Window_SystemMenu|#PB_Window_ScreenCentered)
image=CreateImage(#PB_Any,132,103,32,#PB_Image_Transparent)
imageGadget=ImageGadget(#PB_Any,0,0,132,103,ImageID(image))
buttonGadget=ButtonGadget(#PB_Any,5,109,122,23,"Random")

Define *triangle.Triangle::Triangle

*triangle=Triangle::new(65,7, 113,91, 17,91)

StartDrawing(ImageOutput(image))
DrawingMode(#PB_2DDrawing_AllChannels)
FrontColor(RGBA(0,0,0,255))
Triangle::draw(*triangle)
StopDrawing()

SetGadgetState(imageGadget,ImageID(image))

Repeat
  event=WaitWindowEvent()
 
  If event=#PB_Event_Gadget And EventGadget()=buttonGadget
    *triangle = drawRandomTriangle(*triangle,imageGadget)
  EndIf
Until event=#PB_Event_CloseWindow
Mistrel
Addict
Addict
Posts: 3415
Joined: Sat Jun 30, 2007 8:04 pm

Re: PureBasic modules step-by-step by example (triangles!)

Post by Mistrel »

mestnyi wrote:It only worked for me.
Some of the code samples were iterative and not meant to be copy/pasted as complete. The first, second-to-last, and last can be compiled as such but not the ones between.
#NULL
Addict
Addict
Posts: 1440
Joined: Thu Aug 30, 2007 11:54 pm
Location: right here

Re: PureBasic modules step-by-step by example (triangles!)

Post by #NULL »

But mestnyi is right, you shouldn't reuse a PB_ANY-generated id as a static one. (IMA if the button is clicked a second time)
Mistrel
Addict
Addict
Posts: 3415
Joined: Sat Jun 30, 2007 8:04 pm

Re: PureBasic modules step-by-step by example (triangles!)

Post by Mistrel »

mestnyi, which platform did it fail on? It worked for me on Windows.
mestnyi
Addict
Addict
Posts: 995
Joined: Mon Nov 25, 2013 6:41 am

Re: PureBasic modules step-by-step by example (triangles!)

Post by mestnyi »

Mistrel wrote:mestnyi, which platform did it fail on? It worked for me on Windows.
on mac os x
Post Reply