OOP for Game programs?

Game development specific discussions.
BasicCoder2
Posts: 3323
Joined: Jan 01, 2009 7:03

OOP for Game programs?

Postby BasicCoder2 » Feb 12, 2018 22:30

MrSwiss wrote in thread,
viewtopic.php?f=15&p=243529#p243529
"Note: I don't fancy, the use of "shared" var's., unless absolutely required."

Although I haven't written many OO programs it seems to me that a programmer should at least know how to do OOP and as far as I know it helps remove shared variables?

This is an attempt at a "particle" object. However I am unsure as to how to implement new to create particles when say the left mouse button is down and delete particles when they have "lived" a certain length of time or some other end of life event occurs?

Code: Select all

const SCRW = 640
const SCRH = 480
const MAXP = 100  'number of particles

screenres SCRW,SCRH,32
color rgb(0,0,0),rgb(255,255,255):cls

type PARTICLE
  Public:
  as integer x
  as integer y
  as integer xd
  as integer yd
  as ulong   c
  as integer alive
  Public:
  declare sub drawParticle()
  declare sub moveParticle()
  Declare Constructor()
  Declare Constructor(x As Integer, y As Integer, xd as integer, yd as integer, c As ulong)
end type

sub PARTICLE.drawParticle()
   if this.alive > 0 then
      circle (this.x,this.y),3,this.c,,,,f
   end if
end sub

sub PARTICLE.moveParticle()
   this.x = this.x + this.xd
   this.y = this.y + this.yd
'   if this.x < 0 or this.x > SCRW then this.xd = -this.xd
'   if this.y < 0 or this.y > SCRH then this.yd = -this.yd
   if this.x < 0 or this.x > SCRW then this.alive = 0
   if this.y < 0 or this.y > SCRH then this.alive = 0
end sub

Constructor PARTICLE ()
End Constructor

Constructor PARTICLE (xx As Integer, yy As Integer, xd as integer, yd as integer, cc As ulong)
    this.x = xx
    this.y = yy
    this.xd = xd
    this.yd = yd
    this.c = cc
    this.alive = 255
End Constructor

dim shared as PARTICLE p(1 to MAXP)  'create particle array list
'initialize values
for i as integer = 1 to MAXP
   p(i) = Particle( int(rnd(1)*SCRW), int(rnd(1)*SCRH), int(rnd(1)*3)-1, int(rnd(1)*3)-1,_
          rgb( int(rnd(1)*256), int(rnd(1)*256), int(rnd(1)*256) ) )
next i

sub update()
  screenlock
  cls
  for i as integer = 1 to MAXP
     p(i).drawParticle
     p(i).moveParticle
  next i
  screenunlock
end sub

do
   update()
   sleep 2
loop until multikey(&H01)
Imortis
Posts: 1585
Joined: Jun 02, 2005 15:10
Location: USA
Contact:

Re: OOP for Game programs?

Postby Imortis » Feb 12, 2018 22:55

New and Delete work with pointers, so you will need to have an array of pointers. In your update loop, you will want to check the alive member, then if it is 0, Delete that item and set it's value to 0. Then when doing the draw/move functions you will want to check first if the item in the array is 0, and only perform the operations if it is not.

That is also helpful with re-populating the array when you click the mouse button, because you can look for items with a value of 0, then fill those with the new particle.

If you need a more in-depth description, or examples, let me know. I would be happy to provide them.

EDIT:
I decided to tweak your code and do it just for giggles.

Code: Select all

const SCRW = 640
const SCRH = 480
const MAXP = 100  'number of particles

screenres SCRW,SCRH,32
color rgb(0,0,0),rgb(255,255,255):cls

type PARTICLE
  Public:
  as integer x
  as integer y
  as integer xd
  as integer yd
  as ulong   c
  as integer alive
  Public:
  declare sub drawParticle()
  declare sub moveParticle()
  Declare Constructor()
  Declare Constructor(x As Integer, y As Integer, xd as integer, yd as integer, c As ulong)
end type

sub PARTICLE.drawParticle()
   if this.alive > 0 then
      circle (this.x,this.y),3,this.c,,,,f
   end if
end sub

sub PARTICLE.moveParticle()
   this.x = this.x + this.xd
   this.y = this.y + this.yd
'   if this.x < 0 or this.x > SCRW then this.xd = -this.xd
'   if this.y < 0 or this.y > SCRH then this.yd = -this.yd
   if this.x < 0 or this.x > SCRW then this.alive = 0
   if this.y < 0 or this.y > SCRH then this.alive = 0
   if this.alive <> 0 then this.alive -= 1
end sub

Constructor PARTICLE ()
End Constructor

Constructor PARTICLE (xx As Integer, yy As Integer, xd as integer, yd as integer, cc As ulong)
    this.x = xx
    this.y = yy
    this.xd = xd
    this.yd = yd
    this.c = cc
    this.alive = 255
End Constructor

dim shared as PARTICLE ptr p(1 to MAXP)  'create particle array list
'initialize values
for i as integer = 1 to MAXP
   p(i) = new Particle( int(rnd(1)*SCRW), int(rnd(1)*SCRH), int(rnd(1)*3)-1, int(rnd(1)*3)-1,_
          rgb( int(rnd(1)*256), int(rnd(1)*256), int(rnd(1)*256) ) )
next i

sub update()
   screenlock
   cls
   for i as integer = 1 to MAXP
      if p(i) <> 0 then
         p(i)->drawParticle
         p(i)->moveParticle
         if p(i)->alive = 0 then
            delete (p(i))
            p(i) = 0
         end if
      end if
   next i
   screenunlock
end sub

dim as integer x,y,wheel,button
do
   getmouse(x,y,wheel,button)
   if button = 1 then
      for i as integer = 1 to MAXP
         if p(i) = 0 then
            p(i) = new Particle( x, y, int(rnd(1)*3)-1, int(rnd(1)*3)-1,_
               rgb( int(rnd(1)*256), int(rnd(1)*256), int(rnd(1)*256) ) )
            exit for
         end if
      next
   end if
   update()
   sleep 2
loop until multikey(&H01)
coderJeff
Site Admin
Posts: 2733
Joined: Nov 04, 2005 14:23
Location: Ontario, Canada
Contact:

Re: OOP for Game programs?

Postby coderJeff » Feb 12, 2018 23:30

@BasicCoder2,

Yea, I was trying to minimize the code I had to post to ask the question I wanted. Here is the actual source, maybe it will give you some ideas. I feel bad though, as it is part of larger system, where everything is an object, but I am not ready to share, yet. Working towards that goal, when I can share the whole thing.

Just links (sorry in advance if they go dead):
gfx_particles.bi
gfx_particles.bas

Uses a "free" and "used" singly linked list to manage the particles. I used to only write for win32, so likely not 64bit friendly, but I am learning.
badidea
Posts: 1057
Joined: May 24, 2007 22:10
Location: The Netherlands

Re: OOP for Game programs?

Postby badidea » Feb 12, 2018 23:36

Quick hack, not really OOP, can be done much nicer (like above):

Code: Select all

const SCRW = 640
const SCRH = 480
const MAXP = 100  'number of particles

screenres SCRW,SCRH,32
color rgb(0,0,0),rgb(255,255,255):cls

type PARTICLE
   Private:
   as integer x
   as integer y
   as integer xd
   as integer yd
   as ulong   c
   Public:
   as integer alive 'make getter, or move outside PARTICLE...
   Public:
   declare sub drawParticle()
   declare sub moveParticle()
   Declare Constructor()
   Declare Constructor(x As Integer, y As Integer, xd as integer, yd as integer, c As ulong)
end type

sub PARTICLE.drawParticle()
   if alive > 0 then
      circle (x,y),3,c,,,,f
   end if
end sub

sub PARTICLE.moveParticle()
   x += xd
   y += yd
   if x < 0 or x > SCRW then alive = 0
   if y < 0 or y > SCRH then alive = 0
end sub

Constructor PARTICLE ()
End Constructor

Constructor PARTICLE (xx As Integer, yy As Integer, xd as integer, yd as integer, cc As ulong)
   x = xx
   y = yy
   this.xd = xd
   this.yd = yd
   c = cc
   alive = 255
End Constructor

dim shared as PARTICLE p(1 to MAXP)  'create particle array list
   'initialize values
   for i as integer = 1 to MAXP
   p(i) = Particle( int(rnd(1)*SCRW), int(rnd(1)*SCRH), _
      int(rnd(1)*2)*2-1, int(rnd(1)*2)*2-1,_
      rgb( int(rnd(1)*256), int(rnd(1)*256), int(rnd(1)*256) ) )
next i

function add_particle() as integer
   for i as integer = 1 to MAXP
      if p(i).alive = 0 then
         'same stuff again, to be optimised / merged...
         p(i) = Particle( int(rnd(1)*SCRW), int(rnd(1)*SCRH), _
            int(rnd(1)*2)*2-1, int(rnd(1)*2)*2-1,_
            rgb( int(rnd(1)*256), int(rnd(1)*256), int(rnd(1)*256) ) )
            return 0 'ok, added
      end if
   next
   return -1 'failed to add a particle
end function

sub update_gfx()
   screenlock
   cls
   locate 1,1 : print "press <p> to add particles"
   for i as integer = 1 to MAXP
      p(i).drawParticle
   next i
   screenunlock
end sub

sub update_game()
   for i as integer = 1 to MAXP
      p(i).moveParticle
   next i
end sub

do
   update_game()
   update_gfx()
   if inkey() = "p" then
      add_particle()
   end if
   sleep 2
loop until multikey(&H01)

Some changes:
A) Particle properties Public --> Private
B) update() --> update_gfx() & update_game()
C) xd, yd: int(rnd(1)*3)-1 --> int(rnd(1)*2)*2-1, now all particles move -1 or +1
D) remove 'this.' where possible, just because we can, unlike in python
E) Added 'add_particle()' function
F) 'new' or 'delete' not used
MrSwiss
Posts: 2874
Joined: Jun 02, 2013 9:27
Location: Switzerland

Re: OOP for Game programs?

Postby MrSwiss » Feb 13, 2018 11:04

A more effective way, to define the PARTICLE type:
(using [U/]Integer in UDT's, is a bad idea since, the size changes,
with the used bitness of the compiler, FBC-32 / FBC-64)

Code: Select all

' a 32-bit random color getter
#Define RndRGB  ( CULng(Rnd() * &hFFFFFF) + &hFF000000ul ) ' full Alpha, always

Const As Short  SCRW = 640, SCRH = 480, MAXP = 100      ' screen size, number of particles
Const As ULong  white = &hFFFFFFFF, black = &hFF000000  ' color definitions

Randomize(Timer, 3)                                     ' seed randomizer
For i As UInteger = 1 To 50                             ' warm up randomizer
    Rnd() : Rnd() : Rnd() : Rnd() : Rnd() : Rnd()
Next

' should be placed before MAIN-LOOP
ScreenRes(SCRW, SCRH, 32, 2)    ' double buffer (use Flip/ScreenCopy, to show)
ScreenSet(1, 0)
Color(black, white) : Cls

Type PARTICLE
  Private:
    As Short    x   ' same size as Integer in -lang "QB", 16-bit
    As Short    y
    As Short    xd
    As Short    yd
    As ULong    c
  Public:
    As Boolean  alive 'make getter, or move outside PARTICLE...
    Declare Sub drawParticle(ByVal radi As Single)  ' size setting of PARTICLE)
    Declare Sub moveParticle()
    Declare Constructor()
    Declare Constructor(ByVal x As Short, ByVal y As Short, ByVal xd as Short, ByVal yd as Short, ByVal c As ULong)
End Type

Sub PARTICLE.drawParticle(ByVal radi As Single)
    If This.alive Then Circle (x, y), radi, c,,,, F ' F = fill
End Sub

' and so on ...
BasicCoder2
Posts: 3323
Joined: Jan 01, 2009 7:03

Re: OOP for Game programs?

Postby BasicCoder2 » Feb 13, 2018 15:08

The reason I didn't make the alive variable a boolean is because in some games it is a measure of health. Hit too many times and the health reduces to death.
Knowing about the requirements to deal with the bitness of a compiler is something that needs to be remembered. I assume an issue in other languages like C++?
MrSwiss
Posts: 2874
Joined: Jun 02, 2013 9:27
Location: Switzerland

Re: OOP for Game programs?

Postby MrSwiss » Feb 13, 2018 15:36

BasicCoder2 wrote:Knowing about the requirements to deal with the bitness of a compiler is something that needs to be remembered.
I assume an issue in other languages like C++?
Well, I'm not familiar with C++, but in C:
    Long (C-lang) ..... = Integer (FB-lang), compiler bitness depending
    Int (C-lang) ....... = Long (FB-lang), 32-bit, fixed
    LongLong (C-lang) = LongInt (FB-lang), 64-bit, fixed
Those are the similarities, as far as I know. Applies equally to unsigned types!
dodicat
Posts: 5349
Joined: Jan 10, 2006 20:30
Location: Scotland

Re: OOP for Game programs?

Postby dodicat » Feb 14, 2018 0:18

My small contribution.

Code: Select all

Const screenw = 1024
Const screenh = 768
Const MAX_PARTICLES = 500
Const Gravity=.01
Screenres screenw,screenh,32

Type V2D
    x As single
    y As single
    dx As single
    dy As single
    As Ulong c
    As boolean active
    Declare Constructor
    Declare Function unit() As V2D 'normalized
End Type

Type Circle
    As Long x,y,r
    As Ulong c
    As Single a 'aspect ratio
    Declare Constructor
End Type

Constructor Circle
#define range(f,l) (Rnd*((l)-(f))+(f))
r=range(5,30)
x=range((screenw/2),screenw)
y=Rnd*768
c=Rgb(Rnd*255,Rnd*255,Rnd*255)
a=range(.1,3)
End Constructor

Function V2D.unit() As V2D
    Var L=Sqr(x*x+y*y)
    With This
        .x/=L
        .y/=L
    End With
    Return This
End Function

Constructor V2D
c=Rgb(Rnd*255,Rnd*255,Rnd*255)
dx=2+Rnd*2
dy=-Rnd*4
x=-5
y=500
active=1
End Constructor

Sub drawline(x As Long,y As Long,angle As Double,length As Long,col As Ulong)
    Var x2=x+length*Cos(angle)
    Var y2=y-length*Sin(angle)
    Line(x,y)-(x2,y2),col
End Sub

Function Regulate(Byval MyFps As Long,Byref fps As Long) As Long
    Static As Double timervalue,lastsleeptime,t3,frames
    frames+=1
    If (Timer-t3)>=1 Then t3=Timer:fps=frames:frames=0
    Var sleeptime=lastsleeptime+((1/myfps)-Timer+timervalue)*1000
    If sleeptime<1 Then sleeptime=1
    lastsleeptime=sleeptime
    timervalue=Timer
    Return sleeptime
End Function

Function incircle(c As Circle,mx As Long,my As Long) As Long
    If (c.a)<=1 Then
        Return(c.a)*((c.x)-(mx))*(c.a)*((c.x)-(mx)) +((c.y)-(my))*((c.y)-(my))<= (c.r)*(c.r)*(c.a)*(c.a)
    Else
        Return(c.a)*((c.x)-(mx))*(c.a)*((c.x)-(mx)) +((c.y)-(my))*((c.y)-(my))<= (c.r)*(c.r)
    End If
End Function

Function inacircle(c() As Circle,p As V2D) As Long
    For n As Long=0 To Ubound(c)
        If incircle(c(n),p.x,p.y) Then Return 1
    Next n
End Function

Sub move(p() As V2D,circ() As Circle, c As Long)
    Dim As V2D tmp,p1
    For n As Long=0 To Iif(c<=MAX_PARTICLES,c,MAX_PARTICLES)
        If p(n).active Then
            p(n).x+=p(n).dx
            p(n).y+=p(n).dy:p(n).dy+=Gravity
        End If
        tmp.x=p(n).dx
        tmp.y=p(n).dy
        tmp=tmp.unit
        Var a1=Atan2(-tmp.y,tmp.x)-2.5
        Var a2=Atan2(-tmp.y,tmp.x)+2.5
        Line( p(n).x, p(n).y ) - Step( -50*tmp.x, -50*tmp.y  ), p(n).c
        drawline(p(n).x,p(n).y,a1,10,p(n).c)
        drawline(p(n).x,p(n).y,a2,10,p(n).c)
        If p(n).y>screenh-2  Or p(n).x> screenw-2 Or inacircle(circ(),p(n))  Then p(n).active=0   
    Next
End Sub

Sub main(p() As V2D,c() As Circle)
    windowtitle "Hastings"
    Dim As Long __,btn,ctr,fps,flag
    Do
        Getmouse __,__,,btn
        If btn=1 And flag=0 Then Redim p(MAX_PARTICLES):Redim c(25):ctr=0:flag=1
        If Rnd>.0001 Then ctr+=1
        Screenlock
        Cls
        Draw String(20,20),"FPS  " &fps
        For n As Long=0 To Ubound(c)
            Circle(c(n).x,c(n).y),c(n).r,c(n).c,,,c(n).a,f
        Next
        move(p(),c(),ctr)
        Screenunlock
        Sleep regulate(60,fps),1
        flag=btn
    Loop Until Len(Inkey)
End Sub

Randomize
Redim As V2D p(MAX_PARTICLES)
Redim As Circle c(25)
main(p(),c())



 

Return to “Game Dev”

Who is online

Users browsing this forum: No registered users and 1 guest