FreeBASIC Community produced game

General discussion for topics related to the FreeBASIC project or its community.
Post Reply
paul doe
Moderator
Posts: 1730
Joined: Jul 25, 2017 17:22
Location: Argentina

Re: FreeBASIC Community produced game

Post by paul doe »

BasicCoder2 wrote:I imagined nanoShips as something small enough to inject into the body. Maybe miniShips :)
It can be anything we wish. Last night I got 'ArmedCores Last Sol Taisen' as a game title. And my nuts exploded from testosterone excess HAHAHA =D
BasicCoder2 wrote:The nano45 example code doesn't seem to have a main file to compile and run?
It's NanoHost.bas. Compile with -lang fblite.
RockTheSchock
Posts: 252
Joined: Mar 12, 2006 16:25

Re: FreeBASIC Community produced game

Post by RockTheSchock »

Nanoships Strike Force one
Year 2357.. The battle for the Belt seamed over. The Federation of Free Nations had lost. But a breakthrough in nanotechnology made the conventional Warships vulnarable. The future of space war begins...
Sofisticated autonomous nanoship factories produce and maintaine clouds of nanoships. Theese can attack defend and harvest resources.

To be contonied..
grindstone
Posts: 862
Joined: May 05, 2015 5:35
Location: Germany

Re: FreeBASIC Community produced game

Post by grindstone »

@RockTheSchock: An interesting plot.

Just as a supply of ideas:

In early 2016 I started (the attempt) to code a midage battle simulation (@RockTheSchock: Do you remember? :-) ) This is the latest test run, where you can see 1600 warriors armed with halberds (white pixels) fighting against 300 warriors armed with muskets (green pixels) on a randomly sized battlefield (every red pixel is a dead or incapacitated warrior). Every warrior is an autonomous acting object ("Type tKrieger", searching the nearest enemy, moving towards him and beginning to fight as soon as he gets into the reach of the weapon). Is that enough to call it "AI"?

This project stuck when I realised that the same framework could be used to code one of my favoured propositions: A flight operator simulation. It's nearly done now, the only thing yet missing is the speech of the radio communication.
BasicCoder2
Posts: 3906
Joined: Jan 01, 2009 7:03
Location: Australia

Re: FreeBASIC Community produced game

Post by BasicCoder2 »

BasicCoder2 wrote: From what I could see nano45 was just another shoot up game. There was nothing there to capture my interest.

paul doe replied: What would capture your interest then, concretely? Flashy/stylized graphics? Fast gameplay? It would be nice to know what everyone thinks about this, so we can evolve a design.
I added #lang "fblite" to NanoHost.bas as you suggested and it ran ok so I have some idea now of the game in question. So I assume here anyone can add their own AI driven spaceship to test in combat? That might be an interesting programming problem.

What would capture my interest? In truth I never purchased the C64 or PC to play games. However I did recognize the programming skill and creativity that went into making these games. Also writing simple games is probably an easy fun way to learn the basics of a programming language for those people without a deep mathematical background. So programming a game is of more interest than actually playing one.

When I did have a go at some of the games I usually became bored long before I could ever learn the key controls to play fast enough not to end up losing. On the Amiga I think the FA/18 Interceptor was the most interesting game as I had found learning to fly under the Golden Gate Bridge and then over Alcatraz was fun and then learning to land on the air craft carrier without coming to grief. I thought it would be fun to be able to write such 3d simulations.

With the nanoShips game I think it could be enhanced if the AI had to deal with more than one other ship, asteroid storms or maybe gravity curving the path of a missile. The tank game would have had buildings to use as a tactical advantage, maybe trees to hide behind or even smoke screens. I see in one game you could drop landmines behind in the hope the enemy would drive over one.
paul doe
Moderator
Posts: 1730
Joined: Jul 25, 2017 17:22
Location: Argentina

Re: FreeBASIC Community produced game

Post by paul doe »

RockTheSchock wrote:Nanoships Strike Force one
Year 2357.. The battle for the Belt seamed over. The Federation of Free Nations had lost. But a breakthrough in nanotechnology made the conventional Warships vulnarable. The future of space war begins...
Sofisticated autonomous nanoship factories produce and maintaine clouds of nanoships. Theese can attack defend and harvest resources.
Nice name, I added it to the random generator =D
I love this premise, it's pretty cool and sparks some very interesting ideas! By all means, continue =D
grindstone wrote:Just as a supply of ideas:
Nice. I don't understand german, unfortunately, but the code is pretty clear.
grindstone wrote:This project stuck when I realised that the same framework could be used to code one of my favoured propositions: A flight operator simulation. It's nearly done now, the only thing yet missing is the speech of the radio communication.
Would love to see it. Once this framework is in a usable state, we can start to explore other ideas too =D

Thanks for sharing! Keep them coming, I'm documenting them all =D
Last edited by paul doe on Aug 30, 2018 2:13, edited 1 time in total.
paul doe
Moderator
Posts: 1730
Joined: Jul 25, 2017 17:22
Location: Argentina

Re: FreeBASIC Community produced game

Post by paul doe »

BasicCoder2 wrote:I added #lang "fblite" to NanoHost.bas as you suggested and it ran ok so I have some idea now of the game in question. So I assume here anyone can add their own AI driven spaceship to test in combat? That might be an interesting programming problem.
Yep, that was the original idea. As coderJeff stated early, the idea was good but the implementation was brittle, so he wants to (essentially) write a more robust and flexible one.
BasicCoder2 wrote:What would capture my interest? In truth I never purchased the C64 or PC to play games. However I did recognize the programming skill and creativity that went into making these games. Also writing simple games is probably an easy fun way to learn the basics of a programming language for those people without a deep mathematical background. So programming a game is of more interest than actually playing one.
Indeed. I think that most of us started programming because we played some cool games, and then learned that you could do it, too! As for the fun factor, I think that we'll be able to accomodate everyone =D
BasicCoder2 wrote:When I did have a go at some of the games I usually became bored long before I could ever learn the key controls to play fast enough not to end up losing.
Do you like RPGs? Or roguelikes? Perhaps something with a slower pace. Of course, programming the AIs is a fun experience, too (if you're that kind of geek =D)
BasicCoder2 wrote:With the nanoShips game I think it could be enhanced if the AI had to deal with more than one other ship, asteroid storms or maybe gravity curving the path of a missile. The tank game would have had buildings to use as a tactical advantage, maybe trees to hide behind or even smoke screens. I see in one game you could drop landmines behind in the hope the enemy would drive over one.
Yes, multiple AIs fighting against each other is contemplated in the design (will be more of an 'arena' than a 'duel'). The asteroid storms and gravity curving were interesting ideas. Duly archived. Keep them coming =D
paul doe
Moderator
Posts: 1730
Joined: Jul 25, 2017 17:22
Location: Argentina

Re: FreeBASIC Community produced game

Post by paul doe »

Here are some concepts I threw together today (took a break from coding =D). Just a couple of title screens, since that's what we were doing:

This one is a classical 'space' game title screen:
Image
While this one has more of an 'oriental' feeling (I just love Bullet Hell Shooters =D):
Image

Since the overall aestetics of the game hasn't been decided yet, I'm just toying with some concepts. Does anybody have something in mind? A screenshot of some cool game you like, perhaps? =D
grindstone
Posts: 862
Joined: May 05, 2015 5:35
Location: Germany

Re: FreeBASIC Community produced game

Post by grindstone »

paul doe wrote:Would love to see it.
You already can, except of the speech it works fine (and yet stole several hours of my lifetime from me when I play... ehm, tested it, it's an excellent concentration exercise :-D ). Just download the archive, unzip it and compile the source. (Btw: This source is in english)

Brief instruction:

- To launch a plane, click at one of the yellow entries of the list on the right (wait for the radio communication to be done, it is shown at the bottom of the screen. After the pilot has confirmed the order, the plane icon appears on the runway).
- To turn, touch the plane icon and click left for turning left or click right for turning right, once for every 45 degrees.
- The tag of the plane shows the destination, the actual altitude and the actual speed. If you touch it with the cursor, it displays the target altitude/speed, left click to increase, right click to decrease.
- The tag can be moved around the plane icon with the mouse wheel.
- The plane has to leave the screen at the exit point of the destination slot at an altitude of 5000 feet, a speed <= 400 knots and heading perpendicular to the screen border.
- Press "P" to pause the game.
- Press the space bar to end the game. The actual situation is stored in a file,so you can resume it at the next start of the prog.
paul doe
Moderator
Posts: 1730
Joined: Jul 25, 2017 17:22
Location: Argentina

Re: FreeBASIC Community produced game

Post by paul doe »

grindstone wrote:You already can, except of the speech it works fine (and yet stole several hours of my lifetime from me when I play... ehm, tested it, it's an excellent concentration exercise :-D )
Indeed, I read once that they are only allowed 3 conflicts per year. Now that's what I'd call taxing =D Looks really nice, and had a good time playing it. I observed however that the game keeps counting conflicts once two planes are set to a collision route (I couldn't resist >=D), so I had like 30 conflicts accounted for a single route LOL

Really nice, indeed. Thanks for sharing!
grindstone
Posts: 862
Joined: May 05, 2015 5:35
Location: Germany

Re: FreeBASIC Community produced game

Post by grindstone »

paul doe wrote:so I had like 30 conflicts accounted for a single route LOL
The game counts the time of conflict, and you'll be fired (meaning: "Game over") if you've gathered 60 seconds. The same happens if you gather 100 minutes of delay, cause a crash or a bad exit.

With the applied framework (an array of objects, where the array itself is a static member of the Type) the object mutated from a warrior to a plane, so it shouldn't be too hard to make it a space ship or a tank. My thoughts are, that a main program could provide one or multiple types of machines (space ships, tanks, racing cars, whatever we will choose) with a number of determined features (propulsion, weaponry, manoeuvrability, range etc.) and a pilot/driver implemented as a plugin or (better IMHO) a control interface similar to the UCI - protocol, so from the view of the machine it doesn't matter if the pilot/driver is a bot or a human (or even a combination of both).
paul doe
Moderator
Posts: 1730
Joined: Jul 25, 2017 17:22
Location: Argentina

Re: FreeBASIC Community produced game

Post by paul doe »

grindstone wrote:
paul doe wrote:so I had like 30 conflicts accounted for a single route LOL
The game counts the time of conflict, and you'll be fired (meaning: "Game over") if you've gathered 60 seconds. The same happens if you gather 100 minutes of delay, cause a crash or a bad exit.
Ah, that explains a lot =D
grindstone wrote:My thoughts are, that a main program could provide one or multiple types of machines (space ships, tanks, racing cars, whatever we will choose) with a number of determined features (propulsion, weaponry, manoeuvrability, range etc.) and a pilot/driver implemented as a plugin or (better IMHO) a control interface similar to the UCI - protocol, so from the view of the machine it doesn't matter if the pilot/driver is a bot or a human (or even a combination of both).
BINGO. That's exactly the purpose of the Model-View-Controller architecture: decoupling of components, so you can transparently integrate them, and the underlying code doesn't need to know (nor care) which one is providing the functionality. This is usually implemented using an observer pattern.

As for what you call 'features', I have a couple of similar ideas in a similar vein: you design a ship (or use an existing one), then code its AI, and then put it to fight against other AIs. Naturally, you can also control the ship yourself, and the same goes for any other ship in the arena, so you see that the architecture scales well for a multiplayer arena (if/when we decide to go for it).
paul doe
Moderator
Posts: 1730
Joined: Jul 25, 2017 17:22
Location: Argentina

Re: FreeBASIC Community produced game

Post by paul doe »

Here's a simple example of the Observer Pattern, implemented using a push protocol. It's quite simple but serves to illustrate the pattern and its use:

Code: Select all

/'
  Observer pattern
'/

'' We need this to forward reference the Observer interface
type _Observer as Observer
'' Null for objects
#define NIL cptr( any ptr, 0 )

/'
  Context interface
 
  This interface defines the context for the notification, that is,
  the parameters for the message sent to the listener. It empty
  because it will vary with each individual context (which, in turn,
  depend on the interests of each observer).
  The default constructor is declared protected: to avoid direct
  instantiation of this class.
'/
type Context extends Object
  public:
    declare virtual destructor()
 
  protected:
    declare constructor()
end type

constructor Context()
end constructor

destructor Context()
end destructor

/'
  Subject interface
 
  This interface defines the 'subject' of the pattern, that is, the
  object that acts as the message dispatch service. Observers subscribe
  to receive notifications from him.
'/
type Subject extends Object
  public:
    declare virtual destructor()
   
    declare abstract sub subscribe( _
      byref as _Observer )
    declare abstract sub unsubscribe()
    declare abstract sub sendMessage( _
      byref as Context )
 
  protected:
    declare constructor()
end type

constructor Subject()
end constructor

destructor Subject()
end destructor

/'
  Observer interface
 
  This is the interface that defines the 'observers' of the pattern. They
  subscribe to receive notifications from a 'subject' when needed.
'/
type Observer extends Object
  public:
    declare virtual destructor()
   
    declare abstract sub receiveMessage( _
      byref as Context )
   
  protected:
    declare constructor()
end type

constructor Observer()
end constructor

destructor Observer()
end destructor

/'
  A concrete implementation of a context. In this case, all it does is
  store a key pressed.
'/
type KeyboardContext extends Context
  public:
    declare constructor( _
      byval as ulong )
    declare destructor() override
   
    whichKey as ulong
  
  private:
    declare constructor()
end type

constructor KeyboardContext()
end constructor

constructor KeyboardContext( _
  byval aKey as ulong )
 
  whichKey = aKey
end constructor

destructor KeyboardContext()
end destructor

/'
  A concrete implementation of a subject. In this case, this is a
  simple keyboard handler that will send a message informing the
  subscribed observers of which key has been pressed. Here, there's
  support for a single observer, but this can be easily changed to
  support more than one observer per subject (by maintaining a list
  of observers).
'/
type KeyboardSubject extends Subject
  public:
    declare constructor()
    declare destructor() override
    
    declare property done() as boolean
    
    declare sub subscribe( _
      byref as Observer ) override
    declare sub unsubscribe() override
    declare sub sendMessage( _
      byref as Context ) override
 
    declare sub update()
   
  private:
    m_observer as Observer ptr
    m_done as boolean
end type

constructor KeyboardSubject()
end constructor

destructor KeyboardSubject()
end destructor

property KeyboardSubject.done() as boolean
  return( m_done )
end property

sub KeyboardSubject.subscribe( _
  byref anObserver as Observer )
 
  m_observer = @anObserver
end sub

sub KeyboardSubject.unsubscribe()
  m_observer = NIL
end sub

sub KeyboardSubject.sendMessage( _
  byref aContext as Context )
 
  if( m_observer <> NIL ) then
    m_observer->receiveMessage( aContext )
  end if
end sub

sub KeyboardSubject.update()
  dim as string k = inkey()
 
  if( len( k ) > 0 ) then
    sendMessage( KeyboardContext( asc( k ) ) )
  end if
  
  if( k = chr( 27 ) ) then
    m_done = true
  end if
end sub

/'
  And this is a concrete implementation of an observer. Here, it
  simply listens to messages forwarded by its subject, and prints
  some text when it receives one.
'/
type KeyboardObserver extends Observer
  public:
    declare constructor()
    declare destructor() override
   
    declare sub receiveMessage( _
      byref as Context ) override
end type

constructor KeyboardObserver()
end constructor

destructor KeyboardObserver()
end destructor

sub KeyboardObserver.receiveMessage( _
  byref aContext as Context )
 
  ? "A key has been pressed!"
  var aKey = cptr( _
    KeyboardContext ptr, @aContext )->whichKey
 
  ? "ASCII code: "; aKey
end sub

/'
  Main code
'/
var theSubject = KeyboardSubject()
var theObserver = KeyboardObserver()

theSubject.subscribe( theObserver )

do
  '' Allow the subject to do any processing it needs
  theSubject.update()
 
  sleep( 1, 1 )
  '' Loops until the observer signals it's done
loop until( theSubject.done )
Last edited by paul doe on Aug 31, 2018 1:20, edited 2 times in total.
badidea
Posts: 2586
Joined: May 24, 2007 22:10
Location: The Netherlands

Re: FreeBASIC Community produced game

Post by badidea »

paul doe wrote:Here's a simple example of the Observer Pattern, implemented using a pull protocol. It's quite simple but serves to illustrate the pattern and its use: ...
Your code is like a Chinese crossword puzzle to me.

I tried to visualize it with UML. Which I have never used before and know nothing about. Probably some 'message' arrows or something missing. This is what I got so far:
Image
paul doe
Moderator
Posts: 1730
Joined: Jul 25, 2017 17:22
Location: Argentina

Re: FreeBASIC Community produced game

Post by paul doe »

badidea wrote:Your code is like a Chinese crossword puzzle to me.
Really? I revised and corrected it; I stated that it used a pull model whereas it uses a push model, actually. See if it's clearer now (the code was old, sorry).
badidea wrote:I tried to visualize it with UML. Which I have never used before and know nothing about. Probably some 'message' arrows or something missing.
Indeed, you're missing the dependency of the subject and the observer (implemented here as a weak pointer). Allow me to explain in a nutshell how the code works:

'Context', 'Subject' and 'Observer' are the interfaces for all three classes that intervene in the pattern, and KeyboardContext, KeyboardSubject and KeyboardObserver are the concrete implementations of those interfaces. Here, 'context' refers to the information that the KeyboardSubject class forwards to the KeyboardObserver class so it can update its state or perform an action. This is the actual message. In the new implementation I changed the name of the 'notify()' method from the KeyboardSubject class to 'sendMessage()', and the 'update()' method of the KeyboardObserver to 'receiveMessage()' to better reflect this fact.

The KeyboardObserver class has to subscribe to receive messages from the KeyboardSubject (I changed the name of the 'attach()' method to 'subscribe()' to clarify). So, in the main loop, we call the 'update()' method from the KeyboardSubject class to poll the keyboard and send a message informing the KeyboardObserver class when a key has been pressed. The KeyboardSubject also passes an instance of the KeyboardContext class to the KeyboardObserver that contains information relevant to the message in question, in this case, which key has been pressed.

What this accomplish is decoupling the senders of messages (the subjects) from the receivers of those messages (the observers), since the coupling is abstract and minimal; compare this with temporal coupling, which is what happens when you call the methods directly. Also, the subject can dispatch the message to any number of subscribers (broadcasting) without needing to know which ones are registered (it only knows how many observers subscribed; it doesn't care who they are as long as they conform to the observer's interface).

If this doesn't clarify it a little, tell me and I'll draw a class diagram for the pattern.

Just found this, which may come in handy ;)
fxm
Moderator
Posts: 12081
Joined: Apr 22, 2009 12:46
Location: Paris suburbs, FRANCE

Re: FreeBASIC Community produced game

Post by fxm »

One of the great interests of this method (or the similar "Abstract Factory pattern") is precisely to be able to work by abstraction, that is to say with typed base lists of derived objects.
For example in your case:
- a Subject Ptr array containing pointers to different derived object from Subject,
- an Observer Ptr array containing pointers to different derived object from Observer.

Therefore, in your code, 2 abstract procedure definitions are missing: done() and update() in Subject.

Corrected code (IMHO,) and example compatible with base typed pointers to derived objects (one single pointer to derived object in each array in code below):

Code: Select all

/'
  Observer pattern
'/

'' We need this to forward reference the Observer interface
type _Observer as Observer
'' Null for objects
#define NIL cptr( any ptr, 0 )

/'
  Context interface
 
  This interface defines the context for the notification, that is,
  the parameters for the message sent to the listener. It empty
  because it will vary with each individual context (which, in turn,
  depend on the interests of each observer).
  The default constructor is declared protected: to avoid direct
  instantiation of this class.
'/
type Context extends Object
  public:
    declare virtual destructor()
 
  protected:
    declare constructor()
end type

constructor Context()
end constructor

destructor Context()
end destructor

/'
  Subject interface
 
  This interface defines the 'subject' of the pattern, that is, the
  object that acts as the message dispatch service. Observers subscribe
  to receive notifications from him.
'/
type Subject extends Object
  public:
    declare virtual destructor()
   
    declare abstract property done() as boolean
   
    declare abstract sub subscribe( _
      byref as _Observer )
    declare abstract sub unsubscribe()
    declare abstract sub sendMessage( _
      byref as Context )
   
    declare abstract sub update()
 
  protected:
    declare constructor()
end type

constructor Subject()
end constructor

destructor Subject()
end destructor

/'
  Observer interface
 
  This is the interface that defines the 'observers' of the pattern. They
  subscribe to receive notifications from a 'subject' when needed.
'/
type Observer extends Object
  public:
    declare virtual destructor()
   
    declare abstract sub receiveMessage( _
      byref as Context )
   
  protected:
    declare constructor()
end type

constructor Observer()
end constructor

destructor Observer()
end destructor

/'
  A concrete implementation of a context. In this case, all it does is
  store a key pressed.
'/
type KeyboardContext extends Context
  public:
    declare constructor( _
      byval as ulong )
    declare destructor() override
   
    whichKey as ulong
 
  private:
    declare constructor()
end type

constructor KeyboardContext()
end constructor

constructor KeyboardContext( _
  byval aKey as ulong )
 
  whichKey = aKey
end constructor

destructor KeyboardContext()
end destructor

/'
  A concrete implementation of a subject. In this case, this is a
  simple keyboard handler that will send a message informing the
  subscribed observers of which key has been pressed. Here, there's
  support for a single observer, but this can be easily changed to
  support more than one observer per subject (by maintaining a list
  of observers).
'/
type KeyboardSubject extends Subject
  public:
    declare constructor()
    declare destructor() override
   
    declare property done() as boolean override
   
    declare sub subscribe( _
      byref as Observer ) override
    declare sub unsubscribe() override
    declare sub sendMessage( _
      byref as Context ) override
 
    declare sub update() override
   
  private:
    m_observer as Observer ptr
    m_done as boolean
end type

constructor KeyboardSubject()
end constructor

destructor KeyboardSubject()
end destructor

property KeyboardSubject.done() as boolean
  return( m_done )
end property

sub KeyboardSubject.subscribe( _
  byref anObserver as Observer )
 
  m_observer = @anObserver
end sub

sub KeyboardSubject.unsubscribe()
  m_observer = NIL
end sub

sub KeyboardSubject.sendMessage( _
  byref aContext as Context )
 
  if( m_observer <> NIL ) then
    m_observer->receiveMessage( aContext )
  end if
end sub

sub KeyboardSubject.update()
  dim as string k = inkey()
 
  if( len( k ) > 0 ) then
    sendMessage( KeyboardContext( asc( k ) ) )
  end if
 
  if( k = chr( 27 ) ) then
    m_done = true
  end if
end sub

/'
  And this is a concrete implementation of an observer. Here, it
  simply listens to messages forwarded by its subject, and prints
  some text when it receives one.
'/
type KeyboardObserver extends Observer
  public:
    declare constructor()
    declare destructor() override
   
    declare sub receiveMessage( _
      byref as Context ) override
end type

constructor KeyboardObserver()
end constructor

destructor KeyboardObserver()
end destructor

sub KeyboardObserver.receiveMessage( _
  byref aContext as Context )
 
  ? "A key has been pressed!"
  var aKey = cptr( _
    KeyboardContext ptr, @aContext )->whichKey
 
  ? "ASCII code: "; aKey
end sub

/'
  Main code
'/
var theSubject1 = KeyboardSubject()
var theObserver1 = KeyboardObserver()

dim as Subject Ptr theSubjectPtr(1 to ...) = {@theSubject1}
dim as Observer Ptr theObserverPtr(1 to ...) = {@theObserver1}

theSubjectPtr(1)->subscribe( *theObserverPtr(1) )
'' General association: theSubjectPtr(i)->subscribe( *theObserverPtr(j) )

do
  '' Allow the subject to do any processing it needs
  theSubjectPtr(1)->update()
 
  sleep( 1, 1 )
  '' Loops until the observer signals it's done
loop until( theSubjectPtr(1)->done )
Post Reply