Endless Horizontal Scrolling Code

Previous topic - Next topic

mrplant

Hi.

I am using the following code to scroll along a graphic image. What I have is an image that is 6144 pixels by 768 - I am using a screen resolution of 1024x768 fullscreen.
I want to have this large image shown on the screen and to slowly scroll along the screen - once it gets to the end - it loops around smoothly to the beginning again.
To make it loop smoothly - I pasted the first 1024x768 pixels of the image onto the end again. The code below does the rest. Please take a look.

Now my questions...

Although this code works - its crude and I do want to stick to this method of doing it  - i.e. as described above - but can anyone suggest a more efficient way of doing this that perhaps
is Kinder on memory usage or is faster - although this works fine - I do worry about this.. Anyone?
My code is below should anyone want to run it - comments very welcome. Thanks.



// --------------------------------- //
// Project: Testbed: Lullaby TV
// Start: Wednesday, December 20th, 2011
// IDE Version: 10


SETCURRENTDIR("Media") // go to media files

LOADSPRITE "Lullaby-6144x768.png", 0

//PLAYMUSIC "Old MacDonald.wav",TRUE // Loop Music

CONSTANT ScreenWidth = 1024
CONSTANT ScreenHeight = 768

CONSTANT GraphicWidth = 6144

GLOBAL XPos = 0

LIMITFPS 50

CLEARSCREEN RGB(0,0,0) // Set the backbuffer background colour to Black.
SHOWSCREEN // Show it.

REPEAT
   VIEWPORT XPos,0,ScreenWidth+(-XPos),ScreenHeight
   DRAWSPRITE 0,0,0
   SHOWSCREEN
   DEC (XPos)
   IF XPos < -(GraphicWidth-ScreenWidth)
      XPos = 0
   ENDIF
UNTIL FALSE


[attachment deleted by admin]

ampos

Many devices have sprite lenght limited to 1024x1024 or 2048x2048. Even most of the PCs are at 2048.

So to be safe, you have to be limited to 1024x1024.

BTW, you dont need clearscreen 0, just use clearscreen -1. Why clear the screen if it is going to be overwritten?  :P

also this will work:

Code (glbasic) Select
cleascreen -1
repeat
for x=0 to 6144-1024
   drawsprite 0,x,0
   showscreen
next
until exit=true
check my web and/or my blog :D
http://diniplay.blogspot.com (devblog)
http://www.ampostata.org
http://ampostata.blogspot.com
I own PC-Win, MacBook 13", iPhone 3G/3GS/4G and iPAC-WinCE

mrplant

Thanks for your reply.

The Clearscreen command was an oversight I copied/pasted from my previous project  :-[

Given the size of the graphic file - and this content is just a test - I'd like to have non repeating elements so scrolling parallax layer style prob isn't what I want...

How can I then handle an image of this size - given that its 6000 plus pixels across and I want to display a fullscreen segment of that (1024x768) each frame..

I can't seem to find commands to cut out a rectangles area from a larger graphic image and show that...

I suppose what I am asking is what is the best approach to take to do this?

thanks again.


Moru

Get a tilemap editor. Can't say much else without seeing the picture you want to display...

Slydog

#4
You would split your 6144 wide image into 6 (or 3) smaller images.
I'm not sure what platform you are targeting, but if it's PC then you should be good at 2048 wide images.

Then to scroll it you need to determine which two images (of the 3, if they are 2048 wide) you need displayed currently.
To draw the portion of the two images you want, use POLYVECTORs and specify the x, y for each corner vertice of the source image.

Here's something I whipped up (NOT tested) to show you what I mean.
I used my Poly_Draw() function, and TXyXy TYPE to make things simple.

Code (glbasic) Select
TYPE TXyXy
x1%
y1%
x2%
y2%

FUNCTION Set: x1%, y1%, x2%, y2%
self.x1 = x1
self.y1 = y1
self.x2 = x2
self.y2 = y2
ENDFUNCTION
ENDTYPE

CONSTANT ScreenWidth% = 1024
CONSTANT ScreenHeight% = 768
CONSTANT GraphicWidth% = 2048
CONSTANT BackgroundSprites% = 3
CONSTANT BackgroundWidth% = 2048 * 3 // GraphicWidth * BackgroundSprites

GLOBAL sp_background%[]
DIM sp_background[BackgroundSprites]
LOCAL xPos%=0
LOCAL x1%=0 // x Position where the two sprites are joined
LOCAL sp_current% // Current sprite we're working with
LOCAL xy_screen AS TXyXy // Screen x,y TL and BR corner locations
LOCAL xy_sprite AS TXyXy // Sprite x,y TL and BR corner locations

// Load the three images into the 3 sprites IDs
sp_background[0] = GENSPRITE
LOADSPRITE "Lullaby-1.png", sp_background[0]
sp_background[1] = GENSPRITE
LOADSPRITE "Lullaby-2.png", sp_background[1]
sp_background[2] = GENSPRITE
LOADSPRITE "Lullaby-3.png", sp_background[2]

// +---+------+
// |B1 |B2    |
// |   |      |
// +---+------+
// 0  x1     ScreenWidth

REPEAT
x1 = GraphicWidth - MOD(xPos, GraphicWidth)
sp_current = xPos / GraphicWidth // Will be either 0, 1, or 2

// Draw left background sprite
xy_screen.Set(0, 0, x1, ScreenHeight)
xy_sprite.Set(GraphicWidth-x1, 0, GraphicWidth, GraphicHeight)
STARTPOLY sp_current
Poly_Draw(xy_screen, xy_sprite, RGB(255,255,255))
ENDPOLY

// Draw right background sprite
INC sp_current // Use next background sprite
IF sp_current > BackgroundSprites THEN sp_current = 0  // Cycle to first background sprite when at end
xy_screen.Set(x1+1, 0, ScreenWidth, ScreenHeight)
xy_sprite.Set(0, 0, ScreenWidth-x1, GraphicHeight)
STARTPOLY sp_current
Poly_Draw(xy_screen, xy_sprite, RGB(255,255,255))
ENDPOLY

INC xPos
IF xPos > (BackgroundWidth - ScreenWidth) THEN xPos = 0
UNTIL FALSE

// (uv1) 0___2
//       |  /|
//       | / |
//       |/__|
//       1   3 (uv2)
// xy :: Top-Left and Bottom-Right screen location
// uv :: Top-Left and Bottom-Right texture location
FUNCTION Poly_Draw: xy AS TXyXy, uv AS TXyXy, colour%
POLYNEWSTRIP
POLYVECTOR xy.x1, xy.y1, uv.x1, uv.y1, colour // TL
POLYVECTOR xy.x1, xy.y2, uv.x1, uv.y2, colour // BL
POLYVECTOR xy.x2, xy.y1, uv.x2, uv.y1, colour // TR
POLYVECTOR xy.x2, xy.y2, uv.x2, uv.y2, colour // BR
ENDFUNCTION
My current project (WIP) :: TwistedMaze <<  [Updated: 2015-11-25]

mrplant

Hi thanks.

I will check this new way out and report back..

My target device is probably going to be the iPad in landscape mode 1024x768 - what is the maximum safe size to use for that platform just out of interest - anyone know?

mrplant

This code is simpler and does work... but as I originally discovered when writing my version - it scrolls the background the wrong direction left to right instead of right to left

cleascreen -1
repeat
for x=0 to 6144-1024
   drawsprite 0,x,0
   showscreen
next
until exit=true

Slydog

I think to just reverse the direction, change the last two lines in the loop to:

Code (glbasic) Select
DEC xPos
IF xPos < 0 THEN xPos = (BackgroundWidth - ScreenWidth)  // -1 : May need the '-1' at the end if flickers when at end
My current project (WIP) :: TwistedMaze <<  [Updated: 2015-11-25]

mrplant

Thanks Slydog - I haven't actually looked at your example code yet but it looks interesting - about to check it out now thanks.

I was still playing about with my own code - on the iPad it is stretching the aspect ratio for some weird reason I can't figure out - perhaps as the texture size is too big??

anyway-  about to test your solution out..

thanks.

chve

I should do something so:

Code (glbasic) Select

// --------------------------------- //
// Project: Testbed: Lullaby TV
// Start: Wednesday, December 20th, 2011
// IDE Version: 10.209


SETCURRENTDIR("Media") // go to media files

LOADSPRITE "Lullaby-6144x768.png",  map

//PLAYMUSIC "Old MacDonald.wav",TRUE // Loop Music

CONSTANT ScreenWidth = 1024
CONSTANT ScreenHeight = 768

CONSTANT GraphicWidth = 6144

GLOBAL map, exit

GLOBAL speedH, speedW, imgX, scrW, imgWide, imgY, scrH, imgHeight
GLOBAL worldX, worldY ,MundoX, MundoY


GETSPRITESIZE map, imgWide, imgHeight

scrW=imgWide ; scrH= imgHeight


imgX=0 ;imgY=0 ; speedW=1


LIMITFPS 50

SHOWSCREEN // Show it.

CLEARSCREEN -1
REPEAT
imgX=imgX-speedW ; IF (imgX+scrW)<0 THEN imgX=imgX+scrW

MundoX = MOD (worldX,imgWide) ;MundoX = -imgX ; IF worldX < 0 THEN MundoX = imgX - imgWide
DRAWSPRITE map, imgX, imgY
DRAWSPRITE map, imgX, imgY+scrH
    DRAWSPRITE map, imgX+scrW, imgY
DRAWSPRITE map, imgX+scrW, imgY+scrH

SHOWSCREEN
UNTIL exit=TRUE


mrplant

Hi Slydog.

I have been trying to compile your code but get this error.
Could you possibly run attached file with your code and work out what I have done wrong?
Graphics are cut into 2048 by 768 sizes like you mentioned..

thanks

This is the error I get when compiling for windows.

*** Configuration: WIN32 ***
precompiling:
GPC - GLBasic Precompiler V.10.104 SN:1d5d2793 - 3D, NET
Wordcount:50 commands
compiling:
C:\Users\ADMINI~1\AppData\Local\Temp\glbasic\gpc_temp0.cpp: In function `int __GLBASIC__::__MainGameSub_()':
C:\Users\ADMINI~1\AppData\Local\Temp\glbasic\gpc_temp0.cpp:130: error: `x1' was not declared in this scope
*** FATAL ERROR - Please post this output in the forum
_______________________________________
*** Finished ***

[attachment deleted by admin]

Kitty Hello

oh! bug.

Either move the TYPE declaration below the "main" function, or don't use the same parameter name "x1" in the Set function as well as a LOCAL in "main". So sorry.

mrplant


mrplant

go code to compile but it locked up machine. I don't know the first thing about polyvectors so I added  a show screen command to main loop and it didn't crash this time!
All it showed though was a scrolling in outline sort of like a moving pyramid single line - no graphic content just outline.. then another pyramid outline, followed by another..
Anyone?
Way over my head now... ;-(

Slydog

#14
Sorry, I've been away all Christmas week.
I ran the code and see there were a few bugs.  (ha, I guess I should have tested it!)

I've fixed them as far as I can see, and it now scrolls continuously and smoothly.
See the attached project.

Oh, for testing, I put a red line at the bottom of the 2nd graphic (and a yellow on the 3rd) to help see where the scroll position is at.

You can switch the direction with the new 'direction' variable.  (-1 for reverse)
You can set the scroll speed with the new 'speed' variable.  (I guess these could be combined into one variable using a negative speed for the reverse direction!)

I'm not 100% sure this is pixel perfect yet.
It may skip the 1st or last pixel in the graphic, and/or overlap the joining pics by a pixel.
More testing would be needed. (ie. I would start and end each graphic file with a one pixel wide line, each file with a different colour, see if you notice both lines where the split is).

[Update] I fixed a bug with detecting the end (or start, depending on scroll direction) of the last/first image.
It looked like it was working, but it happens that the 1st half of the 1st image and 2nd half of the last image were identical so it appeared to connect back to back.

[attachment deleted by admin]
My current project (WIP) :: TwistedMaze <<  [Updated: 2015-11-25]