Viewport to scroll

Previous topic - Next topic

teoM

Hello everybody.
Simple question (just started to use glbasic).
Is it ok to use viewport to scroll large playfields (that i previously filled with tiles) or do i have to write a tile scroller?(seems quite complicated to me, read few tutorials and didnt understand at all  O_O ).
Thanks

MrTAToad

You should scroll the tile really, as VIEWPORTs are defining viewing areas within the screen width and height.

matchy

If you have previously filled something with tiles/field, it should be on a sprite via USESCREEN, so then polyvector would just grab the viewing area.

I don't recommend this as playing fields would be small compared to directly scrolling the tiles. For example, 1024x1024 / 32x32 = 32x32.

Welcome and the best way we can help is if you post code!

teoM

Thanks everybody.
Since i am learning i was just curious about the difference between the 2, so i dont waste time focusing on one or the other.
So the concept is (example) to have a playing area of 640*480 that stays static, and have tiles scrolling into it.
Just one thing seems difficult to me, and thats writing down the code that store each tile position.
I will probably have to use arrays and types for that, which is fine, but that means that something as to be bigger than the playing area.
Example:
tiles are 64*64
if i want a playing area of 640*1280 means the screen is 2 times the vertical size, so i will go out of vertical boundaries
Does that means that things aren't cropped even if i go beyond my screen size?So i just have to store each tile position and thats it?
Sorry for not having any code but its just pseudo-code at the moment, so i can learn the concept.
As for the scrolling....i guess i have to update every single tile position to achieve that, is it correct?
Seems a lot of processing power to me (if its how its done).
Also what about the tiles that are out of the boundaries of my screen, and are still moving?Do they take up resources?
Sorry for the simple questions, but it seems i miss the concept!
Thanks

matchy

#4
This would be a good topic for a friendly and creative coding challenge or competition. :)

Here is the most simplest and quickest way I can produce a scrolling tile based field to demonstrate the simple questioned concept.

Code (glbasic) Select

// --------------------------------- //
// Project: tile_example
// Start: Thursday, July 14, 2011
// IDE Version: 9.104


TYPE _rect
x; y; width; height
ENDTYPE

GLOBAL screen AS _rect, boundary AS _rect, tile AS _rect, player AS _rect, tile_map$[]

main()

FUNCTION main:
init()
animate_scene()
ENDFUNCTION

FUNCTION init:
screen.width = 640
screen.height = 480
SETSCREEN screen.width, screen.height, FALSE

tile.width = 64
tile.height = 64

boundary.x = -tile.width
boundary.width = screen.width + tile.width
boundary.y = -tile.height
boundary.height = screen.height + tile.height

tile.y = INTEGER(screen.height * 4 / tile.height)

// Generate an ASCII maze quickly: http://www.vidarholen.net/cgi-bin/labyrinth?w=9&h=31

DIM tile_map$[tile.y + 1]

tile_map$[0] = "???????????????"
tile_map$[1] = "???????????????"
tile_map$[2] = "? ? ? ??? ??? ?"
tile_map$[3] = "? ??? ? ????? ?"
tile_map$[4] = "??? ????? ??? ?"
tile_map$[5] = "? ? ? ??? ?????"
tile_map$[6] = "? ? ? ? ??? ? ?"
tile_map$[7] = "? ? ????????? ?"
tile_map$[8] = "? ??? ? ????? ?"
tile_map$[9] = "??? ? ??? ?????"
tile_map$[10] = "? ????? ? ? ? ?"
tile_map$[11] = "? ? ? ? ????? ?"
tile_map$[12] = "? ? ? ? ? ??? ?"
tile_map$[13] = "? ? ? ? ? ? ? ?"
tile_map$[14] = "? ? ????? ? ? ?"
tile_map$[15] = "? ????? ???????"
tile_map$[16] = "??? ? ??? ??? ?"
tile_map$[17] = "? ? ? ? ? ? ???"
tile_map$[18] = "? ? ? ??????? ?"
tile_map$[19] = "? ????? ????? ?"
tile_map$[20] = "? ? ? ??? ?????"
tile_map$[21] = "? ? ??? ????? ?"
tile_map$[22] = "? ? ? ????? ? ?"
tile_map$[23] = "? ????? ? ? ? ?"
tile_map$[24] = "????? ? ? ? ???"
tile_map$[25] = "? ??????????? ?"
tile_map$[26] = "? ? ? ? ????? ?"
tile_map$[27] = "? ? ??????? ? ?"
tile_map$[28] = "? ??????? ??? ?"
tile_map$[29] = "???????????????"

tile.x = LEN(tile_map$[0])
ENDFUNCTION

FUNCTION animate_scene:
WHILE TRUE
update_player()
draw_field()
SHOWSCREEN
WEND
ENDFUNCTION

FUNCTION update_player:
LOCAL step_move = 4

IF KEY(200) THEN INC player.y, step_move // up
IF KEY(203) THEN INC player.x, step_move // left
IF KEY(205) THEN DEC player.x, step_move // right
IF KEY(208) THEN DEC player.y, step_move // down
ENDFUNCTION

FUNCTION draw_field:
LOCAL map AS _rect

FOR map.y = 0 TO tile.y - 1
FOR map.x = 0 TO tile.x - 1
draw_tile(map.x, map.y)
NEXT
NEXT
ENDFUNCTION

FUNCTION draw_tile: map_x, map_y
LOCAL box AS _rect, color, ascii, line$

box.x = (map_x * tile.width) + player.x
box.y = (map_y * tile.height) + player.y
IF BOXCOLL(box.x, box.y, box.width, box.height, boundary.x, boundary.y, boundary.width, boundary.height)
line$ = tile_map$[map_y]
ascii = ASC(MID$(line$, map_x, 1))
SELECT ascii
CASE 32
color = RGB(0, 128, 0)
DEFAULT
IF map_x = 0 OR map_y = 0 OR map_x = tile.x - 1 OR map_y = tile.y - 1
color = RGB(0, 0, 64 * SIN(GETTIMERALL() / 10) + 64) // outer wall
ELSE
color = RGB(0, 0, 32) // inner wall
ENDIF
ENDSELECT
DRAWRECT box.x, box.y, tile.width - 1, tile.height - 1, color // DRAWSPRITE tiles here
ENDIF
ENDFUNCTION


Kitty Hello

easy to understand. But! I'd calculate xfrom, xto and yfrom,yto variables for the x,y loop that are in the visible range (no need for boxcoll of every tile).
Also, I'd put the tiles in an integer array instead of ASC for each tile/frame.

Great tutorial!

teoM

Wow lots of advanced stuff here!
I will try to analise it bit by bit and try to understand what every line does.
Until the line
QuoteGLOBAL screen AS _rect, boundary AS _rect, tile AS _rect, player AS _rect, tile_map$[]
everything is easy, you basically create a type and make few instances of it, and declare them globals.
The function "init()" has few bits that i dont understand.
Those lines
QuoteFUNCTION init:
   screen.width = 640
   screen.height = 480
   SETSCREEN screen.width, screen.height, FALSE

   tile.width = 64
   tile.height = 64

   boundary.x = -tile.width
   boundary.width = screen.width + tile.width
   boundary.y = -tile.height
   boundary.height = screen.height + tile.height
are used to set the tile size, the starting points of the playfield and the end points (if i am right..).
This line
Quotetile.y = INTEGER(screen.height * 4 / tile.height)
is a mystery..i actually can't understand what "tile.y" is used for!
It returns 30 as a result...is it maybe the total number of tiles on the x axis?

teoM

Sorry i meant on the y axis  :nw:

teoM

Also, i dont know if it was a mistype or no, in this line
Quote// Generate an ASCII maze quickly: http://www.vidarholen.net/cgi-bin/labyrinth?w=9&h=31
it says width=9 .... height=31
but
Quotetile.x = LEN(tile_map$[0])
should give a result of 15, not 9.
Am i wrong?

teoM

Ok i think i understood how it works.
I rewrite your code with comments to show if i made some mistakes in the understanding!
Code (glbasic) Select
TYPE _rect
x; y; width; height
ENDTYPE

GLOBAL screen AS _rect, boundary AS _rect, tile AS _rect, player AS _rect, tile_map$[] //we use the variable "screen" as pointer to the type
// _rect, same goes for boundary, tile, player..and declare them globals

main()

FUNCTION main:
init()
animate_scene()
ENDFUNCTION

FUNCTION init:
screen.width = 640
screen.height = 480
SETSCREEN screen.width, screen.height, FALSE //set the screen size and windowed mode

tile.width = 64
tile.height = 64

boundary.x = -tile.width //this is the starting X point of the field
boundary.width = screen.width + tile.width //this is the ending X point of the field
boundary.y = -tile.height //starting Y point of the field
boundary.height = screen.height + tile.height //ending Y point of the field

tile.y = INTEGER(screen.height * 4 / tile.height) // it should be the total number of tiles on the y axis, in this case 30

// Generate an ASCII maze quickly: http://www.vidarholen.net/cgi-bin/labyrinth?w=9&h=31

DIM tile_map$[tile.y + 1] //we set the dimensions of the map array, the size is the total number of tiles on the y axis plus 1

tile_map$[0] = "???????????????"
tile_map$[1] = "???????????????"
tile_map$[2] = "? ? ? ??? ??? ?"
tile_map$[3] = "? ??? ? ????? ?"
tile_map$[4] = "??? ????? ??? ?"
tile_map$[5] = "? ? ? ??? ?????"
tile_map$[6] = "? ? ? ? ??? ? ?"
tile_map$[7] = "? ? ????????? ?"
tile_map$[8] = "? ??? ? ????? ?"
tile_map$[9] = "??? ? ??? ?????"
tile_map$[10] = "? ????? ? ? ? ?"
tile_map$[11] = "? ? ? ? ????? ?"
tile_map$[12] = "? ? ? ? ? ??? ?"
tile_map$[13] = "? ? ? ? ? ? ? ?"
tile_map$[14] = "? ? ????? ? ? ?"
tile_map$[15] = "? ????? ???????"
tile_map$[16] = "??? ? ??? ??? ?"
tile_map$[17] = "? ? ? ? ? ? ???"
tile_map$[18] = "? ? ? ??????? ?"
tile_map$[19] = "? ????? ????? ?"
tile_map$[20] = "? ? ? ??? ?????"
tile_map$[21] = "? ? ??? ????? ?"
tile_map$[22] = "? ? ? ????? ? ?"
tile_map$[23] = "? ????? ? ? ? ?"
tile_map$[24] = "????? ? ? ? ???"
tile_map$[25] = "? ??????????? ?"
tile_map$[26] = "? ? ? ? ????? ?"
tile_map$[27] = "? ? ??????? ? ?"
tile_map$[28] = "? ??????? ??? ?"
tile_map$[29] = "???????????????"

tile.x = LEN(tile_map$[0]) //we set the total amount of tiles on the x axis, based on the map array dimension (len is used to return
//a number of char in a string, in this case 15)
ENDFUNCTION

FUNCTION animate_scene:
WHILE TRUE
update_player()
draw_field()
SHOWSCREEN
WEND
ENDFUNCTION

FUNCTION update_player:
LOCAL step_move = 4

IF KEY(200) THEN INC player.y, step_move // when we press up,we increase the player.y variable by step_move (in this case 4)
IF KEY(203) THEN INC player.x, step_move // when we press left we do as above
IF KEY(205) THEN DEC player.x, step_move // when we press right we decrease the player.y variable by step_move
IF KEY(208) THEN DEC player.y, step_move // when we press down as above
ENDFUNCTION

FUNCTION draw_field:
LOCAL map AS _rect //we use map as a local pointer to the type _rect

FOR map.y = 0 TO tile.y - 1 //we tell the pc to tile vertically until it reach the total amount of tiles minus 1
FOR map.x = 0 TO tile.x - 1 //same for the x axis
draw_tile(map.x, map.y) //draws the tiles based on the amount contained in map.x and map.y
NEXT
NEXT
ENDFUNCTION

FUNCTION draw_tile: map_x, map_y //a function which accept 2 parameters
LOCAL box AS _rect, color, ascii, line$ //box is locally used as a pointer to rect, color, ascii and line

box.x = (map_x * tile.width) + player.x //this is used to set the x starting point at which we draw the tiles, and since we want
//to scroll them too we add the player.x amount, which is a sort of speed
box.y = (map_y * tile.height) + player.y //same for the y starting point
IF BOXCOLL(box.x, box.y, box.width, box.height, boundary.x, boundary.y, boundary.width, boundary.height)//check if theres a collision
//between boundaries and the actual tile we are on, so we can make the border flash!
line$ = tile_map$[map_y]
ascii = ASC(MID$(line$, map_x, 1))
SELECT ascii
CASE 32
color = RGB(0, 128, 0)
DEFAULT
IF map_x = 0 OR map_y = 0 OR map_x = tile.x - 1 OR map_y = tile.y - 1
color = RGB(0, 0, 64 * SIN(GETTIMERALL() / 10) + 64) // outer wall
ELSE
color = RGB(0, 0, 32) // inner wall
ENDIF
ENDSELECT
DRAWRECT box.x, box.y, tile.width - 1, tile.height - 1, color // DRAWSPRITE tiles here
ENDIF
ENDFUNCTION

It took me a bit to understand how the actual scroll works, but i think i got it.
When i have time i will add some actual borders which we cant trespass.
I noticed theres lots of stuttering with my pc, is it because we need a sort of frame limiting?
Anyway thank you very much for the help!

mentalthink

Hi TeoM, it´s very simple you only have to think in something like this, if I add a value like this.

x_scroll=x_scroll+1

the image or the tile set , go to the right of the screen

if you want to the left it´s this:

x_scroll=x_scroll+1

and if you want try and image or a text or anything, you can make in example this.

Drawsprite my_Image,x_scroll,0


If you have a doubt how works the screen it´s very simple:

Screen: (you have to use your imagination  =D)

           0,0
            ********************************
            *                                                      *
            *                                                      *
            *                                                      *
            *                                                      *
            *                                                      *
            *                                                      *
            *                                                      *
            *                                                      *
            ******************************** THE MAX VALUES OF YOUR SCREEN IN THE X AND Y, in example windows will be set in default 640,480

Left Corner Up, it´s
X=0
Y=0

and the rigth corner bottom it´s the to greater values how you are set the screen.

Remenber to the rigth I have to do an add
to the left I have to do a minus.












matchy

#11
Quote from: Kitty Hello on 2011-Jul-14
easy to understand. But! I'd calculate xfrom, xto and yfrom,yto variables for the x,y loop that are in the visible range (no need for boxcoll of every tile).
Also, I'd put the tiles in an integer array instead of ASC for each tile/frame.

Great tutorial!

@teoM Please note, this is not a tutorial but a demonstration. You've commented a lot of code that self explanatory which is a bit strange for what you really asked for. I think you should understand the basics before attempting tile scrolling to avoid mistakes in understanding. ;)

@Hello Kitty 8) Yes, the map should be moved to an array...which is another topic on creating and importing maps.

Here is the update for tile boundary draw:
Code (glbasic) Select

FUNCTION draw_field:
LOCAL map AS _rect, start AS _rect, fin AS _rect

start.x = INTEGER((-player.x + boundary.x) / tile.width)
start.y = INTEGER((-player.y + boundary.y) / tile.height)
fin.x = INTEGER((-player.x + boundary.x + boundary.width) / tile.width)
fin.y = INTEGER((-player.y + boundary.y + boundary.height) / tile.height)

FOR map.y = start.y TO fin.y
FOR map.x = start.x TO fin.x
draw_tile(map)
NEXT
NEXT
ENDFUNCTION

teoM

I've commented it just to see if i have grasped the concept, thats it.
thanks all

MrTAToad

I have a Mappy routine somewhere.  Its not totally up-to-date (as it can only handle 8 layers), but trying to get the author to detail the format of the extra ones is like trying to wring blood out of a stone :)