Author Topic: Black Art of 3D Game Programming: C to FB  (Read 6907 times)

0 Members and 1 Guest are viewing this topic.

Offline rdc

  • Pentium
  • *****
  • Posts: 1495
  • Karma: 140
  • Yes, it is me.
    • View Profile
    • Clark Productions
Here is chapter's 2 Light.c converted to FB. My additons/subtractions are marked with RDC. I have included the original comments for a reference point into the C source.

Code: [Select]
'Light.bas
'Example program from Chapter 2 of Black Art of 3D Game Programming by Andre LaMothe
'Converted from C to FreeBasic by Richard Clark
'I have included the C comments as a reference point for the C source.
'Copyright (c) 1995 The Waite Group
'==================================================================================
'// LIGHT.C - An example of real-time event loops

'// I N C L U D E S ////////////////////////////////////////////////////////////

'RDC: None needed

'// D E F I N E S /////////////////////////////////////////////////////////////

'// directions

#Define NORTH   0
#Define EAST    1
#Define SOUTH   2
#Define WEST    3

'Color const (not in C source)
Const fbWhite = Rgb(255, 255, 255)
Const fbBlue = Rgb(0, 0, 255)

'Key Const (Not in C source) used in inkey
Const xk = Chr(255)
Const key_right = xk + "M"
Const key_left = xk + "K"
Const key_close = xk + "k"
Const key_esc = Chr(27)
 


'// F U N C T I O N S /////////////////////////////////////////////////////////

Sub Delay(clicks As Integer)

'// this function uses the internal timer to delay a number of clock ticks

Dim dnow As Double

'// get current time

dnow = Timer

'// Wait for number of click to pass

Do
    Sleep 1 'Need to do this so system can run other tasks
Loop Until Timer > (dnow + clicks)

End Sub '// end Delay

'//////////////////////////////////////////////////////////////////////////////

Sub Draw_Game_Grid
'// This function draws a game grid out of horizontal and vertical lines

Dim As Integer x, y

'// the the line color to white
'Will set color in line statement (see below)

' RDC: I am going to use 640x480 in these examples with 32bit color.

'// draw the verical lines

ScreenLock
Cls
For x = 0 To 640 Step 20
   '// position the pen and draw the line
    Line (x, 0) - (x, 479), fbWhite
Next '// end for x
'// draw the horizontal lines

For y = 0 To 479 Step 20
   '/ position the pen and draw the line
    Line (0, y) - (639, y), fbWhite
Next '// end for y

'RDC: make a nice border around screen
Line (0, 0)-(639, 479), fbWhite, B 'B = make a Box

ScreenUnLock
End Sub 'Draw_Game_Grid

'// M A I N ////////////////////////////////////////////////////////////////////

Dim As Integer done = 0         '// main event loop exit flag
Dim As Integer player_x = 160   '// starting position and direction of player
Dim As Integer player_y = 150
Dim As Integer player_direction = NORTH
Dim As String ch 'RDC: use inkey for this since Multikey is too fast.

'// SECTION 1 //////////////////////////////////////////////////////////////////

'// set the graphics mode to (rdc: screen 18, 540x480, 32bit color)

Screen 18, 32

'//draw the game grid

Draw_Game_Grid

'// SECTION 2 //////////////////////////////////////////////////////////////////

'// begin real time event loop

Do
   
    '// SECTION 3 //////////////////////////////////////////////////////////////////

   '// is the player steering his light cycle or trying to exit?
   
    '// is the player steering his light cycle or trying to exit?
    ch = InKey
   
    '// test for Left, Right or Esc/Close
   
    If ch <> "" Then   
        '// turn 90 to the left
        If ch = key_left Then
            player_direction -= 1
            If player_direction < NORTH Then player_direction = WEST
        EndIf
   
    '// turn 90 To the right
    If ch = key_right Then
        player_direction += 1
        If player_direction > WEST Then player_direction = NORTH
    EndIf

    '// set exit flag to true
    If (ch = key_esc) Or (ch = key_close) Then
        done = 1
    EndIf

End If

'// SECTION 4 //////////////////////////////////////////////////////////////////

    '// at this point we need to move the light cycle in the direction its
   '// currently pointing
    Select Case player_direction
        Case NORTH
            player_y -= 1
            If player_y < 0 Then player_y = 479
      Case SOUTH
            player_y += 1
            If player_y > 479 Then player_y = 0
      Case EAST
            player_x += 1
            If player_x > 639 Then player_x = 0
      Case WEST
            player_x -= 1
            If player_x < 0 Then player_x = 639
   End Select '// end switch direction
   
'// SECTION 5 //////////////////////////////////////////////////////////////////

    '// render the lightcyle
    Pset (player_x, player_y), fbBlue

   '// wait a moment and lock the game to 18 fps

    Delay .18
   
Loop Until done = 1 '// End loop

'// end main

Offline rdc

  • Pentium
  • *****
  • Posts: 1495
  • Karma: 140
  • Yes, it is me.
    • View Profile
    • Clark Productions
Re: Black Art of 3D Game Programming: C to FB
« Reply #1 on: March 02, 2009 »
I have added a new section to my wiki on this and will post the Fb code there as well as here.

Offline Clyde

  • A Little Fuzzy Wuzzy
  • DBF Aficionado
  • ******
  • Posts: 7271
  • Karma: 71
    • View Profile
Re: Black Art of 3D Game Programming: C to FB
« Reply #2 on: March 03, 2009 »
Very cool mate and welldone.
K++
Still Putting The IT Into Gravy
If Only I Knew Then What I Know Now.

Challenge Trophies Won:

Offline rdc

  • Pentium
  • *****
  • Posts: 1495
  • Karma: 140
  • Yes, it is me.
    • View Profile
    • Clark Productions
Re: Black Art of 3D Game Programming: C to FB
« Reply #3 on: March 04, 2009 »
Thanks man. I'll have chap 3 done shortly. Since I am following the book, I needed to create a VGA palette. I had to search around for a list of colors and found one on Wikipedia as a graphic. I am not sure how accurate it is (colors can change in graphics), but it will do for the purpose of the conversion.

Offline Moroboshisan

  • Senior Member
  • Amiga 1200
  • ********
  • Posts: 454
  • Karma: 18
  • C=64
    • View Profile
Re: Black Art of 3D Game Programming: C to FB
« Reply #4 on: March 04, 2009 »
I needed to create a VGA palette. I had to search around for a list of colors and found one on Wikipedia as a graphic.

maybe there is something useful about palettes in Denthor's VGA trainers?

http://www.hornet.org/code/tutors/denthor/

or

http://lexoft.eu/asphyxia/

there is Pascal and C sources

Offline rdc

  • Pentium
  • *****
  • Posts: 1495
  • Karma: 140
  • Yes, it is me.
    • View Profile
    • Clark Productions
Re: Black Art of 3D Game Programming: C to FB
« Reply #5 on: March 04, 2009 »
Thanks, I'll check them out.

Offline rdc

  • Pentium
  • *****
  • Posts: 1495
  • Karma: 140
  • Yes, it is me.
    • View Profile
    • Clark Productions
Re: Black Art of 3D Game Programming: C to FB
« Reply #6 on: March 06, 2009 »
Here is Chap 3 code. I cut out all the palette switching switching stuff since I am working in 32bit mode, although I set up a fake vga palette in the code. (I thought someone might want to use it for an old skool demo.) The reason I am not using 256 color mode in FB is that when the book gets to making the 3D stuff 32bit mode will make the objects look better and the lighting will be much better as well. Just because this is old skool doesn't mean that we have to do everything the old way. :)

Here is the bi file, black3.bi:
Code: [Select]
'Black3.bi
'Library file from Chapter 3 of Black Art of 3D Game Programming by Andre LaMothe
'Converted from C to FreeBasic by Richard Clark
'I have included the C comments as a reference point for the C source.
'Copyright The Waite Group (c) 1995
'==================================================================================
'// I N C L U D E S ///////////////////////////////////////////////////////////

'RDC: None needed.

'// G L O B A L S //////////////////////////////////////////////////////////////
'RDC: We can skip the Mode 13h stuff. We don't need it. We are going to use Screen 18
'for all these programs, i.e. 640x480, 32bit colors. However, we will build a fake
'vga palette so as to implement the palette transformations. This is the base palette
'that we will use to restore the palette if we need to make changes to the working palette.
'RDC: This will be our working vga palette.
Dim Shared As Uinteger vga_palette(0 to 255) = {_
4278190080,4278190248,4278233088,4278233256,4289200128,4289200296,4289221632,4289243304,4283716692,_
4283716860,4283759700,4283759868,4294726740,4294726908,4294769748,4294769916,4278190080,4279505940,_
4280295456,4281084972,4281874488,4282664004,4283453520,4284506208,4285558896,4286611584,4287664272,_
4288716960,4290032820,4291348680,4292927712,4294769916,4278190332,4282384636,4286316796,4290511100,_
4294705404,4294705340,4294705276,4294705216,4294705152,4294721536,4294736896,4294753280,4294769664,_
4290575360,4286381056,4282448896,4278254592,4278254656,4278254716,4278254780,4278254844,4278238460,_
4278222076,4278206716,4286348540,4288445692,4290542844,4292639996,4294737148,4294737116,4294737084,_
4294737052,4294737020,4294745212,4294753404,4294761596,4294769788,4292672636,4290575484,4288478332,_
4286381180,4286381212,4286381244,4286381276,4286381308,4286373116,4286364924,4286356732,4290032892,_
4291081468,4292392188,4293440764,4294751484,4294751464,4294751448,4294751428,4294751412,4294755508,_
4294760628,4294764724,4294769844,4293459124,4292410548,4291099828,4290051252,4290051268,4290051288,_
4290051304,4290051324,4290046204,4290042108,4290036988,4278190192,4280025200,4281860208,4283695216,_
4285530224,4285530196,4285530168,4285530140,4285530112,4285537280,4285544448,4285551616,4285558784,_
4283723776,4281888768,4280053760,4278218752,4278218780,4278218808,4278218836,4278218864,4278211696,_
4278204528,4278197360,4281874544,4282660976,4283709552,4284495984,4285544560,4285544544,4285544532,_
4285544516,4285544504,4285547576,4285551672,4285554744,4285558840,4284510264,4283723832,4282675256,_
4281888824,4281888836,4281888852,4281888864,4281888880,4281884784,4281881712,4281877616,4283453552,_
4283977840,4284502128,4285026416,4285550704,4285550696,4285550688,4285550680,4285550672,4285552720,_
4285554768,4285556816,4285558864,4285034576,4284510288,4283986000,4283461712,4283461720,4283461728,_
4283461736,4283461744,4283459696,4283457648,4283455600,4278190144,4279238720,4280287296,4281335872,_
4282384448,4282384432,4282384416,4282384400,4282384384,4282388480,4282392576,4282396672,4282400768,_
4281352192,4280303616,4279255040,4278206464,4278206480,4278206496,4278206512,4278206528,4278202432,_
4278198336,4278194240,4280295488,4280819776,4281344064,4281868352,4282392640,4282392632,4282392624,_
4282392616,4282392608,4282394656,4282396704,4282398752,4282400800,4281876512,4281352224,4280827936,_
4280303648,4280303656,4280303664,4280303672,4280303680,4280301632,4280299584,4280297536,4281084992,_
4281347136,4281609280,4282133568,4282395712,4282395708,4282395700,4282395696,4282395692,4282396716,_
4282397740,4282399788,4282400812,4282138668,4281614380,4281352236,4281090092,4281090096,4281090100,_
4281090108,4281090112,4281089088,4281087040,4281086016,4278190080,4278190080,4278190080,4278190080,_
4278190080,4278190080,4278190080,4278190080}

'RDC: We will store the font sizes here. 

Dim Shared char_height As Integer = 16 'RDC: Using the default settings for screen 18.
Dim Shared char_width As Integer = 8

'// F U N C T I O N S /////////////////////////////////////////////////////////

'RDC: In the orirignal source this did a lookup into the ROM for the font and was
'used by Print_String to print characters. We really don't need this as we can just
'print a whole string using Draw String which is faster and easier. However, this may
'be used in the sources elsewhere so I will include it here. The var clr here (and following)
'refers to the vga_palette index which stores all of our colors.
Sub Print_Char (xc As Integer, yc As Integer, c As string, clr As Integer, transparent As Integer)
'// this function is used to print a character on the screen.
'RDC: We are just going to use Draw String for this since it is easier and faster. If the
'character is not transparent then we'll draw the background in black first.
If transparent = 0 Then
'Set background to black.
Line (xc, yc) - (xc + char_width, yc + char_height), vga_palette(0), BF 'Filled box.
'Draw the character.
Draw String (xc, yc), c, vga_palette(clr)
Else
'Just draw the chatacter on the screen.
Draw String (xc, yc), c, vga_palette(clr)
EndIf
End Sub '// end Print_Char

'//////////////////////////////////////////////////////////////////////////////

Sub Print_String(x As Integer, y As integer, clr As Integer, c As string, transparent As Integer)
Dim slen As Integer

'// this function prints an entire string on the screen with fixed spacing
'// between each character by calling the Print_Char() function
'RDC: We are going to just print the whole string here, rather than calling
'Print_Char since we don't need to do a character lookup like the original source.

'RDC: Get the length of the string. Not in original source, but we will need it
'to draw a background and for some error checking.
slen = Len(c)
'RDC: Nothing to print so exit.
If slen > 0 Then
'RDC:
If transparent = 0 Then
'Set background to black.
Line (x, y) - (((x + CHAR_WIDTH) * slen), y + CHAR_HEIGHT), vga_palette(0), BF 'Filled box.
'Draw the character.
Draw String (x, y), c, vga_palette(clr)
Else
'Just draw the chatacter on the screen.
Draw String (x, y), c, vga_palette(clr)
EndIf
End If
End Sub '// end Print_String

Sub Write_Pixel(x As Integer, y As integer, clr As Integer)
'// plots the pixel in the desired color a little quicker using binary shifting
'// to accomplish the multiplications
'// use the fact that 320*y = 256*y + 64*y = y<<8 + y<<6

'RDC: Just use Pset here.
PSet(x, y), vga_palette(clr)
End sub '// end Write_Pixel

'//////////////////////////////////////////////////////////////////////////////

Sub Set_Graphics_Mode
'// use the video interrupt 10h and the C interrupt function to set
'// the video mode
'RDC: We are just going to use screen 18, 32bit color.
Screen 18, 32 'We are only going to use 1 page here, since we can use Screenlock to write to screen.
End Sub '// end Set_Graphics_Mode

'/////////////////////////////////////////////////////////////////////////////

Sub Time_Delay(clicks As Integer)
'// this function uses the internal timer to wait a specified number of "clicks"
'// the actual amount of real time is the number of clicks * (time per click)
'// usually the time per click is set to 1/18th of a second or 55ms

Dim dnow As Double

'// get current time

dnow = Timer

'// Wait for number of click to pass

Do
    Sleep 1 'Need to do this so system can run other tasks
Loop Until Timer > (dnow + clicks)

End Sub

'////////////////////////////////////////////////////////////////////////////////

Sub Line_H(x1 As integer, x2 As integer, y As integer, clr As Integer)
'// draw a horizontal line using the memset function
'// this function does not do clipping hence x1,x2 and y must all be within
'// the bounds of the screen
'RDC: We can just use the FB's line function for this since it will be faster
'than anything we can code here.

'// sort x1 and x2, so that x2 > x1

if x1 > x2 Then
Swap x1, x2
   End if '// end swap
'// draw the row of pixels
Line (x1, y)-(x2, y), vga_palette(clr)
End sub '// end Line_H

'//////////////////////////////////////////////////////////////////////////////

Sub Line_V(y1 As integer, y2 As integer, x As integer, clr As Integer)
'// draw a vertical line, note that a memset function can no longer be
'// used since the pixel addresses are no longer contiguous in memory
'// note that the end points of the line must be on the screen
'RDC: Again we will just use FB's line method.

if y1 > y2 Then
Swap y1, y2
EndIf '// end swap
Line (x, y1)-(x, y2), vga_palette(clr)
End sub '// end Line_V

'//////////////////////////////////////////////////////////////////////////////
'RDC: For clr here we need an RGB color to put into the palette array, hence it is a UInteger.
Sub Write_Color_Reg(index As integer, clr As UInteger)
'// this function is used to write a color register with the RGB value
'// within "color"
'// tell vga card which color register to update
'RDC: We are just going to update our palette array here.

If (index >= 0) And (index <= UBound(vga_palette)) Then
vga_palette(index) = clr
EndIf

End sub '// end Write_Color_Reg

'///////////////////////////////////////////////////////////////////////////////

Function Read_Color_Reg(index As integer) As UInteger
'// this function reads the RGB triple out of a palette register and places it
'// into "color"
'RDC: We are just going to get out value from the vag_palette array.

If (index >= 0) And (index <= UBound(vga_palette)) Then
Return vga_palette(index)
Else
Return 0
EndIf

End function '// end Read_Color_Reg

'///////////////////////////////////////////////////////////////////////////////

Sub Read_Palette(start_reg As integer, end_reg As integer, the_palette() As UInteger)
'// this function will read the palette registers in the range start_reg to
'// end_reg and save them into the appropriate positions in the_palette

Dim index As integer '// used for looping

'// read all the registers
for index = start_reg to end_reg
    '// read the color register
    the_palette(index) = Read_Color_Reg(index)
   Next '// end for index
End sub '// end Read_Palette

'///////////////////////////////////////////////////////////////////////////////

Sub Write_Palette(start_reg As integer, end_reg As integer, the_palette() As UInteger)
'// this function will write to the color registers using the data in the
'// sen palette structure
'RDC: We are just updating the vga_palette array here.

Dim index As integer '// used for looping

'// write all the registers

for index = start_reg to end_reg
    '// write the color registers using the data from the sent palette

    Write_Color_Reg(index, the_palette(index))

    Next '// end for index

End sub '// end Write_Palette

'///////////////////////////////////////////////////////////////////////////////

Sub Draw_Rectangle(x1 As integer, y1 As integer, x2 As integer, y2 As integer, clr As integer)
'// this function will draw a rectangle from (x1,y1) - (x2,y2)
'// it is assumed that each endpoint is within the screen boundaries
'// and (x1,y1) is the upper left hand corner and (x2,y2) is the lower
'// right hand corner
'RDC: We are just going to use the box function of line here.
Line (x1, y1)-(x2, y2), vga_palette(clr), B
End sub '// end Draw_Rectangle

'////////////////////////////////////////////////////////////////////////////////

Sub Fill_Screen(clr As Integer)
'// this function will fill the entire screen with the sent color
'// use the inline assembler for speed
'RDC: We are just going to use CLS for this.
Color , vga_palette(clr)
Cls

End sub '// end Fill_Screen

'RDC: I am not including the ModeZ functions since they are the same as the Mode 13h functions.

Here is the main file, Mode18.bas:
Code: [Select]

'// MODE13.C - A demo of all the mode 13h functions for this chapter
'RDC: Mode18: sing screen 18 here, 640x480 rather than 320x200. Hence,
'I am calling this Mode18 rather than Mode13.

'// I N C L U D E S ///////////////////////////////////////////////////////////
#include "black3.bi" '/ the header file for this module

Dim index As Integer
Dim save_palette(0 To 255) As UInteger

Randomize Timer

'/ set the graphics mode to mode 13h
'RDC: Will be screen 18
Set_Graphics_Mode

'// show some text

Print_String 0, 0, 15, "Hit a key to see text printing...", 0
Sleep

'// print a few hundred strings on the screen

For index = 0  To 1000
Print_String Rnd * (639 - Len("This is a demo of text printing")), Rnd * 479, Rnd * 254, "This is a demo of text printing", 1
Next
Print_String 0, 0, 15, "Hit a key to see screen filling...", 0
Sleep

'// fill the screen dark grey

Fill_Screen 8
Print_String 0, 0, 15, "Hit a key to see pixel plotting...", 0
Sleep

'// plot 10000 random pixels

for index = 0 To 10000
    Write_Pixel Rnd * 639, Rnd * 479, 12
Next
Print_String 0, 0, 15, "Hit a key to see lines...", 0
Sleep

'// draw 1000 randomly positioned horizontal and vertical lines

for index = 0 To 1000
    Line_H Rnd * 639, Rnd * 639, Rnd * 479, Rnd * 254
    Line_V Rnd * 479, Rnd * 479, Rnd * 639, Rnd * 254
Next '// end for index

Print_String 0, 0, 15, "Hit a key to end program...", 0
Sleep

'Since we are doing this in 32bit color mode, we can't do palette shifts
'so they won't be in ths program. However, in FB 256 color mode, you can shift
'palettes much like you could in the old VGA cards.

If you compare the C source to the FB source, you can see that we don't have to jump through all those hoops that they had to back in the day. Really, the bi file is just wrapping the built-in FB graphics functions. I think in future installments, I will just inline the graphics functions in the main code as it really makes no sense to wrap all these functions like this.

Offline rdc

  • Pentium
  • *****
  • Posts: 1495
  • Karma: 140
  • Yes, it is me.
    • View Profile
    • Clark Productions
Re: Black Art of 3D Game Programming: C to FB
« Reply #7 on: March 17, 2009 »
I finished my 7DRL Challenge entry Escape From Lab 42 successfully, so I will get back to this. Chapter 4 talks about 2D game animation, and I think this would be a good point to introduce some of the OOP features of FreeBasic. Even though FB has limited OOP support (no inheritance for example), it has enough meat to it to provide a good data model for animation. It will also make working with 3D much more simple as well, so building the foundation now will pay off when we get to the main course. :)

Online Shockwave

  • good/evil
  • Founder Member
  • DBF Aficionado
  • ********
  • Posts: 17414
  • Karma: 498
  • evil/good
    • View Profile
    • My Homepage
Re: Black Art of 3D Game Programming: C to FB
« Reply #8 on: March 18, 2009 »
Thanks for the hard work you are putting into this Rick :)

K+
Shockwave ^ Codigos
Challenge Trophies Won:

Offline rdc

  • Pentium
  • *****
  • Posts: 1495
  • Karma: 140
  • Yes, it is me.
    • View Profile
    • Clark Productions
Re: Black Art of 3D Game Programming: C to FB
« Reply #9 on: March 19, 2009 »
No problem. I am hoping it will help me do some decent demos. :)

Online Shockwave

  • good/evil
  • Founder Member
  • DBF Aficionado
  • ********
  • Posts: 17414
  • Karma: 498
  • evil/good
    • View Profile
    • My Homepage
Re: Black Art of 3D Game Programming: C to FB
« Reply #10 on: March 19, 2009 »
The chaldni demos were much better than just decent, you are too modest :)
Shockwave ^ Codigos
Challenge Trophies Won:

Offline rdc

  • Pentium
  • *****
  • Posts: 1495
  • Karma: 140
  • Yes, it is me.
    • View Profile
    • Clark Productions
Re: Black Art of 3D Game Programming: C to FB
« Reply #11 on: March 19, 2009 »
Heh. Thanks man.

I really want to redo The Last Mission in 3D. I liked that demo a lot and I think it would be very cool to have a 3D version of that with some cool camera pans and such. My skills just aren't there-yet. :)

Offline rdc

  • Pentium
  • *****
  • Posts: 1495
  • Karma: 140
  • Yes, it is me.
    • View Profile
    • Clark Productions
Re: Black Art of 3D Game Programming: C to FB
« Reply #12 on: April 20, 2009 »
I just wanted to let you all know that I am still working on this. I have been on vacation, and we had our 2 year old grandson visiting us for a week. It was a joy having him, even though it made me realized just how old I am. :)

Offline rdc

  • Pentium
  • *****
  • Posts: 1495
  • Karma: 140
  • Yes, it is me.
    • View Profile
    • Clark Productions
Re: Black Art of 3D Game Programming: C to FB
« Reply #13 on: June 17, 2009 »
Just to let you all know, I haven't been able to get past the problem of loading the objects that are used in these programs. Very strange format and the book and code is a bit confusing on this point. I have put it aside for the moment and come back to it with fresh eyes.