Hi there - Newb Question :)

Previous topic - Next topic

Stevester

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.

MrTAToad

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.

Ian Price

What you can do is render each rectangle to a sprite/screen and then display that.

Code (glbasic) Select

// 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


:)
I came. I saw. I played.

Moru

Or USEASBMP

Oh, and welcome to the boards :-)

Ian Price

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 :)
I came. I saw. I played.

ampos

Code not tested, just typing "online" :)
Code (glbasic) Select

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
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

quangdx

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.

Code (glbasic) Select

// 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


:)
Asobi tech - the science of play.
Spare time indiegame developer.

Stevester

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.


Ian Price

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.
I came. I saw. I played.

Moru

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.

Ian Price

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.
I came. I saw. I played.

Slydog

#11
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.

Code (glbasic) Select
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
My current project (WIP) :: TwistedMaze <<  [Updated: 2015-11-25]

Ian Price

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
I came. I saw. I played.

Slydog

#13
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
Code (glbasic) Select
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.
My current project (WIP) :: TwistedMaze <<  [Updated: 2015-11-25]

Ian Price

That's a good effect =D
I came. I saw. I played.