News:

Welcome to RetroCoders Community

Main Menu

The SpaceStation

Started by mysoft, Sep 13, 2023, 04:38 AM

Previous topic - Next topic

mysoft

yet another space console game made during classes... but this time with more action!

#include "fbgfx.bi"
#include "crt.bi"

'#define UseConsole
'#define GfxScale

#if defined(__FB_DOS__) andalso defined(UseConsole)
  const ConWid=80 , ConHei=50 'minimum size!
#else
  const ConWid=80 , ConHei=60
#endif
const ConMidLin = ConHei\2-1 , ConMidCol = ConWid\2

#ifdef UseConsole
  #ifndef __FB_DOS__
    #include "MyTDT\ConsoleAuxiliar.bas"
    ConsoleFonte(8,8) 'otherwise, be aware of font size :)
    ConsolePalette(8,64,64,64)
  #endif
#else    
  #ifdef GfxScale
  #include "MyTdt\GfxResize.bas"
  Gfx.PreResize()
  #endif
  screenres ConWid*8,ConHei*8
  palette 1,0,0,85
  #ifdef GfxScale
  Gfx.Resize(ConWid*8,ConHei*8)
  #endif
#endif 

sub Cleanup() destructor
  #ifndef UseConsole
  screen 0
  #endif
  color 7,0 : cls
end sub

'#include "MyTDT\ConsoleBigFont.bas" ======================================================================
static shared as string sUpper(3),sLower(3),sDigit(3),sSymbl(3)
sub InitBigFont() constructor
  '            =====|||||=====|||||=====|||||=====|||||=====|||||=====|||||=====|||||=====|||||=====|||||=====|||||=====|||||=====|||||=====|||||=====|||||=====|||||=====
  sUpper(0) = "        /        \    _   _    __   __   ___  __   ___  ___  ___       _ _  ___                      __   __   __   __   __  ___                           ___"
  sUpper(1) = "       /   ___    \  ~ ) / \  |  | |  \ |    |  \ |    |    |    |  |   |    |  | /  |    |  | | |  |  | |  | |  | |  | |     |   |  | |  | |  | \ /  \ /    /"
  sUpper(2) = "  ,    \   ___    /   |  |a/  |--| |--< |    |  | |--- |--  | -- |--|   |    |  |<   |    |\/| |\|  |  | |--  |  | |--   --   |   |  | |  | |  |  X    |    / "
  sUpper(3) = "  /     \        /    .  \__/ |  | |__/ |___ |__/ |___ |    |__/ |  |  _|_ \_/  | \  |__  |  | | |  |__| |    |_\| |  \  __|  |   |__|  \/  |/\| / \   |   /__"
  sLower(0) = "  __       __                  __   __   ___  __   ___  ___  ___       _ _  ___                      __   __   __   __   __  ___                           ___"
  sLower(1) = " |    \      |   /\   \       |  | |  \ |    |  \ |    |    |    |  |   |    |  | /  |    |  | | |  |  | |  | |  | |  | |     |   |  | |  | |  | \ /  \ /    /"
  sLower(2) = " |     \     |                |--| |--< |    |  | |--- |--  | -- |--|   |    |  |<   |    |\/| |\|  |  | |--  |  | |--   --   |   |  | |  | |  |  X    |    / "
  sLower(3) = " |__    \  __|           ____ |  | |__/ |___ |__/ |___ |    |__/ |  |  _|_ \_/  | \  |__  |  | | |  |__| |    |_\| |  \  __|  |   |__|  \/  |/\| / \   |   /__"
  sDigit(0) = "                _._      ___                                                __    .   __   __        __   __   ___  __   __       "
  sDigit(1) = "  |   ||  _||_ ( |   0/  \ /   |    /     \  \ /   |                    /  | /|  /|     |    | |  | |    |       / |  | |  |   '  "
  sDigit(2) = "  |       _||_  -+-  /0   X         (     )  -|-  -+-       ---        /   |  |   |   --   --|  --| `-\  |--    /  |--|  --|      "
  sDigit(3) = "  .        ||   _|_)     C_<        \     /  / \   |     /         o  /    |/_|  _|_ |__   __|    | \_/  |__|  /   |__|  __|   '  "
  '            =====|||||=====|||||=====|||||=====|||||=====|||||=====|||||=====|||||=====|||||=====|||||=====|||||=====|||||=====|||||=====|||||=====|||||=====|||||=====
  for N as long = 0 to 3 
    dim as zstring ptr pzArr(...) = {strptr(sLower(N)),strptr(sUpper(N)),strptr(sDigit(N))}
    for A as long = 0 to ubound(pzArr)
      #define pzRow (*pzArr(A))    
      for I as long = 0 to len(pzRow)-1
        select case pzRow[I]
        case asc("*"): pzRow[I] = 250
        case asc("~"): pzRow[I] = 239 
        case asc("+"): pzRow[I] = 197
        case asc("o"): pzRow[I] = 254
        end select
      next I
    next A    
  next N  
end sub
sub PrintBig(sText as string)
  var iLin = csrlin() , iCol = pos()
  for iL as long = 3 to 0 step -1
    dim as string sLine
    for N as long = 1 to len(sText)
      var iChar = asc(sText,N)
      select case iChar
      case asc(";") to asc("Z")
        sLine += mid(sUpper(iL),(iChar-asc(";"))*5+1,5)
      case asc("[") to asc("z")
        sLine += mid(sLower(iL),(iChar-asc("["))*5+1,5)
      case asc("!") to asc("@")
        sLine += mid(sDigit(iL),(iChar-asc("!"))*5+1,5)      
      case else
        sLine += space(5)
      end select    
    next N
    locate iLin+iL,iCol : print sLine;
    
  next iL
end sub
'==========================================================================================================

const cMaxShield = 1024+15

type Shot
  as Long Lin,Col
  as long DiffLin,DiffCol
  as Long Erro,Cor
end type

static shared as long StarLin(127),StarCol(127)
static shared as single Ang(34),AngSpd(34)

dim shared as long ShieldHit, AlienHit, StationHit
dim shared as long ScoreStation , ScoreAlien
dim shared as Shot tShotAlien , tShotStation(8)
dim shared as byte Shield(3)
dim shared as long iShield=cMaxShield,iTicks
dim shared as long iTickCharge=0
dim shared as long AlienLin=2,AlienCol=1

function DistFromStation( iLin as long , iCol as long ) as single
  dim as long DistLin = iLin-ConMidLin , DistCol = iCol-ConMidCol
  return sqr(DistLin*DistLIn + DistCol*DistCol)
end function 

sub DrawShield( Quadrant as long )
  select case Quadrant
  case 0
    locate ConMidLin-9 , ConMidCol+1 : print "***";
    locate ConMidLin-8 , ConMidCol+4 : print    "**";
    locate ConMidLin-7 , ConMidCol+6 : print      "*";
    locate ConMidLin-6 , ConMidCol+7 : print       "*";
    locate ConMidLin-5 , ConMidCol+8 : print        "*";
    locate ConMidLin-4 , ConMidCol+8 : print        "*";
    locate ConMidLin-3 , ConMidCol+9 : print         "*";
    locate ConMidLin-2 , ConMidCol+9 : print         "*";
    locate ConMidLin-1 , ConMidCol+9 : print         "*";
  case 1
    locate ConMidLin+1 , ConMidCol+9 : print         "*";
    locate ConMidLin+2 , ConMidCol+9 : print         "*";
    locate ConMidLin+3 , ConMidCol+9 : print         "*";
    locate ConMidLin+4 , ConMidCol+8 : print        "*";
    locate ConMidLin+5 , ConMidCol+8 : print        "*";
    locate ConMidLin+6 , ConMidCol+7 : print       "*";
    locate ConMidLin+7 , ConMidCol+6 : print      "*";
    locate ConMidLin+8 , ConMidCol+4 : print    "**";
    locate ConMidLin+9 , ConMidCol+1 : print "***";
  case 2  
    locate ConMidLin+1 , ConMidCol-9 : print "*";
    locate ConMidLin+2 , ConMidCol-9 : print "*";
    locate ConMidLin+3 , ConMidCol-9 : print "*";
    locate ConMidLin+4 , ConMidCol-8 : print  "*";
    locate ConMidLin+5 , ConMidCol-8 : print  "*";
    locate ConMidLin+6 , ConMidCol-7 : print   "*";
    locate ConMidLin+7 , ConMidCol-6 : print    "*";
    locate ConMidLin+8 , ConMidCol-5 : print     "**";
    locate ConMidLin+9 , ConMidCol-3 : print       "***";
  case 3  
    locate ConMidLin-9 , ConMidCol-3 : print       "***";
    locate ConMidLin-8 , ConMidCol-5 : print     "**";
    locate ConMidLin-7 , ConMidCol-6 : print    "*";
    locate ConMidLin-6 , ConMidCol-7 : print   "*";
    locate ConMidLin-5 , ConMidCol-8 : print  "*";
    locate ConMidLin-4 , ConMidCol-8 : print  "*";
    locate ConMidLin-3 , ConMidCol-9 : print "*";
    locate ConMidLin-2 , ConMidCol-9 : print "*";
    locate ConMidLin-1 , ConMidCol-9 : print "*";
  end select
end sub
sub DrawStation()
  color 15
  locate ConMidLin-2 ,ConMidCol-7 : print chr(&hC9,&hCD,&hCB,&hCD,&hBB, 32 );"/ \";chr( 32 ,&hC9,&hCD,&hCB,&hCD,&hBB);
  locate ConMidLin-1 ,ConMidCol-7 : print chr(&hCC,&hC5,&hC5,&hC5,&hB9,&hC4);"   ";chr(&hC4,&hCC,&hC5,&hC5,&hC5,&hB9);
  locate ConMidLin-0 ,ConMidCol-7 : print chr(&hC8,&hCD,&hCA,&hCD,&hBC, 32 );"\ /";chr( 32 ,&hC8,&hCD,&hCA,&hCD,&hBC);
  locate ConMidLin+1 ,ConMidCol-1 : print                                    " _ ";
  locate ConMidLin+2 ,ConMidCol-1 : print                                    " . ";
  locate ConMidLin+3 ,ConMidCol-1 : print                                    "...";
end sub
sub DrawShieldBar()
  if iShield < cMaxShield andalso abs(iTickCharge-iTicks)>30 andalso (iTicks mod 2)=0 then iShield += 1     
  locate 1,2: color 11,0 : print "Shield: ";  
  if iShield>(cMaxShield\2) then color 10,8 else if iShield >(cMaxShield\8) then color 14,8 else color 12,8
  
  const cAdjShield = ConWid/80
  print string((iShield\16)*cAdjShield,219);
  if iShield > 0 then    
    #ifdef UseConsole
      print chr( iif( (iShield mod 16)<12 , 176+((iShield mod 16)\4) , 219 ) );
    #else
      print chr( iif((iShield mod 16) >= 8 , 219 , 221 ) );
    #endif
  end if
  color 8,0 : print string((64-((iShield+1)\16))*cAdjShield,219);
  
end sub

sub InitStars()  
  for N as long = 0 to 127
    dim as long Lin=2+rnd*(ConHei-3) , Col = 1+rnd*(ConWid-1)
    if DistFromStation(Lin,Col)<10 then N=N-1:continue for
    StarLin(N) = Lin : StarCol(N) = Col  
  next N
end sub
sub DrawStars(iForce as long=1)
  static as long iStarBase=0
  for N as long =iStarBase to iStarBase+15 
    dim as integer iChar = iif(iForce,32,screen(StarLin(N),StarCol(N)))
    if iChar=32 or iChar=250 then
      color 2+rnd*8 : locate StarLin(N),StarCol(N) : print chr(250);    
    end if
  next N
  iStarBase = (iStarBase+16) and 127
end sub

sub SyncFps()
  static as double dFPS
  static as double dSync
  static as long iFps : iFps += 1
  if abs(timer-dFPS)>=1 then
    dFPS = timer 
    locate 1,ConWid-4: color 15 : print iFps
    iFps=0
  end if
    
  if abs(timer-dSync)>1 then dSync = timer
  while (timer-dSync) < 1/60
    sleep 1,1
  wend
  dSync += 1/60

end sub
sub IntroScreen()  
  for N as long = 0 to 3
    color 10+N : DrawShield(N)
    DrawStars()
  next N
  for N as long = -1 to 0 
    color (N and 14)     
    locate ConMidLin-23,ConMidCol-34 : PrintBig("Use The Shield")
    locate ConMidLin-18,ConMidCol-28 : PrintBig("To Defend...")
    color (N and 10) : locate ConMidLin-11,ConMidCol+ 9 : PrintBig("E")
    color (N and 11) : locate ConMidLin+ 7,ConMidCol+ 9 : PrintBig("C")      
    color (N and 12) : locate ConMidLin+ 7,ConMidCol-12 : PrintBig("Z")
    color (N and 13) : locate ConMidLin-11,ConMidCol-12 : PrintBig("Q")
    color (N and 12) : locate ConMidLin+14,ConMidCol-38 : PrintBig("The SpaceStation")
    if N = -1 then 
      do          
        color (N and 3) : locate ConMidLin+21,ConMidCol-38 : PrintBig("Any Key to Start")
        for N as long = 0 to (400/16)
          DrawStars(0)            
          SyncFps()
        next N
        color 0 : locate ConMidLin+21,ConMidCol-38 : PrintBig("Any Key to Start")
        for N as long = 0 to (200/16)
          DrawStars(0)
          if len(inkey) then exit do
          SyncFps()
        next N
      loop
    end if          
  next N
end sub

sub InitAlien()
  const PI=atn(1)*8
  for N as long = 0 to ubound(Ang)
    AngSpd(N) = (rnd*2-1)/256
    Ang(N) = rnd*PI
  next N
end sub
sub DrawAlien()
  
  const PI=atn(1)*8
  
  dim as single fLin,fCol
  static as long OldLin,OldCol
  static as long iMove = 60
  dim as long Lin=any,Col=any
  
  if rnd<(1/60) then iMove += 30
  
  if iMove orelse (iTicks and 7)=0 then
    if iMove then 
      iMove -= 1
    elseif rnd<(1/15) then 
      for N as long = 0 to ubound(Ang)
        Ang(N) = fmod(Ang(N)+rnd*PI,PI)          
      next N
    end if
    do
      fLin=0:fCol=0
      for N as long = 0 to ubound(Ang)
        Ang(N) = fmod(Ang(N)+AngSpd(N)+PI,PI)
        fLin += sin(Ang(N))*(ConHei/20) : fCol += cos(Ang(N))*(ConWid/20)
      next N
      if abs(fLin)>(ConMidLin\2) then fLin = sgn(fLin)*(ConMidLin\2)
      if abs(fCol)>(ConMidCol\2) then fCol = sgn(fCol)*(ConMidCol\2)
      
      var fDist = 14+sqr(fLin*fLin + fCol*fCol)')\2
      var fAng = atan2(fLin,fCol)
      Lin = ConMidLin+sin(fAng)*fDist : Col = ConMidCol+cos(fAng)*fDist
      
      if Lin<2 then Lin=2-(Lin-2) else if Lin>(ConHei-4) then Lin=(ConHei-4)-(Lin-(ConHei-4))
      if Col<1 then Col=1-(Col-1) else if Col>(ConWid-3) then Col=(ConWid-3)-(Col-(ConWid-3))
      
      if OldLin<>Lin or OldCol<>Col then
        OldLin=Lin : OldCol=Col
        exit do
      end if    
    loop
  
    color 0
    locate AlienLin+0,AlienCol+1 : print   "#" ;
    locate AlienLin+1,AlienCol+0 : print  "#O#";
    locate AlienLin+2,AlienCol+1 : print   "#" ;
    AlienLin = Lin : AlienCol = Col
    color 10
    locate AlienLin+0,AlienCol+1 : print   "#" ;
    locate AlienLin+1,AlienCol+0 : print  "#O#";
    locate AlienLin+2,AlienCol+1 : print   "#" ;
  
  end if
end sub

sub Shoot( tShot as Shot , LinFrom as long , ColFrom as long , LinTo as long , ColTo as long , Cor as long )
  with tShot
    .Lin = LinFrom : .Col = ColFrom
    .DiffLin = LinTo-.Lin
    .DiffCol = ColTo-.Col
    .Erro = 0 : .Cor = Cor
  end with
end sub
sub KillShot( tShot as Shot )
  with tShot
    locate .Lin,.Col : Print " ";
    .Lin = 0
  end with
end sub
sub MoveShot( tShot as Shot )
  with tShot
    locate .Lin,.Col : Print " ";
    if abs(.DiffLin) > abs(.DiffCol) then
      'bigger difference is row
      .Lin = .Lin+sgn(.DiffLin)
      .Erro = .Erro+abs(.DiffCol)
      if .Erro > abs(.DiffLin) then
        .Col = .Col+sgn(.DiffCol)
        .Erro = .Erro-abs(.DiffLin)
      end if
    else
      'bigger or equal difference is column
      .Col = .Col+sgn(.DiffCol)
      .Erro = .Erro+abs(.Difflin)
      if .Erro > abs(.Diffcol) then
        .Lin = .Lin+sgn(.Difflin)
        .Erro = .Erro-abs(.DiffCol)
      end if
    end if
    if .Lin<3 or .Lin>(ConHei-2) or .Col<1 or .Col>ConWid then
      KillShot( tShot ) : exit sub
    end if
    locate .Lin,.Col 
    color .Cor : Print chr(&hFE);  
  end with
end sub

sub ProcessShooting()
  with tShotAlien
    if .Lin=0 then 'if not shooting there's 1/60 chance to shoot
      if rnd<(1/60) then
        Shoot( tShotAlien , AlienLin+1 , AlienCol+1 , ConMidLin,ConMidCol , 14 )
        ShieldHit= iif(.DiffLin<0,1,0) xor (iif(.DiffCol>0,3,0))
      end if
    else
      if (iTicks mod 4)=0 then
        MoveShot( tShotAlien )      
        'shot entered shield area?
        dim as single fDist = DistFromStation(.Lin,.Col)
        if StationHit=0 andalso fDist<10 then        
          if Shield(ShieldHit)=0 then 'Shield Shutdown... lose
            StationHit = 1            
          else 'Shield on. REFLECT
            const PI90 = atn(1)*2
            'add 1 buller every 10° of each reflected Quadrant
            if ShieldHit=0 or ShieldHit=2 then ShieldHit xor= 2
            for N as long = 0 to 8
              dim as double Ang = ShieldHit*PI90 + ((N+.5)*(PI90/9))            
              dim as long   DeLin = ConMidLin+sin(Ang)*9  ,   DeCol = ConMidCol-cos(Ang)*9
              dim as long ParaLin = ConMidLin+sin(Ang)*ConWid , ParaCol = ConMidCol-cos(Ang)*ConWid
              Shoot( tShotStation(N) , DeLin,DeCol , ParaLin,ParaCol , 11 )
            next N
            AlienHit=0 : KillShot(tShotAlien)
          end if          
        end if
        if StationHit andalso fDist<4 then
          color 12 : locate ConMidLin+6,ConMidCol-15 : print "Your Station has been Destroyed!";
          do
            var sKey = inkey
            if len(sKey) then
              select case sKey[0]
              case asc("Q"),asc("q"),asc("E"),asc("e"),asc("Z"),asc("z"),asc("C"),asc("c")
                rem ignore keys that might be pressed before this point
              case else : exit do
              end select
            end if
            color 9+rnd*6 : locate ConMidLin-2,ConMidCol-11 : PrintBig("Bang!")
            SyncFps()
          loop
          locate ConMidLin+6,ConMidCol-15 : print space(32);
          color 0 : locate ConMidLin-2,ConMidCol-11 : PrintBig("Bang!")
          ScoreAlien = ScoreAlien + 1 : StationHit = 0
          color 14 : locate ConHei,ConWid-10: print "Alien: ";ScoreAlien;
          DrawStation() : KillShot(tShotAlien)
        end if
      end if
    end if 
  end with
  'move our shots if enabled
  for N as long = 0 to 8
    with tShotStation(N)
      if .Lin <> 0 then
        MoveShot( tShotStation(N) )
        if AlienHit<>0 then continue for
        'check if shot hit alien
        if abs(.Lin-(AlienLin+1)) < 3 and abs(.Col-(AlienCol+1)) < 3 then          
          for N as long = 0 to 19
            locate AlienLin-1 , AlienCol-1
            Color 8+rnd*4 : PrintBig("*")          
            SyncFps()
          next N
          ScoreStation = ScoreStation + 1
          color 11 : locate ConHei,2        : print "You: " ;ScoreStation;
          locate AlienLin-1 , AlienCol-1 : PrintBig(" ")          
          KillShot( tShotStation(N) ) 
          AlienHit=1
        end if      
      end if
    end with
  next N
end sub
sub ProcessKeys()
  'process Keys
  static as byte Teclas(3) = { fb.SC_E , fb.SC_C , fb.SC_Z , fb.SC_Q }
  for N as long = 0 to 3
    Shield(N) = (iShield>0 andalso multikey(Teclas(N)))
    if Shield(N) then
      iShield -= 1 : iTickCharge = iTicks
      if iShield>(cMaxShield\3) orelse (iTicks mod 2) then color 10+N else color 1
    else 
      color 1
    end if    
    DrawShield(N)
  next N
  do
    var sKey = inkey
    if len(sKey)=0 then exit do
    select case sKey[0]
    case 27 : end
    end select
  loop    
  
end sub

Width ConWid,ConHei : locate ,,0
randomize()

InitStars()
InitAlien()
DrawStation()
IntroScreen()

color 11 : locate ConHei,2        : print "You: " ;ScoreStation;
color 14 : locate ConHei,ConWid-10: print "Alien: ";ScoreAlien;

do
  iTicks += 1
  
  DrawStars()
  DrawShieldBar()  
  DrawAlien()
  ProcessShooting()
  ProcessKeys()
  SyncFps()  

loop

linux users... to run this using console, you need to set your console to 80x50 (as seem freebasic width may not work with all terminals... and you need to set the console codepage to be IBM-850 or the classic US-437).