Would anyone find a FreeBASIC vs JavaScript side-by-side series useful (+is it allowed here)?

For other topics related to the FreeBASIC project or its community.
Pritchard
Posts: 5485
Joined: Sep 12, 2005 20:06
Location: Ohio, USA

Would anyone find a FreeBASIC vs JavaScript side-by-side series useful (+is it allowed here)?

Postby Pritchard » Oct 08, 2018 1:25

Some people are finding my latest JS thread irrelevant. That was not my intent, and the same spirit that carried me here to FreeBASIC (over 15 years ago) lives on in the work I do now with JavaScript.

However, I do understand that it's technically a violation of this forum to run promotions / have thread purely about other languages.

So... As a compromise, since I genuinely love and enjoy both JavaScript and FreeBASIC... What do people (especially the mods) think about a side-by-side series demonstrating how to do things we typically do in FreeBASIC in JavaScript? Both on the client/browser and native/server?

I think it would provide value to the community as a whole (since my main thing personally is just wanting to keep that active / the spirit alive), as well as academic value for the FreeBASIC community. Thoughts?
Last edited by Pritchard on Oct 08, 2018 2:47, edited 2 times in total.
owen
Posts: 497
Joined: Apr 19, 2006 10:55
Location: Kissimmee, FL
Contact:

Re: Would a FreeBASIC vs JavaScript series be useful / allowed here?

Postby owen » Oct 08, 2018 1:59

Because my goal is to teach fb (rather, have it taught) I vote yes.

Some of the interns say they know or are learning java / js or c or vb etc... And when possible side by side code examples (FB/JS), (FB/VB), etc.. Is helpful

If I could point them to this topoc and they will learn FB by comparison the would be handy

But to see fb bashing, then no.
St_W
Posts: 1404
Joined: Feb 11, 2009 14:24
Location: Austria
Contact:

Re: Would a FreeBASIC vs JavaScript series be useful / allowed here?

Postby St_W » Oct 08, 2018 2:07

Whoa ... tbh I couldn't imagine that my post (you're referring to my post, do you?) triggered such a reaction and I didn't intend to do so.
I did not call the JS thread "irrelevant" - at least that's not what I meant - I just wanted to point out that comparing FB with JS will just result in an endless discussion without real results or without new results (similar to the "what to you like/dislike about FB" discussions we had some time ago). That doesn't mean that they have no value or - even worse - I'd like to forbid them.
On the other hand I do think that motivating people to move away from FB to other programming languages doesn't really align with FreeBasic's goals. At least as long as fbc is still alive and hasn't been replaced e.g. by a JS framework :-)
And I do think that therefore some obvious advantages of other programming languages over FB (or obvious disadvantages of FB) don't have to be discussed on this forums again and again. Yet, that's just my personal opinion and I wouldn't forbid them just because somebody doesn't like it.
After all, I repeated your recommendation to try JS and/or other programming languages because, being a software engineer myself (just like you) and having implemented projects with many tools (including JS), I'm confident that knowing different languages is beneficial and allows to choose a tool on a requirement oriented basis.
So, please don't let you stop from discussing.
dafhi
Posts: 1220
Joined: Jun 04, 2005 9:51

Re: Would anyone find a FreeBASIC vs JavaScript side-by-side series useful (+is it allowed here)?

Postby dafhi » Oct 08, 2018 3:51

JavaScript had been on my mind before your initial post .. i would enjoy a 'comparison' of sorts :-)
BasicCoder2
Posts: 3308
Joined: Jan 01, 2009 7:03

Re: Would anyone find a FreeBASIC vs JavaScript side-by-side series useful (+is it allowed here)?

Postby BasicCoder2 » Oct 08, 2018 5:33

dafhi wrote:JavaScript had been on my mind before your initial post .. i would enjoy a 'comparison' of sorts :-)

If you google "writing games with Javascript" you can make your own comparison, perhaps by writing a FreeBASIC version of the demo games.
Pritchard
Posts: 5485
Joined: Sep 12, 2005 20:06
Location: Ohio, USA

Re: Would anyone find a FreeBASIC vs JavaScript side-by-side series useful (+is it allowed here)?

Postby Pritchard » Oct 08, 2018 6:46

BasicCoder2 wrote:
dafhi wrote:JavaScript had been on my mind before your initial post .. i would enjoy a 'comparison' of sorts :-)

If you google "writing games with Javascript" you can make your own comparison, perhaps by writing a FreeBASIC version of the demo games.

This is definitely an option. Do you have any links you think are interesting?

Not sure how educational it would be, though. (Perhaps) Ideally it'd be a series starting with basics like Hello World and moving on from there, but toward a goal of having a fully functional game or application written in both languages.
jj2007
Posts: 879
Joined: Oct 23, 2016 15:28
Location: Roma, Italia
Contact:

Re: Would a FreeBASIC vs JavaScript series be useful / allowed here?

Postby jj2007 » Oct 08, 2018 7:04

St_W wrote:I do think that motivating people to move away from FB to other programming languages doesn't really align with FreeBasic's goals.
That's a nice way of describing the problem ;-)

Is there any JavaScript forum with a side-by-side series on FreeBasic? Rhetoric question, of course. What I certainly would find interesting is the possibility to tap or link to JS routines. Imagine you could enter into The World of DOM with FreeBasic... not so easy, apparently, see e.g. Boost MiniDOM.
dafhi
Posts: 1220
Joined: Jun 04, 2005 9:51

Re: Would anyone find a FreeBASIC vs JavaScript side-by-side series useful (+is it allowed here)?

Postby dafhi » Oct 08, 2018 7:13

What I like about Pritchard's idea is the fact that he offered to serve up something relevant, and of interest
marcov
Posts: 2643
Joined: Jun 16, 2005 9:45
Location: Eindhoven, NL
Contact:

Re: Would anyone find a FreeBASIC vs JavaScript side-by-side series useful (+is it allowed here)?

Postby marcov » Oct 08, 2018 7:55

I think it is offtopic.

If you want to discuss javascript features to FB? Fine.
Want to discuss javascript and FB interoperability or embedding? Fine.
Posting javascript comparisons for javascript starters: offtopic.

But if I'm mistaken, and that is allowed, I'll be happy to do a very expansive pascal comparison too :-)
Pritchard
Posts: 5485
Joined: Sep 12, 2005 20:06
Location: Ohio, USA

Re: Would a FreeBASIC vs JavaScript series be useful / allowed here?

Postby Pritchard » Oct 08, 2018 13:01

jj2007 wrote:
St_W wrote:I do think that motivating people to move away from FB to other programming languages doesn't really align with FreeBasic's goals.
That's a nice way of describing the problem ;-)

Is there any JavaScript forum with a side-by-side series on FreeBasic? Rhetoric question, of course. What I certainly would find interesting is the possibility to tap or link to JS routines. Imagine you could enter into The World of DOM with FreeBasic... not so easy, apparently, see e.g. Boost MiniDOM.

I'd probably focus on server-side / NodeJS for a lot of stuff and then browser for graphics. I have no intention of manipulating the DOM from BASIC.

I'm looking into embedding a small JS runtime in FB programs for scripting purposes, but accessing JS routines from the browser probably wouldn't work. Might work from Node.

May very well be possible to get a simple HTTP and routing utility in FB for web dev.
Lost Zergling
Posts: 145
Joined: Dec 02, 2011 22:51
Location: France

Re: Would anyone find a FreeBASIC vs JavaScript side-by-side series useful (+is it allowed here)?

Postby Lost Zergling » Oct 08, 2018 14:32

Hello Pritchard
"The DOM APIs come with XMLHttpRequest objects, and Node comes with http built-in" : Yes true, please accept my excuses Pritchard, having a parochial quarrel over the definition of server client architecture is not very productive. The point is I was thinking we were trying to compare different stuff. I was wrong.
"May very well be possible to get a simple HTTP and routing utility in FB for web dev." : Do you mean a sort of mini "NodeFB" ? Let's be open-minded.
In my opinion this would be a Great idea. It should then be featured enought allowing wide range of uses or evolutions (no just demo).
paul doe
Posts: 802
Joined: Jul 25, 2017 17:22
Location: Argentina

Re: Would a FreeBASIC vs JavaScript series be useful / allowed here?

Postby paul doe » Oct 08, 2018 15:22

Pritchard wrote:I'm looking into embedding a small JS runtime in FB programs for scripting purposes, but accessing JS routines from the browser probably wouldn't work. Might work from Node.

May very well be possible to get a simple HTTP and routing utility in FB for web dev.

Now we're talking. I agree with Lost Zergling (for a change): this is really useful, and can leverage your JavaScript knowledge for something that can actually benefit FreeBasic as a language.

You see, FreeBasic is chock-full of library wrappers, but has virtually nothing in the way of frameworks. I'm pretty sure you're already well-aware of how big of a difference this can make:

Code: Select all

'#include once "inc/tgf.bi"
/'
  Tiny Game Framework
 
  This is part of the run-time library for the Tiny Game Framework,
  developed as part of the Game Coding Tutorial series.
'/
namespace tgf
  '' The Null pointer
  const as any ptr NIL = cptr( any ptr, 0 )
 
  namespace collections
    '' Defines a callback for disposal of elements of collections
    type DisposeCallback as sub( _
      byval as any ptr )
  end namespace
end namespace

type RGBAColor as ulong

'#include once "inc/tgf-linked-list.bi"
namespace tgf
  namespace collections
    /'
      Linked list implementation
     
      This code implements an abstract doubly-linked list. It allows for
      insertion/removal of elements either from the head of the list or
      from the tail, and also allows traversal either from first-to-last
      or last-to-first. Thus, it can be used either as a queue/heap or as
      a stack, by using the appropriate methods to add/remove the elements
      of it.
     
      There'aSimulation nothing special to it, just a vanilla implementation.
    '/
    type LinkedListNode
      public:
        declare constructor( _
          byval as any ptr, _
          byval as DisposeCallback = NIL )
       
        declare destructor()
       
        item as any ptr
       
        '' This is usually called the 'next' node
        forward as LinkedListNode ptr
        '' This is usually called the 'previous' node
        backward as LinkedListNode ptr
     
      private:
        declare constructor()
       
        m_disposeCallback as DisposeCallback
    end type
   
    constructor LinkedListNode()
    end constructor
   
    constructor LinkedListNode( _
      byval pItem as any ptr, _
      byval pDisposeCallback as DisposeCallback = NIL )
     
      item = pItem
      m_disposeCallback = pDisposeCallback
    end constructor
   
    destructor LinkedListNode()
      if( m_disposeCallback <> NIL ) then
        m_disposeCallback( item )
      end if
    end destructor
   
    /'
      The LinkedList class itself
     
      This class defines the list proper. Be aware that the list is
      FULLY MUTABLE, so be careful here. FreeBasic doesn't allow to
      implement Friend classes, and making the class immutable would
      involve substantial hacks that decrease performance, so I
      didn't bother (or rather, I bothered but changed the implemen-
      tation back to a 'standard' one; the solution is too stupid and
      ugly to be shown here).
    '/
    type LinkedList extends Object
      public:
        declare constructor()
        declare destructor()
       
        declare property count() as integer
        declare property first() as LinkedListNode ptr
        declare property last() as LinkedListNode ptr
       
        declare function insertBefore( _
          byval as LinkedListNode ptr, _
          byval as any ptr, _
          byval as DisposeCallback = NIL ) as LinkedListNode ptr
       
        declare function insertAfter( _
          byval as LinkedListNode ptr, _
          byval as any ptr, _
          byval as DisposeCallback = NIL ) as LinkedListNode ptr
       
        declare function insertBeginning( _
          byval as any ptr, _
          byval as DisposeCallback = NIL ) as LinkedListNode ptr
         
        declare function insertEnd( _
          byval as any ptr, _
          byval as DisposeCallback = NIL ) as LinkedListNode ptr
       
        declare function remove( _
          byval as LinkedListNode ptr ) as any ptr
       
        declare function removeFirst() as any ptr
        declare function removeLast() as any ptr
       
      private:
        m_last as LinkedListNode ptr
        m_first as LinkedListNode ptr
       
        m_count as integer
    end type
   
    constructor LinkedList()
    end constructor
   
    destructor LinkedList()
      do while( m_count > 0 )
        remove( m_last )
      loop
    end destructor
   
    property LinkedList.count() as integer
      return( m_count )
    end property
   
    property LinkedList.first() as LinkedListNode ptr
      return( m_first )
    end property
   
    property LinkedList.last() as LinkedListNode ptr
      return( m_last )
    end property
   
    function LinkedList.insertAfter( _
      byval node as LinkedListNode ptr, _
      byval pItem as any ptr, _
      byval pDisposeCallback as DisposeCallback = NIL ) as LinkedListNode ptr
     
      var newNode = new LinkedListNode( pItem, pDisposeCallback )
     
      newNode->backward = node
      newNode->forward = node->forward
     
      if( node->forward = NIL ) then
        m_last = newNode
      else
        node->forward->backward = newNode
      end if
     
      m_count += 1
      node->forward = newNode
     
      return( newNode )
    end function
   
    function LinkedList.insertBefore( _
      byval node as LinkedListNode ptr, _
      byval pItem as any ptr, _
      byval pDisposeCallback as DisposeCallback = NIL ) as LinkedListNode ptr
     
      var newNode = new LinkedListNode( pItem, pDisposeCallback )
     
      newNode->backward = node->backward
      newNode->forward = node
     
      if( node->backward = NIL ) then
        m_first = newNode
      else
        node->backward->forward = newNode
      end if
     
      m_count += 1
      node->backward = newNode
     
      return( newNode )
    end function
   
    function LinkedList.insertBeginning( _
      byval pItem as any ptr, _
      byval pDisposeCallback as DisposeCallback = NIL ) as LinkedListNode ptr
     
      if( m_first = NIL ) then
        var newNode = new LinkedListNode( pItem, pDisposeCallback )
       
        m_first = newNode
        m_last = newNode
        newNode->backward = NIL
        newNode->forward = NIL
       
        m_count += 1
       
        return( newNode )
      else
        return( insertBefore( m_first, pItem, pDisposeCallback ) )
      end if
    end function
   
    function LinkedList.insertEnd( _
      byval pItem as any ptr, _
      byval pDisposeCallback as DisposeCallback = NIL ) as LinkedListNode ptr
     
      if( m_last = NIL ) then
        return( insertBeginning( pItem, pDisposeCallback ) )
      else
        return( insertAfter( m_last, pItem, pDisposeCallback ) )
      end if
    end function
   
    function LinkedList.remove( _
      byval node as LinkedListNode ptr ) as any ptr
   
      dim as any ptr ret = NIL
     
      if( m_count > 0 ) then
        ret = node->item
       
        if( node->backward = NIL ) then
          m_first = node->forward
        else
          node->backward->forward = node->forward
        end if
       
        if( node->forward = NIL ) then
          m_last = node->backward
        else
          node->forward->backward = node->backward
        end if
       
        m_count -= 1
        delete( node )
      end if
     
      return( ret )
    end function
   
    function LinkedList.removeFirst() as any ptr
      return( remove( m_first ) )
    end function
   
    function LinkedList.removeLast() as any ptr
      return( remove( m_last ) )
    end function
  end namespace
end namespace

namespace tgf
  namespace math
    /'
      Several useful basic math functions and constants.
    '/
    #ifndef floor
      #define floor( x ) ( ( ( x ) * 2.0 - 0.5 ) shr 1 )
    #endif
   
    #ifndef ceil
      #define ceil( x ) ( - ( ( - ( x ) * 2.0 -0.5 ) shr 1 ) )
    #endif
   
    #ifndef max
      #define max( a, b ) _
        iif( ( a ) > ( b ), ( a ), ( b ) )
    #endif
   
    #ifndef min
      #define min( a, b ) _
        iif( ( a ) > ( b ), ( a ), ( b ) )
    #endif
   
    /'
      TODO: make clamp() and wrap() allow for arbitrary limits
    '/
    #ifndef clamp
      #define clamp( v, mn, mx ) _
        iif( ( v ) < ( mn ), ( mn ), _
        iif( ( v ) > ( mx ), ( mx ), ( v ) ) )
    #endif
   
    #ifndef wrap
      #define wrap( wrapValue, v ) _
        ( ( ( v ) + ( wrapValue ) ) mod ( wrapValue ) )
    #endif
   
    '#ifndef floor
    '  #define floor( x ) ( int( x ) )
    '#endif
    '
    '#ifndef ceil
    '  #define ceil( x ) _
    '    ( -cint( ( -x * 2.0 - 0.5 ) / 2 ) )
    '#endif
   
    '' Portable floating-point modulus
    #ifndef fmod
      #define fmod( n, d ) _
        ( ( n ) - int( ( n ) / ( d ) ) * ( d ) )
    #endif
   
    '' Useful constants
    const as double PI = 4 * atn( 1 )
    const as double TWOPI = 2 * PI
    const as double HALFPI = PI / 2   
    const as double DEGTORAD = PI / 180
    const as double RADTODEG = 180 / PI
    const as double EPSILON = 0.00000001
   
    '' Used to express angles in another unit
    #ifndef radians
      #define radians( angle ) ( ( angle ) * DEGTORAD )
    #endif
   
    #ifndef degrees
      #define degrees( angle ) ( ( angle ) * RADTODEG )
    #endif
  end namespace
end namespace

'#include once "inc/tgf-vec2f.bi"
namespace tgf
  namespace math
    /'
      homogeneous 2D vector type
     
      | x |
      | y |
      | 1 |
    '/
    type vec2f
      public:
        declare constructor()
        declare constructor( _
          byval as single, _
          byval as single, _
          byval as single = 1.0 )
       
        declare constructor( _
          byref as vec2f )
        declare operator let( _
          byref as vec2f )
       
        declare function dot( _
          byref as vec2f ) as single
        declare function cross( _
          byref as vec2f ) as single
        declare function length() as single
        declare function squaredLength() as single
        declare function unit() as vec2f
        declare sub makeHomogeneous()
        declare sub normalize()
        declare sub turnLeft()
        declare sub turnRight()
        declare sub rotate( _
          byval as single )
        declare function angle() as single
        declare function distance( _
          byref as const vec2f ) as single
        declare sub setLength( _
          byval as single )
        declare operator cast() as string
       
        x as single
        y as single
        w as single
    end type
   
    constructor vec2f()
      x = 0.0
      y = 0.0
      w = 1.0
    end constructor
   
    constructor vec2f( _
      byval nx as single, _
      byval ny as single, _
      byval nw as single = 1.0 )
     
      x = nx
      y = ny
      w = nw
    end constructor
   
    constructor vec2f( _
      byref nv as vec2f )
     
      x = nv.x
      y = nv.y
      w = nv.w
    end constructor
   
    operator vec2f.let( _
      byref rhs as vec2f )
     
      x = rhs.x
      y = rhs.y
      w = rhs.w
    end operator
   
    '' Basic arithmetic operators
    operator +( _
      byref lhs as vec2f, byref rhs as vec2f ) as vec2f
     
      return( vec2f( lhs.x + rhs.x, lhs.y + rhs.y ) )
    end operator
   
    operator -( _
      byref lhs as vec2f, byref rhs as vec2f ) as vec2f
     
      return( vec2f( lhs.x - rhs.x, lhs.y - rhs.y ) )
    end operator
   
    operator -( byref lhs as vec2f ) as vec2f
      return( vec2f( -lhs.x, -lhs.y ) )
    end operator
   
    operator *( _
      byref lhs as vec2f, byref rhs as vec2f ) as vec2f
     
      return( vec2f( lhs.x * rhs.x, lhs.y * rhs.y ) )
    end operator
   
    operator *( _
      byref lhs as vec2f, byref rhs as single ) as vec2f
     
      return( vec2f( lhs.x * rhs, lhs.y * rhs ) )
    end operator
   
    operator *( _
      byref lhs as single, byref rhs as vec2f ) as vec2f
     
      return( vec2f( lhs * rhs.x, lhs * rhs.y ) )
    end operator
   
    operator *( _
      byref lhs as vec2f, byref rhs as integer ) as vec2f
     
      return( vec2f( lhs.x * rhs, lhs.y * rhs ) )
    end operator
   
    operator *( _
      byref lhs as integer, byref rhs as vec2f ) as vec2f
     
      return( vec2f( lhs * rhs.x, lhs * rhs.y ) )
    end operator
   
    operator /( _
      byref lhs as vec2f, byref rhs as vec2f ) as vec2f
     
      return( vec2f( lhs.x / rhs.x, lhs.y / rhs.y ) )
    end operator
   
    operator /( _
      byref lhs as vec2f, byref rhs as single ) as vec2f
     
      return( vec2f( lhs.x / rhs, lhs.y / rhs ) )
    end operator
   
    operator /( _
      byref lhs as single, byref rhs as vec2f ) as vec2f
     
      return( vec2f( lhs / rhs.x, lhs / rhs.y ) )
    end operator
   
    operator <=( _
      byref lhs as vec2f, byref rhs as vec2f ) as integer
     
      return( iif( lhs.x <= rhs.x andAlso _
        lhs.y <= rhs.y, -1, 0 ) )
    end operator
   
    operator >=( _
      byref lhs as vec2f, byref rhs as vec2f ) as integer
     
      return( iif( lhs.x >= rhs.x andAlso _
        lhs.y >= rhs.y, -1, 0 ) )
    end operator
   
    operator <>( _
      byref lhs as vec2f, byref rhs as vec2f ) as integer
     
      return( iif( lhs.x <> rhs.x orElse _
        lhs.y <> rhs.y, -1, 0 ) )
    end operator
   
    operator vec2f.cast() as string
      return(   _
        "[" & str( x ) & "]" & chr( 10 ) & chr( 13 ) & _
        "[" & str( y ) & "]" & chr( 10 ) & chr( 13 ) & _
        "[" & str( w ) & "]" )
    end operator
   
    function vec2f.dot( _
      byref v as vec2f ) as single
      /'
        Returns the dot product of this vector with another
        vector v
      '/
      return( x * v.x + y * v.y )
    end function
   
    function dot overload( _
      byref v as vec2f, byref w as vec2f ) as single
     
      return( v.x * w.x + v.y * w.y )
    end function
   
    function vec2f.cross overload( _
      byref v as vec2f ) as single
      /'
        The cross product is not defined in 2d, so this _
        function returns the z component of the cross product
        of this vector with vector v, augmented to 3d
      '/
      return( x * v.y - y * v.x )
    end function
   
    function vec2f.length() as single
      '' Returns the length of this vector
      return( sqr( x * x + y * y ) )
    end function
   
    function vec2f.squaredLength() as single
      /'
        Returns the squared length of this vector.
       
        Useful when one just want to compare two vectors to
        see which is longest, as this avoids computing the
        square root.
      '/
      return( x * x + y * y )
    end function
   
    function vec2f.unit() as vec2f
      '' Returns a normalized copy of this vector, without
      '' normalizing the it.
      return( vec2f( x, y ) / sqr( x * x + y * y ) )
    end function
   
    sub vec2f.normalize()
      '' Normalizes this vector
      dim as single l = sqr( x * x + y * y )
     
      x /= l
      y /= l
    end sub
   
    function normalize overload( _
      byval v as vec2f ) as vec2f
      '' Returns a normalized copy of vector v
      v.normalize()
     
      return( v )
    end function
   
    /'
      turnLeft and turnRight rotate this vector 90 degrees to
      the left and right.
     
      Very useful to quickly find normals in 2D, as the normal
      of any vector is simply the vector rotated 90 degrees.
      So, if you want to find the normal of vector v, you can
      express it like this:
     
      n = normalize( turnLeft( v ) )
    '/
    sub vec2f.turnLeft()
      this = vec2f( y, -x )
    end sub
   
    sub vec2f.turnRight()
      this = vec2f( -y, x )
    end sub
   
    function turnLeft( _
      byref v as vec2f ) as vec2f
     
      return( vec2f( v.y, -v.x ) )
    end function
   
    function turnRight( _
      byref v as vec2f ) as vec2f
     
      return( vec2f( -v.y, v.x ) )
    end function
   
    sub vec2f.rotate( _
      byval anAngle as single )
     
      '' Rotates this vector by anAngle radians
      dim as single si = sin( anAngle )
      dim as single co = cos( anAngle )
     
      this = vec2f( _
        x * co - y * si, x * si + y * co )
    end sub
   
    function rotate( _
      byref v as vec2f, byval anAngle as single ) as vec2f
      '' Returns the vector v, rotated by anAngle radians
      dim as single si = sin( anAngle )
      dim as single co = cos( anAngle )
     
      return( vec2f( _
        v.x * co - v.y * si, v.x * si + v.y * co ) )         
    end function
   
    function vec2f.angle() as single
       '' Returns the angle that this vector points to, in radians
      return( atan2( y, x ) )
    end function
   
    function vectorAngle overload( _
      byref v as vec2f ) as single
      '' Returns the angle that v vector points to, in radians
      return atan2( v.y, v.x )
    end function
   
    function vectorAngle( _
      byref v as vec2f, byref w as vec2f ) as single
      '' Returns the angle between two vectors v and w
      dim as single cosOfAngle = _
        dot( normalize( v ), normalize( w ) )
     
      return( -acos( clamp( -1.0, 1.0, cosOfAngle ) ) )
    end function
   
    sub vec2f.makeHomogeneous()
      '' Homogeneizes this vector (makes the w component 1.0)
      x /= w
      y /= w
      w /= w
    end sub
   
    sub vec2f.setLength( _
      byval newLength as single )
       '' Sets the length of this vector
      dim as single vectorAngle = atan2( y, x )
     
      x = newLength * cos( vectorAngle )
      y = newLength * sin( vectorAngle )
    end sub
   
    function distance overload( _
      byval a as vec2f, byval b as vec2f ) as single
      '' Returns the distance between two vectors
      return( ( a - b ).length )
    end function
   
    function vec2f.distance( _
      byref aVector as const vec2f ) as single
      '' Return the distance between this vector and another one
      return( ( this - aVector ).length )
    end function
   
    function alignment( _
      byval position as vec2f, _
      byval size as vec2f, _
      byval align as vec2f ) as vec2f
      /'
        Returns a vector aligned between position and position + size
        align should be a normalized vector
      '/
      return( position + size * align )
    end function
   
    function interpolate( _
      byval p0 as vec2f, _
      byval p1 as vec2f, _
      byval t as single ) as vec2f
      '' Returns the interpolation point t (0..1) between p0 and p1
      return( ( 1.0 - t ) * p0 + t * p1 )
    end function
  end namespace
end namespace

type PointList as tgf.collections.LinkedList

type PointMass
  public:
    declare constructor( _
      byref as const tgf.math.vec2f, _
      byval as boolean = false )
   
    declare destructor()
   
    declare sub applyForce( _
      byref as const tgf.math.vec2f )
    declare sub integrate( _
      byval as double )
    declare sub render()
    declare sub correct( _
      byref as const tgf.math.vec2f )
   
    declare property isFixed() as boolean
    declare property isFixed( _
      byval as boolean )
   
    position as tgf.math.vec2f = any
    prevPosition as tgf.math.vec2f = any
    acceleration as tgf.math.vec2f = any
 
  private:
    declare constructor()
   
    m_isFixed as boolean
end type

constructor PointMass()
end constructor

constructor PointMass( _
  byref aPosition as const tgf.math.vec2f, _
  byval nIsFixed as boolean = false )
 
  position = aPosition
  prevPosition = position
  acceleration = tgf.math.vec2f( 0.0, 0.0 )
  m_isFixed = nIsFixed
end constructor

destructor PointMass()
end destructor

property PointMass.isFixed() as boolean
  return( m_isFixed )
end property

property PointMass.isFixed( _
  byval value as boolean )
 
  m_isFixed = value
end property

sub PointMass.correct( _
  byref aVector as const tgf.math.vec2f )
 
  if( m_isFixed = false ) then
    position += aVector
  end if
end sub

sub PointMass.applyForce( _
  byref aForce as const tgf.math.vec2f )
 
  if( m_isFixed = false ) then
    acceleration += aForce
  end if
end sub

sub PointMass.integrate( _
  byval delta as double )
 
  if( m_isFixed = false ) then
    var oldPosition = position
   
    '' The integration is damped a little here
    position += ( position * 0.999 - prevPosition * 0.999 ) + _
      acceleration * ( delta ^ 2 )
    prevPosition = oldPosition
  end if
end sub

sub PointMass.render()
  dim as RGBAColor pointColor = iif( m_isFixed = true, _
    rgba( 255, 0, 0, 255 ), rgba( 255, 255, 255, 255 ) )
   
  circle( position.x, position.y ), _
    3, pointColor, , , , f
end sub

type ConstraintList as tgf.collections.LinkedList

type Constraint
  public:
    declare constructor( _
      byval as PointMass ptr, _
      byval as PointMass ptr )
   
    declare destructor()
   
    declare sub resolve()
    declare sub render()
   
  private:
    declare constructor()
   
    m_point1 as PointMass ptr
    m_point2 as PointMass ptr
    m_target as single
end type

constructor Constraint()
end constructor

constructor Constraint( _
  byval aPointMass as PointMass ptr, _
  byval anotherPointMass as PointMass ptr )
 
  m_point1 = aPointMass
  m_point2 = anotherPointMass
  m_target = tgf.math.distance( m_point1->position, m_point2->position )
end constructor

destructor Constraint()
end destructor

sub Constraint.resolve()
  var direction = m_point2->position - m_point1->position
  dim as single length = direction.length
  dim as single diff = ( length - m_target ) / length
 
  m_point1->correct( direction * diff * 0.5 )
  m_point2->correct( -direction * diff * 0.5 )
end sub

sub Constraint.render()
  line( m_point1->position.x, m_point1->position.y ) - _
    ( m_point2->position.x, m_point2->position.y ), rgba( 128, 128, 128, 255 )
end sub

type Simulation
  public:
    declare constructor()
    declare destructor()
   
    declare function addPoint( _
      byval as PointMass ptr ) as Simulation ptr
    declare function addConstraint( _
      byval as Constraint ptr ) as Simulation ptr
   
    declare sub advance()
    declare sub render()
   
  private:
    declare sub deletePoints()
    declare sub deleteConstraints()
    declare sub resolveConstraints()
    declare sub updatePoints( _
      byval as double )
   
    m_points as PointList ptr
    m_constraints as ConstraintList ptr
end type

constructor Simulation()
  m_points = new PointList()
  m_constraints = new ConstraintList()
end constructor

destructor Simulation()
  deleteConstraints()
  deletePoints()
end destructor

sub Simulation.deletePoints()
  var n = m_points->first
 
  do while( n <> tgf.NIL )
    delete( cptr( PointMass ptr, n->item ) )
   
    n = n->forward
  loop

  delete( m_points )
end sub

sub Simulation.deleteConstraints()
  var n = m_constraints->first
 
  do while( n <> tgf.NIL )
    delete( cptr( Constraint ptr, n->item ) )
   
    n = n->forward
  loop

  delete( m_constraints )
end sub

function Simulation.addPoint( _
  byval aPoint as PointMass ptr ) as Simulation ptr
 
  m_points->insertEnd( aPoint )
  return( @this )
end function

function Simulation.addConstraint( _
  byval aConstraint as Constraint ptr ) as Simulation ptr
 
  m_constraints->insertEnd( aConstraint )
  return( @this )
end function

sub Simulation.resolveConstraints()
  dim as integer iterations = 5
 
  for i as integer = 0 to iterations - 1
    var n = m_constraints->first
   
    do while( n <> tgf.NIL )
      dim as Constraint ptr c = n->item
     
      c->resolve()
     
      n = n->forward
    loop
  next
end sub

sub Simulation.updatePoints( _
  byval delta as double )
 
  var n = m_points->first
  var gravity = tgf.math.vec2f( 0.0, 0.98 / 3 )
 
  do while( n <> tgf.NIL )
    dim as PointMass ptr aPoint = _
      n->item
   
    aPoint->applyForce( gravity )
    aPoint->integrate( delta )
    aPoint->acceleration = tgf.math.vec2f( 0.0, 0.0 )
   
    n = n->forward
  loop
end sub

sub Simulation.advance()
  dim as integer steps = 2
  dim as double delta = 1.0 / steps
 
  for i as integer = 0 to steps - 1
    updatePoints( delta )
    resolveConstraints()
  next
end sub

sub Simulation.render()
  '' Render constraints
  var c = m_constraints->first
 
  do while( c <> tgf.NIL )
    dim as Constraint ptr aConstraint = c->item
   
    aConstraint->render()
   
    c = c->forward
  loop

  '' Render points
  var n = m_points->first
 
  do while( n <> tgf.NIL )
    dim as PointMass ptr aPoint = _
      n->item
   
    aPoint->render()
   
    n = n->forward
  loop
end sub

/'
  Main code
'/
screenRes( 800, 600, 32 )

var aSimulation = new Simulation()

var p1 = new PointMass( _
  tgf.math.vec2f( 100.0, 100.0 ), true )
var p2 = new PointMass( _
  tgf.math.vec2f( 150.0, 100.0 ), false )
var p3 = new PointMass( _
  tgf.math.vec2f( 200.0, 100.0 ), false )
var p4 = new PointMass( _
  tgf.math.vec2f( 250.0, 100.0 ), false )
var p5 = new PointMass( _
  tgf.math.vec2f( 300.0, 100.0 ), false )

var p6 = new PointMass( _
  tgf.math.vec2f( 100.0, 130.0 ), true )
var p7 = new PointMass( _
  tgf.math.vec2f( 150.0, 130.0 ), false )
var p8 = new PointMass( _
  tgf.math.vec2f( 200.0, 130.0 ), false )
var p9 = new PointMass( _
  tgf.math.vec2f( 250.0, 130.0 ), false )
var p10 = new PointMass( _
  tgf.math.vec2f( 300.0, 130.0 ), false )

aSimulation _
  ->addPoint( p1 ) _
  ->addPoint( p2 ) _
  ->addPoint( p3 ) _
  ->addPoint( p4 ) _
  ->addPoint( p5 ) _
  ->addPoint( p6 ) _
  ->addPoint( p7 ) _
  ->addPoint( p8 ) _
  ->addPoint( p9 ) _
  ->addPoint( p10 ) _

aSimulation _
  ->addConstraint( new Constraint( p1, p2 ) ) _
  ->addConstraint( new Constraint( p2, p3 ) ) _
  ->addConstraint( new Constraint( p3, p4 ) ) _
  ->addConstraint( new Constraint( p4, p5 ) ) _
  ->addConstraint( new Constraint( p6, p7 ) ) _
  ->addConstraint( new Constraint( p7, p8 ) ) _
  ->addConstraint( new Constraint( p8, p9 ) ) _
  ->addConstraint( new Constraint( p9, p10 ) ) _
  _
  ->addConstraint( new Constraint( p1, p7 ) ) _
  ->addConstraint( new Constraint( p2, p8 ) ) _
  ->addConstraint( new Constraint( p3, p9 ) ) _
  ->addConstraint( new Constraint( p4, p10 ) ) _
  _
  ->addConstraint( new Constraint( p1, p6 ) ) _
  ->addConstraint( new Constraint( p2, p7 ) ) _
  ->addConstraint( new Constraint( p3, p8 ) ) _
  ->addConstraint( new Constraint( p4, p9 ) ) _
  ->addConstraint( new Constraint( p5, p10 ) ) _

dim as string k

do
  k = inkey()
 
  if( k = "1" ) then
    p1->isFixed = p1->isFixed xor true
  end if
 
  if( k = "2" ) then
    p6->isFixed = p6->isFixed xor true
  end if

  aSimulation->advance()
 
  screenLock()
    cls()
    aSimulation->render()
  screenUnlock()
 
  sleep( 1, 1 )
loop until( k = chr( 27 ) )

delete( aSimulation )

This is a port of the JavaScript tutorial that can be found on Codeflow, here:
http://codeflow.org/entries/2010/sep/01/hard-constraints-easy-solutions/

More than 1K LOC, whereas the JS tutorial is far less. Of course, I had to code the tiny 'framework' from scratch (and my code layout is mostly vertical) but there's still a lot you need to implement yourself.
Pritchard, in another thread wrote:Just about 2 - 3 hours overall, whereas I'd probably run into major blockers with lack of generic containers and stuff in FB... I could probably use redim and arrays, but beyond that I'd have to use macros and pointer-driven constructs. With JS you just use the built-in dictionaries and you're good to go.

Indeed, but those shouldn't be 'major blockers', just minor inconveniences =D

So, other than showing porting issues or providing a framework to interface with JavaScript, this is bound to be yet another pointless thread preaching JavaScript, in a forum about FreeBasic. So, what will it be?
Last edited by paul doe on Oct 09, 2018 2:04, edited 1 time in total.
Pritchard
Posts: 5485
Joined: Sep 12, 2005 20:06
Location: Ohio, USA

Re: Would anyone find a FreeBASIC vs JavaScript side-by-side series useful (+is it allowed here)?

Postby Pritchard » Oct 08, 2018 15:59

Having a thread be called pointless is a bit frustrating. In my mind it was very clear what I'm asking.

Read the title of the thread. That is all.
MrSwiss
Posts: 2811
Joined: Jun 02, 2013 9:27
Location: Switzerland

Re: Would anyone find a FreeBASIC vs JavaScript side-by-side series useful (+is it allowed here)?

Postby MrSwiss » Oct 08, 2018 16:07

Pritchard wrote:Having a thread be called pointless is a bit frustrating.
Just as much, as your recent threads/comments on this forum are, for others? (hopefully!)
paul doe
Posts: 802
Joined: Jul 25, 2017 17:22
Location: Argentina

Re: Would anyone find a FreeBASIC vs JavaScript side-by-side series useful (+is it allowed here)?

Postby paul doe » Oct 08, 2018 16:31

Pritchard wrote:Having a thread be called pointless is a bit frustrating...

...and so it is when you don't even read the rest of the post.
Pritchard wrote:Read the title of the thread. That is all.

So, what will it be??

Return to “Community Discussion”

Who is online

Users browsing this forum: No registered users and 4 guests