Hi there,
I'm looking at GLBasic as a replacement to DBPro and have downloaded and been playing with it tonight.
Love some of the sample games out there, especially those with the vector style 'glowy' graphics (glowingrocksfromouterspace, scramble, etc)! I'm a ways off from anything like that tho. :)
Anyhoo, I'm made my first 'Hello World' program and am well on the way but have a question on my second (and most complex program to date) . . . .
I'm trying to display lots of random rectangles on the screen, adding one with each loop but I'm finding the SHOWSCREEN command appears to be getting in the way as its clearing the screen on every loop. What I'm wanting is to add a rectangle to screen on every loop rather than draw, show, clear, repeat.
This is what I have so far:
REPEAT
DRAWRECT RND(800), RND(600), RND(100), RND(100), RGB(RND(255), RND(255), RND(255))
SHOWSCREEN
UNTIL KEY(28)
MOUSEWAIT
END
I don't want the showscreen command to clear the backscreen every time, I want the rectangles to randomly overlap and fill the screen. Is there an alternative command to use to draw to the main screen or prevent the backscreen from wiping?
Any help would be appreciated. :)
Steve.
You could use CLEARSCREEN -1 for a blurry effect. However, unlike DBPro, you do have to render all graphics for each display loop, which does give you the power to change the order of rendering.
What you can do is render each rectangle to a sprite/screen and then display that.
// Set screen resolution (Windowed mode=0 - full screen=1)
SETSCREEN 800,600,0
// Create a virtual screen and use it as sprite #999
CREATESCREEN 1,999,640,480
// Repeat until ESC pressed
WHILE TRUE
// Switch all drawing processes to the virtual screen
USESCREEN 1
// Draw rectangles ONTO the virtual screen sprite
DRAWRECT RND(800), RND(600), RND(100), RND(100), RGB(RND(255), RND(255), RND(255))
// Switch back to normal screen
USESCREEN -1
// Draw the virtual screen sprite
DRAWSPRITE 999,0,0
// Update the screen
SHOWSCREEN
// Repeat loop if WEND condition is not met
WEND
:)
Or USEASBMP
Oh, and welcome to the boards :-)
USEASBMP will capture the entire screen and ANY and ALL changes. This would be OK for the example above, as there's no moving elements and you just want to update the rectangles. IIRC it also takes CPU time to use this.
My code above will only capture what is drawn onto the virtual screen, so you can have other things moving over/on/behind the sprite image and they won't appear repeatedly in the scene. Obviously the request was only for DRAWRECTs and this would work fine (as I said above), but if you want anything else moving on screen as well, then avoid USEASBMP (or you can end up with some very funky and cool effects).
And yes, welcome :)
Code not tested, just typing "online" :)
type r
x;y;w;h
endtype
dim rect[] as r
repeat
s=bounds(rect[],0)
redim rect[s]
rect[s].x=rnd(100) rect[s].y=rnd(100) rect[s].w=rnd(100) rect[s].h=rnd(100)
for each box in rect[]
drawrect box.x,box.y,box.w,box.h
next
showscreen
until exit=true
I second Ian Price on his solution,
as I was about to suggest the exact same thing.
Quote from: Ian Price on 2011-Jun-14
What you can do is render each rectangle to a sprite/screen and then display that.
// Set screen resolution (Windowed mode=0 - full screen=1)
SETSCREEN 800,600,0
// Create a virtual screen and use it as sprite #999
CREATESCREEN 1,999,640,480
// Repeat until ESC pressed
WHILE TRUE
// Switch all drawing processes to the virtual screen
USESCREEN 1
// Draw rectangles ONTO the virtual screen sprite
DRAWRECT RND(800), RND(600), RND(100), RND(100), RGB(RND(255), RND(255), RND(255))
// Switch back to normal screen
USESCREEN -1
// Draw the virtual screen sprite
DRAWSPRITE 999,0,0
// Update the screen
SHOWSCREEN
// Repeat loop if WEND condition is not met
WEND
:)
Thanks for the responses (and the welcomes) :)
So i can draw to a virtual screen then show the results. The virtual screen isn't cleared and can be added to and flipped back to the realscreen (if I got that correct!). Will have a play when i get home tonight.
Am i right in thinking Ampos' solution is building an array on each loop and redrawing rects to the screen on each sync?
It's gonna take me a while to get my head round the ins and outs but I'm liking the simplicity/clarity so far.
Cheers,
Steve.
Yes, ampos is building an array of Types and then every loop iterating through them to draw the rect. This is not a good idea, as eventually you'll have to iterate through thousands of rects, which will significantly slow down the system.
The virtual screen solution will never have any slowdown, as it's only ever drawing one rect per loop to the virtual screen (which has all the old rects on it) and displaying that to the actual screen.
Quote from: Ian Price on 2011-Jun-14
USEASBMP will capture the entire screen and ANY and ALL changes. This would be OK for the example above, as there's no moving elements and you just want to update the rectangles. IIRC it also takes CPU time to use this.
Not entirely true, it will only capture the content of the screen at the time of the call. Everything you add after this is not captured and will be cleared the next time. Perfect for paint-programs or for a background-effect. And simple to understand for a newbie :-)
I'm not saying it's the only way of doing it, just another way of getting static content on the screen.
QuoteNot entirely true, it will only capture the content of the screen at the time of the call. Everything you add after this is not captured and will be cleared the next time.
Actually, just using the BMP image from calling USEASBMP takes longer than displaying a full-screen sprite (I tested this a long while back and it may have changes since then). Calling the USEASBMP before a main loop slowed the actual FPS for the main loop by a fraction, and that was only calling it once. Calling it every frame may have a more dramatic effect.
This is a fun one!
Updating ampos's code, you could have a maximum rectangles allowed in the array at once, with the older ones getting overwritten in the array. This could be updated to allow for effects for the older rectangles such as fading away, or slowly moving off the screen.
But even at 1000, DRAWRECT could get slow. I would recommend using POLYVECTORS for anything real.
TYPE TRectangle
left%
top%
width%
height%
colour%
FUNCTION Set: l%, t%, w%, h%, colour%
self.left = l
self.top = t
self.width = w
self.height = h
self.colour = colour
ENDFUNCTION
FUNCTION Draw:
// Exit if rectangle hasn't been initialized
IF (self.left=0) AND (self.top=0) AND (self.width=0) AND (self.height=0) THEN RETURN
DRAWRECT self.left, self.top, self.width, self.height, self.colour
ENDFUNCTION
ENDTYPE
CONSTANT RECT_MAX% = 1000
GLOBAL rects[] AS TRectangle
GLOBAL pos%
GLOBAL rx%
DIM rects[RECT_MAX]
REPEAT
// New Rectangle
INC pos
IF pos>=RECT_MAX THEN pos=0
rects[pos].Set(RND(100), RND(100), RND(100), RND(100), RGB(RND(255),RND(255),RND(255)) )
// Draw all rectangles in the reverse order they were added, this controls the 'z-order' so latest is on top
// . . . draw the ones at the end of the array first
FOR rx = pos+1 TO RECT_MAX-1
rects[rx].Draw()
NEXT
// . . . draw the ones at the start of the array next
FOR rx = 0 TO pos
rects[rx].Draw()
NEXT
UNTIL FALSE
Yep, POLYVECTOR should be faster than multiple DRAWRECTS. And you can add extra effects to them.
You have to remember though that the OP has limited experience with GLB, so that's perhaps pushing him a bit too far and too fast. Let him get the basics down first! :P
Ya, I understand he's new to GLB, and was just trying to introduce him to some useful GLB concepts. :good:
Pushing it a bit too far would be this: (my attempt of fading the older rects!) :O
TYPE TRectangle
left%
top%
width%
height%
colour%
FUNCTION Set: l%, t%, w%, h%, colour%
self.left = l
self.top = t
self.width = w
self.height = h
self.colour = colour
ENDFUNCTION
FUNCTION Draw:
// Exit if rectangle hasn't been initialized
IF (self.left=0) AND (self.top=0) AND (self.width=0) AND (self.height=0) THEN RETURN
DRAWRECT self.left, self.top, self.width, self.height, self.colour
ENDFUNCTION
FUNCTION Expand: amount%=1
DEC self.left, amount
DEC self.top, amount
INC self.width, amount*2; IF (self.width<1) THEN self.width=0
INC self.height, amount*2; IF (self.height<1) THEN self.height=0
ENDFUNCTION
ENDTYPE
CONSTANT RECT_MAX% = 100
GLOBAL rects[] AS TRectangle
GLOBAL pos%
GLOBAL rx%
DIM rects[RECT_MAX]
ALLOWESCAPE TRUE
REPEAT
// New Rectangle
INC pos
IF pos>=RECT_MAX THEN pos=0
rects[pos].Set(RND(200), RND(200), RND(200)+20, RND(200)+20, RGB(RND(255),RND(255),RND(255)) )
// Draw all rectangles in reverse order they were added, this controls the 'z-order' so latest is on top
// . . . draw the ones at the end of the array first
FOR rx = pos+1 TO RECT_MAX-1
rects[rx].colour = Fade(rects[rx].colour, rx, pos)
rects[rx].Expand(-1)
rects[rx].Draw()
NEXT
// . . . draw the ones at the start of the array next
FOR rx = 0 TO pos
rects[rx].colour = Fade(rects[rx].colour, rx, pos)
rects[rx].Expand(-1)
rects[rx].Draw()
NEXT
SLEEP 50
SHOWSCREEN
UNTIL FALSE
FUNCTION Fade%: colour%, rx%, pos%
LOCAL colour_new%
LOCAL age#
age = pos - rx
IF age < 0 THEN age = age + RECT_MAX
// Set 'age' to range: [0.0] - [1.0]
age = age / (RECT_MAX * 1.0)
colour_new = Colour_Brightness(colour, -(age * 100))
RETURN colour_new
ENDFUNCTION
// colour_new = Colour_Brightness(colour, 25) // new colour 25% brighter
// colour_new = Colour_Brightness(colour, -50) // new colour 50% darker
FUNCTION Colour_Brightness%: colour%, increase%
LOCAL r%, g%, b%, percent#
percent = increase / 100.0
r=bAND(colour,0xff)
g=bAND(colour/0x100,0xff)
b=bAND(colour/0x10000,0xff)
//a=bAND(colour/0x1000000,0xff)
IF percent >= 0
r = INTEGER((255 - r) * percent + r)
g = INTEGER((255 - g) * percent + g)
b = INTEGER((255 - b) * percent + b)
ELSE
r = INTEGER(r * ABS(-1 - percent))
g = INTEGER(g * ABS(-1 - percent))
b = INTEGER(b * ABS(-1 - percent))
ENDIF
RETURN RGB(r, g, b)
ENDFUNCTION
[Edit] Updated to shrink rectangles as they get older, they appear to get further away.
That's a good effect =D
Ampos: You should push onto the array rather than redimming. Is a bit less code and is easier to read IMO.
Cheers
Hi and welcome.
As you can see, there are often many solutions for one problem. As a programer its up to you, to find the one, that fits best to your needs. My solution for your Problem would be GRABSPRITE:
REPEAT
DRAWSPRITE 1, 0,0
DRAWRECT RND(800), RND(600), RND(100), RND(100), RGB(RND(255), RND(255), RND(255))
GRABSPRITE 1, 0,0, 800,800
SHOWSCREEN
UNTIL KEY(28)
MOUSEWAIT
END
GRABSPRITE would again grab the whole screen (like USEASBMP) and any action on it. It would be OK on just the rectangles but if you want to add anything else (moving player etc.) then avoid.
Going back to the original question, I've just tested CLEARSCREEN -1 using GLBasic 9.040
and it gives the required effect.
CLEARSCREEN -1
REPEAT
DRAWRECT RND(800), RND(600), RND(100), RND(100), RGB(RND(255), RND(255), RND(255))
SHOWSCREEN
UNTIL KEY(28)
MOUSEWAIT
END
I know previously it would flicker between odd and even frames of rendering (back and front buffers, as they were swapped with the SHOWSCREEN command) But it now looks like they are one in the same.
Quote from: Stevester on 2011-Jun-14
I'm trying to display lots of random rectangles on the screen, adding one with each loop but I'm finding the SHOWSCREEN command appears to be getting in the way as its clearing the screen on every loop. What I'm wanting is to add a rectangle to screen on every loop rather than draw, show, clear, repeat.
I don't want the showscreen command to clear the backscreen every time, I want the rectangles to randomly overlap and fill the screen. Is there an alternative command to use to draw to the main screen or prevent the backscreen from wiping?
Any help would be appreciated. :)
Steve.
Thanks for the responses on this one guys.
Looks like there are a few options to achieving what I was looking for, and running through them has led me onto learning some of the other commands.
I like the fading / shrinking effect in particular - adds a bit of style to the program :)
Struggling to understand the 'self' command though. Can't find reference to it in the help doc:
FUNCTION Set: l%, t%, w%, h%, colour%
self.left = l
self.top = t
self.width = w
self.height = h
self.colour = colour
ENDFUNCTION
Cheers,
Steve.
Self is used to let a function in a type access a variable defined in it :
TYPE TTest
a%
FUNCTION test%:
self.a%=1 // Set the a% value in TTest to 1
ENDFUNCTION
ENDTYPE
You may be interested in my Programmers Reference Guide, which details it all : http://www.lulu.com/product/paperback/glbasic-programmers-reference-guide-%28second-edition%29/16044005
alternative you can use CREATESCREEN and draw each box into that, and then draw that screen to the backbuffer.
SCREENS other than backbuffer is never clean up, so its can been alternativt to avoid drawing 1000boxes in one frame.
QuoteYou may be interested in my Programmers Reference Guide, which details it all : http://www.lulu.com/product/paperback/glbasic-programmers-reference-guide-%28second-edition%29/16044005
Had a look at this and will definitely be looking into a copy though there's quite a difference (price-wise) between the hardcopy and the download (about £70) - is this correct? The hardcopy seems really expensive but the download seems too cheap!
QuotePosted by: spacefractal
« on: Today at 01:45:14 pm »
alternative you can use CREATESCREEN and draw each box into that, and then draw that screen to the backbuffer.
SCREENS other than backbuffer is never clean up, so its can been alternativt to avoid drawing 1000boxes in one frame.
Thats very handy to have a screen (or image) that isn't cleared every cycle. You then copy this to the backscreen and flip it to the visible screen using SHOWSCREEN command.
This is slightly different to what I'm used to but I think I'm starting to get the hang of it!! :)
I'd been thinking that having to pass everything through the SHOWSCREEN command at the end of every cycle was a bit of a limitation but thats not looking to be the case with the alternative options available. I think it promotes a bit more structure to the coding as well.
I was also a bit stumped with the explicit declarations (hadn't realised theres a tick box in options) but I can see the benefit of this facility - especially with my dodgy coding! :) Will be very useful in larger programs when I accidentally misspell one of my variables. (Mind, I've turned it off for now!).
Quote from: Ian Price on 2011-Jun-14
GRABSPRITE would again grab the whole screen (like USEASBMP) and any action on it. It would be OK on just the rectangles but if you want to add anything else (moving player etc.) then avoid.
but if you drew the sprite, then the new rectangle, then grab it, then draw the player which could move, then showscreen you would keep the rectangles sprite minus any other moving images added after.