Using LibTcod (Example)

Post your FreeBASIC source, examples, tips and tricks here. Please don’t post code without including an explanation.
TJF
Posts: 3809
Joined: Dec 06, 2009 22:27
Location: N47°, E15°
Contact:

Using LibTcod (Example)

Post by TJF »

Image

LibTcod is a library for developing 'roguelike' games. A header and further information is available here.

Now I partially translated this tutorial from Python to FB to test the header. The result is a little app that shows two rooms, connected with a tunnel. One player (blue) can move in this dungeon, another is standing at one place.

Here's the source code

Code: Select all

#LIBPATH "libtcod-1.5.1"
#INCLUDE "libtcod.bi"

DIM SHARED AS TCOD_console_t con

TYPE Tile
  DECLARE CONSTRUCTOR(BYVAL Vb AS INTEGER, BYVAL Vs AS INTEGER)
  AS INTEGER Block, Block_Sight
END TYPE

CONSTRUCTOR Tile(BYVAL Vb AS INTEGER, BYVAL Vs AS INTEGER)
  Block = Vb
  Block_Sight = Vs
END CONSTRUCTOR

STATIC SHARED AS INTEGER MAP_WIDTH = 80, MAP_HEIGHT = 45
DIM SHARED AS Tile PTR map(MAP_WIDTH, MAP_HEIGHT)


SUB Rect(byval X AS INTEGER, BYVAL Y AS INTEGER, BYVAL W AS INTEGER, BYVAL H AS INTEGER)
  FOR c AS INTEGER = X + 1 TO X + W
    FOR r AS INTEGER = Y + 1 TO Y + H
      map(c, r)->Block = FALSE
      map(c, r)->Block_Sight = FALSE
    NEXT
  NEXT
END SUB

TYPE Objct
  DECLARE CONSTRUCTOR(BYVAL x AS INTEGER, BYVAL y AS INTEGER, BYVAL char AS INTEGER, BYVAL col AS TCOD_color_t)
  DECLARE SUB move(BYVAL dx AS INTEGER, BYVAL dy AS INTEGER)
  DECLARE SUB draw()
  DECLARE SUB clear()
  AS INTEGER X, Y, Char
  AS TCOD_color_t Col
END TYPE

CONSTRUCTOR Objct(BYVAL Vx AS INTEGER, BYVAL Vy AS INTEGER, BYVAL Vc AS INTEGER, BYVAL Cv AS TCOD_color_t)
  X = Vx
  Y = Vy
  Char = Vc
  Col = Cv
END CONSTRUCTOR

SUB Objct.move(BYVAL dx AS INTEGER, BYVAL dy AS INTEGER)
  IF map(X + dx, Y + dy)->Block THEN EXIT SUB
  X += dx
  Y += dy
END SUB

SUB Objct.draw(BYVAL )
  TCOD_console_set_foreground_color(con, Col)
  TCOD_console_put_char(con, X, Y, Char, TCOD_BKGND_NONE)
END SUB

SUB Objct.clear()
  TCOD_console_put_char(con, X, Y, ASC(" "), TCOD_BKGND_NONE)
END SUB

DIM SHARED AS Objct PTR obj(1)
CONST SCREEN_WIDTH = 80, SCREEN_HEIGHT = 50, LIMIT_FPS = 20
STATIC SHARED AS TCOD_color_t color_dark_wall, color_dark_ground



FUNCTION handle_keys() AS bool
  VAR key = TCOD_console_check_for_keypress(TRUE) ' real-time
  'VAR key = TCOD_console_wait_for_keypress(FALSE) '  turn-based
  SELECT CASE AS CONST key.vk
  CASE TCODK_ENTER : IF key.lalt THEN _
    TCOD_console_set_fullscreen(IIF(TCOD_console_is_fullscreen(), FALSE, TRUE))
  CASE TCODK_ESCAPE : RETURN TRUE
  END SELECT

  IF TCOD_console_is_key_pressed(TCODK_UP) THEN
    obj(0)->move(0, -1)
  ELSEIF TCOD_console_is_key_pressed(TCODK_DOWN) THEN
    obj(0)->move(0, 1)
  ELSEIF TCOD_console_is_key_pressed(TCODK_LEFT) THEN
    obj(0)->move(-1, 0)
  ELSEIF TCOD_console_is_key_pressed(TCODK_RIGHT) THEN
    obj(0)->move(1, 0)
  END IF : RETURN FALSE
END FUNCTION

SUB make_map()
  FOR y AS INTEGER = 0 TO MAP_HEIGHT
    FOR x AS INTEGER = 0 TO MAP_WIDTH
      map(x, y) = NEW Tile(TRUE, TRUE)
    NEXT
  NEXT
  Rect(20, 15, 10, 15) ' romm 1
  Rect(50, 12, 15, 25) ' romm 2
  Rect(30, 25, 20, 1)  ' tunnel
END SUB

SUB render_all()
  '#go through all tiles, and set their background color
  FOR y AS INTEGER = 0 TO MAP_HEIGHT
    FOR x AS INTEGER = 0 TO MAP_WIDTH
      IF map(x, y)->Block_Sight THEN
        TCOD_console_set_back(con, x, y, color_dark_wall, TCOD_BKGND_SET)
      ELSE
        TCOD_console_set_back(con, x, y, color_dark_ground, TCOD_BKGND_SET)
      END IF
    NEXT
  NEXT

  FOR i AS INTEGER = 0 TO UBOUND(obj)
    obj(i)->draw()
  NEXT

  TCOD_console_blit(con, 0, 0, SCREEN_WIDTH - 1, SCREEN_HEIGHT - 1, 0, 0, 0, 1.0, 1.0)
END SUB

TCOD_console_set_custom_font("libtcod-1.5.1/data/fonts/arial10x10.png", _
                             TCOD_FONT_TYPE_GREYSCALE OR TCOD_FONT_LAYOUT_TCOD, FALSE, FALSE)
TCOD_console_init_root(SCREEN_WIDTH + 1, SCREEN_HEIGHT + 1, "Rogue", FALSE, TCOD_RENDERER_SDL)
TCOD_sys_set_fps(LIMIT_FPS)
con = TCOD_console_new(SCREEN_WIDTH + 1, SCREEN_HEIGHT + 1)
color_dark_wall = TCOD_color_RGB(0, 0, 100)
color_dark_ground = TCOD_color_RGB(50, 50, 150)

obj(0) = NEW Objct(25, 23, ASC("@"), TCOD_white)
obj(1) = NEW Objct(SCREEN_WIDTH/2 - 5, SCREEN_HEIGHT/2, ASC("@"), TCOD_yellow)

make_map()

WHILE 0 = TCOD_console_is_window_closed()
  render_all()
  TCOD_console_flush()
  FOR i AS INTEGER = 0 TO UBOUND(obj)
    obj(i)->clear()
  NEXT
  IF handle_keys() THEN EXIT WHILE
WEND


' delete UDTs
FOR i AS INTEGER = 0 TO UBOUND(obj)
  DELETE obj(i)
NEXT
FOR y AS INTEGER = 0 TO MAP_HEIGHT
  FOR x AS INTEGER = 0 TO MAP_WIDTH
    DELETE map(x, y)
  NEXT
NEXT
Find further information and updates at the original example page
[edit]-> Header updated now!
Note:
I found a bug in the header libtcod.bi. Edit line 138 to

Code: Select all

#DEFINE true CAST(bool, 1)
[/edit]
Last edited by TJF on Sep 19, 2012 9:21, edited 1 time in total.
TJF
Posts: 3809
Joined: Dec 06, 2009 22:27
Location: N47°, E15°
Contact:

Re: Using LibTcod (Example)

Post by TJF »

Image

Here's a further example, some more movements at the screen (player and 10 ghosts) and a bit more FB-styled syntax:

Code: Select all

'#DEFINE __TCOD_OLD_1_5_1__ ' try to uncomment if you get error 'undefined reference to ...'

#LIBPATH "libtcod-1.5.1"
#INCLUDE ONCE "libtcod.bi"

TYPE Tile
  AS INTEGER Block = TRUE, Block_Sight = TRUE
END TYPE

DIM SHARED AS TCOD_console_t con
CONST AS INTEGER MAP_WIDTH = 60, MAP_HEIGHT = 35
DIM SHARED AS Tile map(MAP_WIDTH, MAP_HEIGHT)
CONST SCREEN_WIDTH = MAP_WIDTH, SCREEN_HEIGHT = MAP_HEIGHT + 3, LIMIT_FPS = 20
STATIC SHARED AS TCOD_color_t color_dark_wall, color_dark_ground

SUB Rect(byval X AS INTEGER, BYVAL Y AS INTEGER, BYVAL W AS INTEGER, BYVAL H AS INTEGER)
  FOR c AS INTEGER = X + 1 TO X + W
    FOR r AS INTEGER = Y + 1 TO Y + H
      map(c, r).Block = FALSE
      map(c, r).Block_Sight = FALSE
    NEXT
  NEXT
END SUB

TYPE Objct
  DECLARE CONSTRUCTOR(BYVAL Vx AS INTEGER, BYVAL Vy AS INTEGER, BYVAL Vc AS INTEGER, BYVAL Cv AS TCOD_color_t)
  DECLARE SUB move(BYVAL dx AS INTEGER, BYVAL dy AS INTEGER)
  DECLARE SUB draw()
  DECLARE SUB clear()
  AS INTEGER X, Y, Char, Count = RND() * 2 * LIMIT_FPS
  AS TCOD_color_t Col
END TYPE

CONSTRUCTOR Objct(BYVAL Vx AS INTEGER, BYVAL Vy AS INTEGER, BYVAL Vc AS INTEGER, BYVAL Cv AS TCOD_color_t)
  X = Vx
  Y = Vy
  Char = Vc
  Col = Cv
END CONSTRUCTOR

SUB Objct.move(BYVAL dx AS INTEGER, BYVAL dy AS INTEGER)
  IF map(X + dx, Y + dy).Block THEN BEEP : EXIT SUB
  map(X, Y).Block = FALSE
  X += dx
  Y += dy
  map(X, Y).Block = TRUE
END SUB

SUB Objct.draw(BYVAL )
  TCOD_console_set_default_foreground(con, Col)
  TCOD_console_put_char(con, X, Y, Char, TCOD_BKGND_NONE)
END SUB

SUB Objct.clear()
  TCOD_console_put_char(con, X, Y, ASC(" "), TCOD_BKGND_NONE)
END SUB

' some objects to move
DIM SHARED AS Objct obj(10) => { _
    TYPE<Objct>(11, 23, ASC("@"), TCOD_silver) _
  , TYPE<Objct>(12, 21, ASC("1"), TCOD_yellow) _
  , TYPE<Objct>(13, 21, ASC("2"), TCOD_red) _
  , TYPE<Objct>(14, 21, ASC("3"), TCOD_blue) _
  , TYPE<Objct>(15, 21, ASC("4"), TCOD_red) _
  , TYPE<Objct>(35, 21, ASC("5"), TCOD_yellow) _
  , TYPE<Objct>(36, 21, ASC("6"), TCOD_red) _
  , TYPE<Objct>(37, 21, ASC("7"), TCOD_yellow) _
  , TYPE<Objct>(38, 21, ASC("8"), TCOD_red) _
  , TYPE<Objct>(39, 21, ASC("9"), TCOD_yellow) _
  , TYPE<Objct>(40, 21, ASC("0"), TCOD_gold) _
  }


SUB make_map()
  ' rooms and tunnel
  Rect(             3,  8, MAP_WIDTH - 38, MAP_HEIGHT - 12) ' room 1
  Rect(MAP_WIDTH - 30,  4, MAP_WIDTH - 34, MAP_HEIGHT - 7) ' room 2
  Rect(MAP_WIDTH - 35, 25,              5, 1)  ' tunnel

  ' the objects (can move)
  FOR i AS INTEGER = 0 TO UBOUND(obj)
    map(obj(i).X, obj(i).Y).Block = TRUE
  NEXT

  '#go through all tiles, and set their background color
  FOR y AS INTEGER = 0 TO MAP_HEIGHT
    FOR x AS INTEGER = 0 TO MAP_WIDTH
      IF map(x, y).Block_Sight THEN
        TCOD_console_set_char_background(con, x, y, color_dark_wall, TCOD_BKGND_SET)
      ELSE
        TCOD_console_set_char_background(con, x, y, color_dark_ground, TCOD_BKGND_SET)
      END IF
    NEXT
  NEXT
END SUB


FUNCTION handle_keys() AS bool
  VAR key = TCOD_console_check_for_keypress(TRUE) ' real-time
  'VAR key = TCOD_console_wait_for_keypress(FALSE) '  turn-based
  SELECT CASE AS CONST key.vk
  CASE TCODK_ENTER : IF key.lalt THEN _
    TCOD_console_set_fullscreen(IIF(TCOD_console_is_fullscreen(), FALSE, TRUE))
  CASE TCODK_ESCAPE : RETURN TRUE
  END SELECT

  IF TCOD_console_is_key_pressed(TCODK_UP) THEN
    obj(0).move(0, -1)
  ELSEIF TCOD_console_is_key_pressed(TCODK_DOWN) THEN
    obj(0).move(0, 1)
  ELSEIF TCOD_console_is_key_pressed(TCODK_LEFT) THEN
    obj(0).move(-1, 0)
  ELSEIF TCOD_console_is_key_pressed(TCODK_RIGHT) THEN
    obj(0).move(1, 0)
  END IF : RETURN FALSE
END FUNCTION

SUB render_all()
  FOR i AS INTEGER = 0 TO UBOUND(obj)
    obj(i).draw()
  NEXT

  TCOD_console_blit(con, 0, 0, SCREEN_WIDTH, SCREEN_HEIGHT, 0, 0, 0, 1.0, 1.0)
END SUB

SUB move_ghosts()
  VAR i = 0
  FOR i = 1 TO UBOUND(obj) - 1
    obj(i).Count -= 1
    IF obj(i).Count <= 0 THEN
      obj(i).Count = CUINT(LIMIT_FPS * (1 + RND()))
      obj(i).move(CINT(RND() * 2 - 1), CINT(RND() * 2 - 1))
    END IF
  NEXT
  obj(i).Count -= 1
  IF obj(i).Count <= 0 THEN
    obj(i).Count = CUINT(LIMIT_FPS * (1 + RND()))
    VAR dx = SGN(obj(0).X - obj(i).X)
    VAR dy = SGN(obj(0).Y - obj(i).Y)
    obj(i).move(dx, dy)
  END IF
END SUB


' ***** main *****

TCOD_console_set_custom_font("libtcod-1.5.1/data/fonts/arial12x12.png", _
                             TCOD_FONT_TYPE_GREYSCALE OR TCOD_FONT_LAYOUT_TCOD, FALSE, FALSE)
TCOD_console_init_root(SCREEN_WIDTH, SCREEN_HEIGHT, "Rogue2", FALSE, TCOD_RENDERER_SDL)
TCOD_sys_set_fps(LIMIT_FPS)
con = TCOD_console_new(SCREEN_WIDTH, SCREEN_HEIGHT)
color_dark_wall = TCOD_color_RGB(0, 0, 100)
color_dark_ground = TCOD_color_RGB(50, 50, 150)

make_map()

RANDOMIZE
VAR c = 2 * LIMIT_FPS
WHILE 0 = TCOD_console_is_window_closed()
  render_all()
  TCOD_console_flush()
  FOR i AS INTEGER = 0 TO UBOUND(obj)
    obj(i).clear()
  NEXT
  move_ghosts()
  IF handle_keys() THEN EXIT WHILE
WEND
Edit:
source updated, image included.
Last edited by TJF on Sep 19, 2012 9:17, edited 1 time in total.
Jocke The Beast
Posts: 272
Joined: May 28, 2005 10:21
Contact:

Re: Using LibTcod (Example)

Post by Jocke The Beast »

Thanks for doing this great example and everything.

But...could you explain, like if you talked to a child almost, how to set up the lib and header-file for playing around with this. Only if you got a spare minute or two since my skills are down at zero when it comes to libs etc. right now.

Cheers for doing this!!!!
TJF
Posts: 3809
Joined: Dec 06, 2009 22:27
Location: N47°, E15°
Contact:

Re: Using LibTcod (Example)

Post by TJF »

Jocke The Beast wrote:But...could you explain, like if you talked to a child almost, how to set up the lib and header-file for playing around with this.
In the past I tested on Ubuntu 12.04. Do you like me to explain this configuration?

Today I made a first test on wondiws and I found a fancy problem. They changed the API. These changes are not in the sources I downlowded some weeks ago, but they're in the binaries I downloaded today (both are version 1.5.1).

As a workaround I prepended this code (before #INCLUDE "libtcod.bi")

Code: Select all

#IFDEF __FB_WIN32__
 #DEFINE TCOD_console_set_foreground_color TCOD_console_set_default_foreground
 #DEFINE TCOD_console_set_background_color TCOD_console_set_default_background
 #DEFINE TCOD_console_get_background_color TCOD_console_get_default_background
 #DEFINE TCOD_console_get_foreground_color TCOD_console_get_default_foreground
 #DEFINE TCOD_console_set_back TCOD_console_set_char_background
 #DEFINE TCOD_console_set_fore TCOD_console_set_char_foreground
 #DEFINE TCOD_console_get_back TCOD_console_get_char_background
 #DEFINE TCOD_console_get_fore TCOD_console_get_char_foreground
#ENDIF

' and the original code ...
#LIBPATH "libtcod-1.5.1"
#INCLUDE ONCE "libtcod.bi"

TYPE Tile
...
I'm not sure how to handle this in the header. Let me think about it a little bit ...

If this doesn't fix your problems and you want further support then I need a detailed report on the trouble you're facing (OS, fbc version, error messages, changes in source code, ...).
Jonge
Posts: 130
Joined: Jul 17, 2012 17:51
Location: Norway
Contact:

Re: Using LibTcod (Example)

Post by Jonge »

I'm having some trouble compiling your examples on windows using FB 0.24.
I'm getting an error saying 'bool' is not a defined variable. Though to me it looks like its defined as uint8, which is defined as ubyte. The change in line 138 seems to me to be inside a define for c++ ?

I think Jocke is asking for step by step instructions to getting a running example on windows(including what to download and where to put the needed files)
TJF
Posts: 3809
Joined: Dec 06, 2009 22:27
Location: N47°, E15°
Contact:

Re: Using LibTcod (Example)

Post by TJF »

Jonge wrote:I think Jocke is asking for step by step instructions to getting a running example on windows(including what to download and where to put the needed files)
Yes, may be. I can't test on wndoiws at my office. I do the testing on the box of a friend and I have to prepare my USB stick before I start. That's why I need a good bug report first.
Jonge wrote:I'm getting an error saying 'bool' is not a defined variable. Though to me it looks like its defined as uint8, which is defined as ubyte. The change in line 138 seems to me to be inside a define for c++ ?
'#IFNDEF __cplusplus

Yes, you're right: bool should be uint8 (= UBYTE), so it's a UDT (= user defined type -- no variable).

Please send me the complete text of the error message or better the complete output of your compiler run (ATM I need the file name and line # where the error occurs to learn more about your trouble).
Jonge
Posts: 130
Joined: Jul 17, 2012 17:51
Location: Norway
Contact:

Re: Using LibTcod (Example)

Post by Jonge »

If I remeber correct, line 138 in the header file was:

Code: Select all

#IFNDEF __cplusplus
..
#ELSE
..
#ENDIF     <----- This line
I'm at work so cant check it out now. Could be something happend when converting the header file to have Windows type line endings. Thanks for your work =)

EDIT:
I think I know what I did wrong.
The two line after #IFNDEF __cplusplus

#DEFINE false ((bool) 0)
#DEFINE true ((bool) 1)

Should be ->

#DEFINE false CAST(bool, 0)
#DEFINE true CAST(bool, 1)

Will test it when I get home. The above lines are taken from my memory(they might be corrupt =) )
TJF
Posts: 3809
Joined: Dec 06, 2009 22:27
Location: N47°, E15°
Contact:

News:

Post by TJF »

header update
  • new name: libtcod.bi
  • bugfix: #DEFINE true
  • extension: symbol __TCOD_OLD_1_5_1__ for API changes
  • clean up
New download
  • example project including all needed files (source, header, binaries -- widnows only)
Jonge
Posts: 130
Joined: Jul 17, 2012 17:51
Location: Norway
Contact:

Re: Using LibTcod (Example)

Post by Jonge »

Nize =)
Jocke The Beast
Posts: 272
Joined: May 28, 2005 10:21
Contact:

Re: Using LibTcod (Example)

Post by Jocke The Beast »

We love you man :)
Will try when I get home from work.
Thanks man
Jocke The Beast
Posts: 272
Joined: May 28, 2005 10:21
Contact:

Re: Using LibTcod (Example)

Post by Jocke The Beast »

There it is!
Working.
Amazing.

Thanks again for taking time to help us out.
Will sit down and toy around now. :)
TJF
Posts: 3809
Joined: Dec 06, 2009 22:27
Location: N47°, E15°
Contact:

Re: Using LibTcod (Example)

Post by TJF »

Thanks for feedback and good luck for your projects.
Ryan
Posts: 695
Joined: Jun 10, 2005 2:13
Location: Louisville, KY
Contact:

Re: Using LibTcod (Example)

Post by Ryan »

Quick post to say I was also able to get the updated header and example and compile it. Woohoo! : )
TJF
Posts: 3809
Joined: Dec 06, 2009 22:27
Location: N47°, E15°
Contact:

Re: Using LibTcod (Example)

Post by TJF »

Thanks for feedback!

Good luck for your project.
Jocke The Beast
Posts: 272
Joined: May 28, 2005 10:21
Contact:

Re: Using LibTcod (Example)

Post by Jocke The Beast »

Ryan wrote:Quick post to say I was also able to get the updated header and example and compile it. Woohoo! : )
Same here Ryan!
Awesome!

Now let's begin to make something roguelike-ish with it :)
Keep me posted about your progress since I suck at programming right now ;)
Cheers!
Post Reply