Fade in/out effect

General FreeBASIC programming questions.
Post Reply
Tusike
Posts: 207
Joined: Jan 03, 2008 16:53
Location: Hungary

Fade in/out effect

Post by Tusike »

Here is the code I have for fading a picture on the screen in and then out again:

Code: Select all

FOR i = 0 TO 255
    PALETTE GET i, red(i), grn(i), blu(i)
NEXT
FOR i = 0 TO 255
PALETTE i, 0, 0, 0
NEXT
FOR i = 255 TO 0 STEP -1
a = INKEY$
IF a <> "" THEN EXIT FOR
FOR h = 0 TO 255
    PALETTE h, ((red(h) - (i * (red(h) / 255)))), ((grn(h) - (i * (grn(h) / 255)))),((blu(h) - (i * (blu(h) / 255))))
NEXT h  
 SLEEP 10
NEXT i

DO: LOOP UNTIL INKEY$ = ""
IF i = -1 THEN SLEEP 50
FOR i = i + 1 TO 255
a = INKEY$
IF a <> "" THEN EXIT FOR
FOR h = 0 TO 255
   PALETTE h, ((red(h) - (i * (red(h) / 255)))), ((grn(h) - (i * (grn(h) / 255)))),((blu(h) - (i * (blu(h) / 255))))
NEXT h 
SLEEP 10
NEXT i
This only works for 8bpp depth. For true colors like 15bpp or higher depth it doesn't. Does anybody know how to fade in/out using 15bpp or higher?
Thanks!

-Tusike
nkk_kan
Posts: 209
Joined: May 18, 2007 13:01
Location: India
Contact:

Post by nkk_kan »

The Pallete command won't work in gfx modes having depth greater than 8 bpp..

for greater screen mode...i think RGB command should be useful...it doesn't change the pallete but u can get the colour you want using it..

what compiler version are you using?
you haven't declared any variables...
nkk_kan
Posts: 209
Joined: May 18, 2007 13:01
Location: India
Contact:

Post by nkk_kan »

this works on my windows Xp
but the problem is that it also changes the windows pallete
It should work well for a fullscreen program..

Code: Select all

#include "fbgfx.bi"
using FB

screenres 640,480,32,,0
screenset 1,0

dim shared as integer i,red(255),grn(255),blu(255),h

FOR h = 255 to 1 step -1
    out &h3c8,0
    out &h3c9,h
    out &h3c9,h
    out &h3c9,h
    flip
    sleep 10,1
    screensync
next
FOR h = 1 To 255 step -1
    out &h3c8,0
    out &h3c9,h
    out &h3c9,h
    out &h3c9,h
    flip
    sleep 10,1
    screensync
next

Tusike
Posts: 207
Joined: Jan 03, 2008 16:53
Location: Hungary

Post by Tusike »

Sorry I forgot to include the variable declaration part. The FB help section doesn't say that palette doesn't work for screen 14 - 21...
I noticed that POINT returns 255 + 255 * 256 + 255 * 65536 for a white pixel. (16777215).

-Tusike
nkk_kan
Posts: 209
Joined: May 18, 2007 13:01
Location: India
Contact:

Post by nkk_kan »

which version of FB compiler are you using?

i've got 0.18.2..

and make sure you get latest help file too

from here


http://freebasic.net/index.php/download
Tusike
Posts: 207
Joined: Jan 03, 2008 16:53
Location: Hungary

Post by Tusike »

I have the latest version. I don't think it'll work. Using your idea, I have to draw the image again and again using different palette. I just want to change the palette... Well, there's not much of a difference between 24bit and 256 color bitmap images:) I wouldn't be able to create really good looking sprites anyway.

-Tusike
Merick
Posts: 1038
Joined: May 28, 2007 1:52

Post by Merick »

With the higher color modes, I don't think that there's really any way to do it without having to redraw the image every frame.

However, if your image is in an fb.image ptr, then use can use the Alpha option with the put statment:

Code: Select all

#include once "fbgfx.bi"

using FB

screenres 640, 480, 32

dim as uinteger red = rgb(0,0,255), blue = rgb(255,0,0)

dim as image ptr img

img = imagecreate (200, 200, blue)

circle img, (100,100), 75,  red,,,,F

dim as double i = .3, a = 0  

while inkey ="" 
	screenlock
	cls
	put (100, 100), img, Alpha, a
	
	a += i
	
	if (a >=255) or a < = 0 then 
		i = -i
		a += i
	endif
	screenunlock
wend
Lachie Dazdarian
Posts: 2338
Joined: May 31, 2005 9:59
Location: Croatia
Contact:

Post by Lachie Dazdarian »

Yeah, what Merick said. In 16-bit and higher color depth modes forget about palettes. Think about pasting images with PUT using different ALPHA blenders.
wallace
Posts: 72
Joined: Dec 08, 2007 16:31

Post by wallace »

Code: Select all

dim i as FBimage ptr = imagecreate(640, 480)  'might be wrong order
dim j as FBimage ptr = imagecreate(640, 480, 0)
'create you image on the i buffer
dim a as ubyte
for a = 0 to 255
   PUT mainbuffer, (0, 0), i, PSET  'double buffered
   PUT mainbuffer, (0, 0), j, ALPHA, a
next
To fade back in change the for loop from '0 to 255' to '255 to 0 step -1'
KristopherWindsor
Posts: 2428
Joined: Jul 19, 2006 19:17
Location: Sunnyvale, CA
Contact:

Post by KristopherWindsor »

Here is a color blending demo:

Code: Select all

' Color Blending! v1.0
' By Kristopher Windsor

Sub colorsplit (Byval c As Uinteger, Byref r As Uinteger, Byref g As Uinteger, Byref b As Uinteger)
  r = (c And (&HFF Shl 16)) Shr 16
  g = (c And (&HFF Shl 8)) Shr 8
  b = c And &HFF
End Sub

Dim As Uinteger c1, c2, c, r1, g1, b1, r2, g2, b2, r, g, b

'make colors
c1 = Rgb(255, 100, 100) 'pink
c2 = Rgb(100, 0, 255) 'purplish blue

'split each color into three channels (r, g, b)
colorsplit(c1, r1, g1, b1)
colorsplit(c2, r2, g2, b2)

'average values of colors for each channel
r = (r1 + r2) Shr 1 '(shr 1) is (/ 2)
g = (g1 + g2) Shr 1
b = (b1 + b2) Shr 1

'put the channel averages into one color (the average, or blend of c1 and c2)
c = Rgb(r, g, b)

'draw
Screenres 640, 480, 32
Circle (100, 100), 80, c1,,,, F
Circle (200, 200), 80, c2,,,, F
Circle (300, 300), 80, c,,,, F 'average color
Sleep
And here is a macro for color blending. Instead of giving the exact average color, this will slightly change oldc toward the color of newc. If called several times, oldc will eventually be the same color as newc. So you can use this for animated blending. ;-)

Code: Select all

  #macro igui_mousedown_color_blend(newc, oldc)
    Scope
      Dim As Integer r, g, b
      r = (((oldc And &HFF0000) Shr 16) * 4 + ((newc And &HFF0000) Shr 16)) / 5
      g = (((oldc And &HFF00) Shr 8) * 4 + ((newc And &HFF00) Shr 8)) / 5
      b = ((oldc And &HFF) * 4 + (newc And &HFF)) / 5
      oldc = Rgb(r, g, b)
    End Scope
  #endmacro
;-)
nkk_kan
Posts: 209
Joined: May 18, 2007 13:01
Location: India
Contact:

Post by nkk_kan »

oh good...
my alpha mystery solved :P
Mlok
Posts: 123
Joined: Mar 08, 2006 1:07
Location: Czech Republic
Contact:

Post by Mlok »

nkk_kan: This is the commented source for a game of mine, where a very simple alpha based fading is used. Look on it, if you wish.

Code: Select all

' LASER PIPES by Mlok

#Include "fbgfx.bi"
Declare Function drawlines(tile As Any Ptr, ctile As Byte) As Any Ptr
Declare Sub drawbox (x1 As Integer, y1 As Integer ,x2 As Integer ,y2 As Integer)

ScreenRes 552,552,32,1,&h40
Randomize Timer

Dim Shared As Any Ptr hline, vline
Dim As Any Ptr tile, backtile, basetile, bomb, fadeout
Dim As UByte ctilex = 4, ctiley, state = 1
Dim As Byte ctile, temptile, fall, chart(8, -1 To 14), counter(3), stopcheck, nexttile, bonus(3)
Dim As Integer cola, colb, x, y, z, changex, score, tilecount=35, x1, x2, y1, y2, level = 0
Dim As String keypressed
Dim As Double speedtime, speed = 0.8, fallspeed = 0.02, rand
/'
For the start, let's make a quick list of what each varible is used for:

Ptrs HLINE and VLINE are image buffers  for pipes drawn on top of the image of a basic
	tile without any lines: BASETILE.
Ptr TILE is image buffer for the actal falling tile.
Ptr BACKTILE is the background image buffer.
Ptr BOMB is the image buffer for the "bomb" tile type.
Ptr FADEOUT is the image buffer used for alpha blending effects and for some general
	image storage as well.
UBytes CTILEX and CTILEY store the position of the falling tile.
Ubyte STATE stores the current state, states will be discussed later.
Byte CTILE stores the information about pipes in the falling tile.
Byte TEMPTILE is just sort of swapping space.
Byte FALL = 1 if the down arrow was pressed and the tile is on its way down, otherwise
	FALL = 0.
Byte array CHART stores information about all tiles and pipes on the board. 
Byte array COUNTER is used in the process of checking for long-enough pipes.
Byte STOPCHECK is used in the same process.
Byte NEXTTILE stores information about pipes in the tile which will come next.
Byte array BONUS sgnifies which pipe has currently the bonus property.
Integers COLA and COLB are colors used in the creation of the background.
Integers X, Y and Z are general purpose variables, mostly used in various FOR-NEXT
	loops etc.
Integer CHANGEX is used for to shift the falling tile right/left according to user's
	input.
Integers SCORE and LEVEL don't need to be explained
Integer TILECOUNT stores the number of tiles falled from the beginning of the current
	level.
Integers X1, Y1, X2 and Y2 are the dimensions for the drawbox sub
String KEYPRESSED is just a container for InKey
Doubles SPEEDTIME and SPEED are used for tile movement timing. The smaller SPEED is,
	the faster game runs, so better naming would be someting like delay, but what the
	hell.   
Double FALLSPEED is the speed into which the game is temporarily switched once user
	pressed down arrow. 
'/
Const light = RGBA(255,240,200,64)
Const lighter = RGBA(255,240,200,128)
Const dark = RGBA(8,16,32,64)
Const darker = RGBA(8,16,32,128)
Const text = RGB(0,48,192)
Const brighttext = RGB(0,64,240)
Const red = RGB(160,0,0)
Const brightred = RGB (240,0,0)

tile = ImageCreate(32,32,32)
basetile = ImageCreate(32,32,32)
backtile = ImageCreate(32, 32, RGB(0,40,80), 32)
bomb = ImageCreate (32,32,32)
hline = ImageCreate (32,6,32)
vline = ImageCreate (6,32,32)
fadeout = ImageCreate(288,480,32)

' The following section just pre-generates the grapihics into the buffers 
For x = 0 To 31
	For y = 0 To 31
		rand = CUByte((Rnd - 0.5) * 20)
		PSet basetile,(x, y), RGB(128 + rand, 136 + rand, 144 + rand)
	Next y
Next x

Line basetile,(0,0)-(31,0),lighter
Line basetile,(0,1)-(0,31),lighter
Line basetile,(1,1)-(30,1),light
Line basetile,(1,2)-(1,30),light
Line basetile,(1,31)-(31,31),darker
Line basetile,(31,1)-(31,30),darker
Line basetile,(2,30)-(30,30),dark
Line basetile,(30,2)-(30,29),dark

Get basetile,(0,0)-(31,31), bomb

Line bomb, (6,6)-(25,25),RGB(80,16,0),b
Line bomb, (7,7)-(24,24),RGB(128,24,0),b
Line bomb, (8,8)-(23,23),RGB(168,48,0),b
Line bomb, (9,9)-(22,22),RGB(192,64,0),b
Line bomb, (10,10)-(21,21),RGB(170,56,0),b
Line bomb, (11,11)-(20,20),RGB(144,32,0),b

Line hline, (0,0)-(31,0),RGB(144,32,0)
Line hline, (0,1)-(31,1),RGB(170,56,0)
Line hline, (0,2)-(31,2),RGB(192,64,0)
Line hline, (0,3)-(31,3),RGB(168,48,0)
Line hline, (0,4)-(31,4),RGB(128,24,0)
Line hline, (0,5)-(31,5),RGB(80,16,0)

Line vline, (0,0)-(0,31),RGB(144,32,0)
Line vline, (1,0)-(1,31),RGB(170,56,0)
Line vline, (2,0)-(2,31),RGB(192,64,0)
Line vline, (3,0)-(3,31),RGB(168,48,0)
Line vline, (4,0)-(4,31),RGB(128,24,0)
Line vline, (5,0)-(5,31),RGB(80,16,0)

For x = 0 To 31 Step 2
	Line backtile,(0+x,0+x)-(31,0+x),RGB(0,60-x*2,165-x*5)
	Line backtile,(0+x,1+x)-(0+x,31),RGB(0,60-x*2,165-x*5)
Next x

' drawing background...:
screenlock
For y = 1 To 16
	cola=RGB(0+y*0,0+y*4,0+y*11)
	colb=RGB(0+y*0,0+y*5,0+y*10)
	For x = y - 292 To 900 Step 24
		Line (x-300,0)-(x+300,600),cola
		Line (x-300,600)-(x+300,0),colb
	Next x
Next y

Line (48,35)-(337,516),RGB(0,24,64),b

' ...and drawing the "welcome" screen:
Get(337,36)-(384,515),fadeout
drawbox (49,36,505,515)
Draw String (193,75),"L A S E R   P I P E S",brightred
Draw String (249,95),"by Mlok",red
Draw String (65,125),"The goal of this game is to arrange the falling tiles", text
Draw String (77,145),"so that the lines inside the tiles match. Once you", text
Draw String (85,165),"manage to put at least four lines in a row, they", text 
Draw String (157,185),"disappear, raising your score.", text 
Draw String (61,205),"The more lines are in the row, the higher is the score", text
Draw String (57,225),"bonus. Additionally, if the disappearing row is the one", text
Draw String (69,245),"shown in BONUS tile, your score increase is doubled.", text
Draw String (241,275),"Controls:",brighttext
Draw String (73,295),"RIGHT/LEFT ARROW - Move the falling tile right/left", text
Draw String (141,315),"UP ARROW - rotate the falling tile", text
Draw String (85,335),"DOWN ARROW - drop the falling tile on the ground", text
Draw String (221,355),"P - pause game", text
Draw String (217,450),"<Enter to play>",brightred
Draw String (225,470),"<Esc to Quit>",red
screenunlock

Do
	keypressed = InKey
	If keypressed = Chr(13) Then Exit do
	If keypressed = Chr(255)+"k" Or keypressed = Chr(27) Then GoTo quit
	Sleep 10
Loop 

screenlock
Put (337,36),fadeout,pset

' drawing the info-box on the right:
drawbox (385,36,505,515)
Draw String (425,75),"LEVEL", red
Draw String (425,180),"SCORE", red
Draw String (409,285),"NEXT TILE", red
Draw String (425,390),"BONUS", red

Line (427,313)-(462,348),RGB(0,52,130),b
Line (425,311)-(464,350),RGB(0,40,100),b
Line (423,309)-(466,352),RGB(0,28,70),b
Line (427,418)-(462,453),RGB(0,52,130),b
Line (425,416)-(464,455),RGB(0,40,100),b
Line (423,414)-(466,457),RGB(0,28,70),b

' generating initial NEXTTILE:
Nexttile = 0
For x = 0 To 3
	If Fix(Rnd*2) = 1 Then nexttile = nexttile Or (1 Shl (x*2))
Next x

' drawing the main game board:
For x = 1 To 7
	For y = 0 To 14
		Put(x*32+49, y*32+36), backtile, PSet
	Next y
Next x

For y = 0 To 14
	Put(49, y*32+36), basetile, PSet
	Put(305, y*32+36), basetile, PSet
Next y
ScreenUnLock

' starting the stopwatch:
speedtime = timer
/'
Now we are entering the main loop and will never come back above again. It is good
time to say something about the STATEs. Most of the time, the STATE = 0 and the loop
is just making rounds doing nothing more then watching for user's input and the time.
When something happens, the STATE changes and the program reacts accordingly.
	Though I admit that may be not ideal for a little game like this, I liked this
concept and wanted to use it even though I've only some 3 states of which one is huge,
and the rests are quite miniature. In the other hand, this kind of core is good for
the game's future expansion, as new states are quite easy to add.
	Here is the list of special STATEs which are currently in use:

If STATE = 1 Then the falling tile just landed and it is necessary to check for
	long-enough pipes and also to create a new current tile. If the long-enoug pipes
	are found, they dissappear. If a whole tile disappear, it is also necessary to
	check if there are some other tiles on top of it, and if that is true, bring them
	down and do the whole check for pipes again. And of course, rise the score properly.
	The check if the game is on its end is here too.
		As you can see, lot of things are happening here and the code of this section is
	probably more than half of the whole program. I could've broken it in some SUBs or
	FUNCTIONs, but I don't like to do that with code which is used only in one place of
	the program, so.. it is like this, for now.

If STATE = 2 Then... nothing. This poor state was abondoned during the development.

If STATE = 3 Then the user pressed left or right arrow key and it is time to shift the
	current tile accordingly.
	
If STATE = 4 Then the TIMER reached the time stored in SPEEDTIME + SPEED, which means
	 that it is necessary to move the current tile one position lower.   
'/
Do
	keypressed = Inkey

	Select Case state

		Case 1
' So here we go. A tile just landed and this is what we do:
' Update the CHART array with the current tile:
			chart(ctilex,ctiley) = ctile

			' This is a loop for both checking for long-enough pipes, raising the score,
			' clearing CHART, as well as the screen, from the disappearing pipes and
			' subsequent shifting of the rest of the tiles on the screen down,
			' if necessary.
			Do
				stopcheck = 1

				' Now we look for the horizontal pipes:
				For y = 0 To 14
					counter(0) = 0
					counter(1) = 0
					For x = 0 To 8

						If chart(x,y) And 1 Then
							counter(0) += 1
						Else
							If counter(0) >= 4 Then score += ((counter(0) + counter(0)^2)/2) * bonus(0)
							counter(0) = 0
						End If

						If chart(x,y) And (1 Shl 4) Then
							counter(1) += 1
						Else
							If counter(1) >= 4 Then score += ((counter(1) + counter(1)^2)/2) * bonus(1)
							counter(1) = 0
						EndIf
						
						If x = 8 Then
							If counter(0) >= 4 Then score += ((counter(0) + counter(0)^2)/2) * bonus(0)
							If counter(1) >= 4 Then score += ((counter(1) + counter(1)^2)/2) * bonus(1)
						EndIf
						
						If counter(0) = 4 Then
							stopcheck = 0
							chart(x-3,y) = chart(x-3,y) And Not 1
							chart(x-2,y) = chart(x-2,y) And Not 1
							chart(x-1,y) = chart(x-1,y) And Not 1
							chart(x,y) = chart(x,y) And Not 1
						End If

						If counter(1) = 4 Then
							stopcheck = 0
							chart(x-3,y) = chart(x-3,y) And Not (1 Shl 4)
							chart(x-2,y) = chart(x-2,y) And Not (1 Shl 4)
							chart(x-1,y) = chart(x-1,y) And Not (1 Shl 4)
							chart(x,y) = chart(x,y) And Not (1 Shl 4)
						EndIf

						If counter(0) >= 5 Then
							chart(x,y) = chart(x,y) And Not 1
						EndIf

						If counter(1) >= 5 Then
							chart(x,y) = chart(x,y) And Not (1 Shl 4)
						EndIf

					Next x
				Next y

				' Now we look for the vertical pipes:
				For x = 0 To 8
					counter(2) = 0
					counter(3) = 0
					For y = 0 To 14

						If chart(x,y) And (1 Shl 2) Then
							counter(2) += 1
						Else
							If counter(2) >= 4 Then score += ((counter(2) + counter(2)^2)/2) * bonus(2)
							counter(2) = 0
						End If
						
						If chart(x,y) And (1 Shl 6) Then
							counter(3) += 1
						Else
							If counter(3) >= 4 Then score += ((counter(3) + counter(3)^2)/2) * bonus(3)
							counter(3) = 0
						EndIf

						If y = 14 Then
							If counter(2) >= 4 Then score += ((counter(2) + counter(2)^2)/2) * bonus(2)
							If counter(3) >= 4 Then score += ((counter(3) + counter(3)^2)/2) * bonus(3)
						EndIf
						
						If counter(2) = 4 Then
							stopcheck = 0
							chart(x,y-3) = chart(x,y-3) And Not (1 Shl 2)
							chart(x,y-2) = chart(x,y-2) And Not (1 Shl 2)
							chart(x,y-1) = chart(x,y-1) And Not (1 Shl 2)
							chart(x,y) = chart(x,y) And Not (1 Shl 2)
						End If

						If counter(3) = 4 Then
							stopcheck = 0
							chart(x,y-3) = chart(x,y-3) And Not (1 Shl 6)
							chart(x,y-2) = chart(x,y-2) And Not (1 Shl 6)
							chart(x,y-1) = chart(x,y-1) And Not (1 Shl 6)
							chart(x,y) = chart(x,y) And Not (1 Shl 6)
						EndIf

						If counter(2) >= 5 Then
							chart(x,y) = chart(x,y) And Not (1 Shl 2)
						EndIf

						If counter(3) >= 5 Then
							chart(x,y) = chart(x,y) And Not (1 Shl 6)
						EndIf

					Next y
				Next x

				If stopcheck = 1 Then
					' If STOPCHECK = 1, it means that no long-enough lines were found, so
					' we can update the score on the screen and exit the checking loop. 
					Line (400,210)-(490,226), RGB(0,16,40),bf
					Draw String (445-4*Len(Str(score)),210),Str(score), brightred	
					Exit Do
				EndIf

				' This is where the found long-enough pipes fade out off the screen.
				Get (49,36)-(336,515), fadeout
				For y = 0 To 14
					For x = 1 To 7
						If chart(x,y) = 0 Then
							Get backtile,(0,0)-(31,31), tile
						Else
							Get basetile,(0,0)-(31,31), tile
							tile = drawlines(tile,chart(x,y))
						EndIf
						Put fadeout,(x*32,y*32), tile, PSet
					Next x
				Next y

				For x = 1 To 20
					Put (49,36),fadeout, alpha, 16
					Sleep 12
				Next x
				Put (49,36),fadeout, PSet
				
				' Here the remaining tiles with pipes are piled down, if they have 
				' some space under themselves:
				ScreenLock
				For x = 1 To 7
					z = 0
					For y = 14 To 0 Step -1
						If chart(x,y) <> 0 Then
							If y < 14-z Then
								chart(x,14-z) = chart(x,y)
								chart(x,y) = 0
								Put(x*32 + 49, y*32 + 36), backtile, PSet
								Get basetile,(0,0)-(31,31), tile
								tile = drawlines(tile,chart(x,14-z))
								Put(x*32 + 49, (14-z)*32 + 36), tile, PSet
							EndIf
						z += 1
						EndIf
					Next y
				Next x
				ScreenUnLock
			Loop

' Now let's initialize the new current tile:
			ctiley = 0

			' If the last tile was dropped on the ground using the down arrow, this will
			' set the speed back to normal:
			If fall = 1 Then
				swap speed, fallspeed
				fall = 0
			End If

			ctile = nexttile
			
			' If there is alredy a tile on the place where the new tile should appear,
			' the game is over.
			If chart(ctilex, ctiley) <> 0 Then
				drawbox (49,36,336,515)
				Draw String (192-4*Len("You reached level "+Str(level)),200),"You reached level "+Str(level), red
				Draw String (192-4*Len("With score " + Str(score)),250),"With score " + Str(score), brightred
				Draw String (112,430),"<Enter to play again>", brighttext
				Draw String (140,460),"<Esc to quit>", text 
 
				Do
					keypressed = InKey
					If keypressed = Chr(13) Then
						' setting up new game:
						' - clear the CHART
						For x = 1 To 7
							For y = 0 To 14
								chart(x,y) = 0
							Next y
						Next x
						' - clear the board
						screenlock
						For x = 1 To 7
							For y = 0 To 14
								Put(x*32+49, y*32+36), backtile, PSet
							Next y
						Next x
						For y = 0 To 14
							Put(49, y*32+36), basetile, PSet
							Put(305, y*32+36), basetile, PSet
						Next y
						ScreenUnLock
						' - reintialize some variables
						ctiley = 15
						ctilex = 4
						score = 0
						level = 0
						state = 1
						tilecount = 35
						changex = 0
						speed = 0.8
						speedtime = timer
						' - Exit SELECT into the main loop  
						Exit select
					EndIf 
					
					If keypressed = Chr(27) Or keypressed = Chr(255)+"k" Then Exit do
					Sleep 10
				Loop
				
				Exit Do
			EndIf

			' set and display the bonus pipe:
			For x = 0 To 3
				bonus(x) = 1	
			Next x
			x = Fix(Rnd*4)
			bonus(x) = 2
						
			Get basetile,(0,0)-(31,31), tile
			Select Case x
				Case 0
					tile = drawlines(tile,1)
				Case 1
					tile = drawlines(tile,1 Shl 4)
				Case 2
					tile = drawlines(tile,1 Shl 2)
				Case 3
					tile = drawlines(tile,1 Shl 6)
			End Select
			Put(429,420),tile, PSet
			
			' set and display the new NEXTTILE:
			nexttile = 0
			For x = 0 To 3
				If Fix(Rnd*2) = 1 Then nexttile = nexttile Or (1 Shl (x*2))
			Next x
			
			If nexttile = 0 Then Get bomb,(0,0)-(31,31), tile Else Get basetile,(0,0)-(31,31), tile
			tile = drawlines(tile,nexttile)
			Put(429,315),tile, PSet

			' display the current tile on the top:
			If ctile = 0 Then Get bomb,(0,0)-(31,31), tile Else Get basetile,(0,0)-(31,31), tile
			tile = drawlines(tile,ctile)
			Put(ctilex*32 + 49, ctiley*32 + 36), tile, PSet

			' increase the TILECOUNT and check if it isn't enough for the next level:
			tilecount += 1
			If tilecount = 36 + level*4 Then
				level += 1
				' draw the level announcement box: 
				Get (143,192)-(243,232),fadeout
				drawbox(143,192,243,232)
				Draw string (194-4*Len("Level "+Str(level)),209),"Level " + Str(level), brightred
				While InKey = "":Wend
				For x = 1 To 20
					Put (143,192),fadeout, alpha, 16
					Sleep 12
				Next x
				Put (143,192),fadeout, PSet 							
				
				tilecount = 0
				
				' update the speed accordingly to the level:
				speed -= 0.6/(level+4)
				If speed < 0.08 Then speed = 0.08 				
				
				Line (400,105)-(490,121), RGB(0,16,40),bf
				Draw String (445-4*Len(Str(level)),105),Str(level),brightred
				EndIf 
			state = 0
			speedtime = Timer

		Case 4
			' if we are here, it means it is time to move the current tile down by one. 
			If ctiley = 14 Or chart(ctilex,ctiley+1) <> 0 Then
				' Here we check if the tile isn't alredy on top of some other tile or on
				' the ground. If that is true, STATE changes to 1.
				' If the tile is a bomb, it is handled accordingly.   
				state = 1
				If ctile = 0 Then
					Put(ctilex*32 + 49, ctiley*32 + 36), backtile, PSet
					ctiley += 1
					If ctiley = 15 Then ctiley = 14
						Put(ctilex*32 + 49, ctiley*32 + 36), tile, PSet
						screenunlock
						For x = 1 To 20
							Sleep 12
							Put(ctilex*32 + 49, ctiley*32 + 36), backtile, alpha, 16
						Next x
						Put(ctilex*32 + 49, ctiley*32 + 36), backtile, PSet
				EndIf
				speedtime = Timer
				Exit Select
			End If
			' update the tile position on the screen: 
			screenlock
			Put(ctilex*32 + 49, ctiley*32 + 36), backtile, PSet
			ctiley += 1
			Put(ctilex*32 + 49, ctiley*32 + 36), tile, PSet
			screenunlock
			state = 0
			
		Case 3
			' right/left arrow was pressed.. no big deal..
			screenlock
			Put(ctilex*32 + 49, ctiley*32 + 36), backtile, PSet
			ctilex = ctilex + changex
			Put(ctilex*32 + 49, ctiley*32 + 36), tile, PSet
			screenunlock
			state = 0
	
	End Select

	If state = 0 Then
		' user input business:
		Select Case keypressed

			Case Chr(255) + "M"
				' right arrow...
				If ctilex = 7 Then Exit Select
				If chart(ctilex+1, ctiley) <> 0 Then Exit Select
				changex = 1
				state = 3

			Case Chr(255) + "K"
				' left arrow...
				If ctilex = 1 Then Exit Select
				If chart(ctilex-1, ctiley) <> 0 Then Exit Select
				changex = -1
				state = 3

			Case Chr(255) + "H"
				' up arrow: rotate the pipes in the current tile
				temptile = ctile
				ctile = 0
				If temptile And 1 Then ctile = ctile Or (1 Shl 2)
				If temptile And (1 Shl 2) Then ctile = ctile Or (1 Shl 4)
				If temptile And (1 Shl 4) Then ctile = ctile Or (1 Shl 6)
				If temptile And (1 Shl 6) Then ctile = ctile Or 1
				
				If ctile <> 0 Then
					Get basetile,(0,0)-(31,31), tile
				Else
					Get bomb,(0,0)-(31,31), tile
				EndIf
				tile = drawlines(tile,ctile)
				Put(ctilex*32 + 49, ctiley*32 + 36), tile, PSet

			Case Chr(255) + "P"
				' down arrow: drop the tile on the ground (or stop the fall if a tile is 
				' alredy falling)
				If fall = 0 Then fall = 1 Else fall = 0
				swap speed, fallspeed
			
			Case "p", "P"
				' pause game
				Get (49,36)-(336,515), fadeout
				drawbox (49,36,336,515)
				Draw String (156,200),"P A U S E",RGB(192,0,0)
				Draw String (108,260),"<any key to continue>",RGB(0,48,144)
				
				do
				keypressed = InKey
				If keypressed = Chr(255)+"k" Then GoTo quit
				If keypressed <> "" Then Exit do
				Sleep 10
				loop
				
				Put (49,36),fadeout, PSet
				speedtime = Timer
		End Select
	End If

	' check if it is not the time to move tha current tile 
	If Timer - speedtime >= speed Then
		speedtime = Timer
		state = 4
	End If

	Sleep 1

Loop Until keypressed = Chr(27) Or keypressed = Chr(255)+"k"

quit:

ImageDestroy tile
ImageDestroy backtile
ImageDestroy basetile
ImageDestroy bomb
ImageDestroy hline
ImageDestroy vline
ImageDestroy fadeout

End

Function drawlines (tile As Any Ptr, ctile As Byte) As Any Ptr
' this function returns a tile on which pipes specified by CTILE are drawn.
	If ctile And 1 Then Put tile,(0,6), hline, PSet
	If ctile And (1 Shl 4) Then Put tile,(0,20), hline, PSet
	If ctile And (1 Shl 2) Then Put tile,(20,0), vline, PSet
	If ctile And (1 Shl 6) Then Put tile,(6,0), vline, PSet
	Return tile
End Function

Sub drawbox (x1 As Integer, y1 As Integer ,x2 As Integer ,y2 As Integer)
' this sub (surprise) draws a box :-p
	Line (x1,y1)-(x2,y2),RGB(0,64,160),b
	Line (x1+1,y1+1)-(x2-1,y2-1),RGB(0,16,40),bf
	Line (x1+2,y1+2)-(x2-2,y2-2),RGB(0,52,130),b
	Line (x1+4,y1+4)-(x2-4,y2-4),RGB(0,40,100),b
	Line (x1+6,y1+6)-(x2-6,y2-6),RGB(0,28,70),b
End Sub
Post Reply