April 24, 2024, 01:44:28 AM

News:

IonicWind Snippit Manager 2.xx Released!  Install it on a memory stick and take it with you!  With or without IWBasic!


It's Amazing

Started by GWS, February 19, 2010, 10:08:03 AM

Previous topic - Next topic

0 Members and 1 Guest are viewing this topic.

GWS

February 19, 2010, 10:08:03 AM Last Edit: February 22, 2010, 10:19:23 AM by GWS
Hi folks,

I thought I'd post this in case anyone else finds the same problem ..  :)

I was trying an example program to illustrate the 'GetKeyState' command for an upcoming addition to my user guide series.

So I wrote this little Maze program, and found I needed to know when the marker collided with the walls of the maze.


Rather than try to use x,y co-ordinates for this, I decided to detect when the colour of the walls was found in a 'GetPixel' command.


To my surprise, the marker just went straight through the walls ..  

I found after a bit of research, that the GetPixel command works in Blue, Green, Red values - not Red, Green, Blue.

You can prove this by using GetPixel on a known colour area, and calculating:


col = GETPIXEL(w, x, y )
red = (col & 0x0000ff)
green = (col & 0x00ff00) / 256
blue = (col & 0xff0000) / 65536


You will find the r,g,b components are reversed.

Once that little snag was overcome by testing for the reverse colour, the program then turned out as follows ..


' GWS Feb 2010
' Creative Basic Code

' (use the arrow keys to move the marker)

def w:window
def TicksPerSecond,run:int
def sw,sh,gametime,mwid,nmaze:int
def posy,mcol,rcol,scol:int
def markspeed:float
def markx,marky,dt,ts:float
def a$:string

declare "kernel32",GetTickCount(),int

type maze
def x:int
def y:int
def wid:int
def hgt:int
endtype

def m[110]:maze

autodefine "off"

sw = 1024 :' screen width
sh = 768 :' screen height

window w,0,0,sw,sh,@NOAUTODRAW|@MINBOX|@MAXBOX|@SIZE,0,"Maze",mainwindow
centerwindow w

' define a Button control ..
control w, "B,Exit, (1024 - 70)/2, 650, 70, 30, @ctlbtnflat, 1"
setcontrolcolor w, 1, 0, rgb(120,140,220)
' create a DX screen ..
if CREATESCREEN(w,sw,sh) < 0
messagebox w, "Could not create DirectX screen","Error"
closewindow w
end
endif

' game timing ..
TicksPerSecond = 40 :' number of frames per second
ts = 1.0 / TicksPerSecond :' game frame interval (sec)
dt = 1000.0 * ts :' game update interval (msec)

drawmode w,@TRANSPARENT

launch

run = 1
waituntil run = 0
stoptimer w
closewindow w
END

mainwindow:
select @CLASS
  case @IDCLOSEWINDOW
    run = 0
case @IDKEYDOWN
if (@code = 0x1B) then run = 0 :' Escape key ends game
case @IDCONTROL
if (@controlid = 1) then run = 0

  case @IDDXUPDATE
dxfill w,rgb(20,100,200)
' display main text ..
setfont w, "Arial", 20, 700, @sfitalic
frontpen w,RGB(180,180,250)
move w, 350,20
print w, "Navigate out of the Maze"

' draw the maze ..
' horizontal lines ..
for i = 1 to 52
rect w,m[i].x,m[i].y,m[i].wid,m[i].hgt,mcol,mcol
next i
' vertical lines ..
for i = 60 to 109
rect w,m[i].x,m[i].y,m[i].wid,m[i].hgt,mcol,mcol
next i

' temporary design grid lines ..
'for i = 1 to 18
' line w,100,100 + (i-1)*30,920,100+(i-1)*30,rgb(0,180,180)
'next i
'for i = 1 to 30
' line w,120+(i-1)*27,80,120+(i-1)*27,640,rgb(0,180,180)
'next i

' update the game status ..
update

DXFLIP w

endselect
RETURN


sub update
' update game status every 'dt' msec ..
if (GetTickCount() - gametime > dt)

' check for collision with the maze walls ..
' look 5 px ahead, allowing for the marker size of 10 px ..
' Note: The GetPixel function works in 'b,g,r' format, so test for the reversed colours in 'rcol'
' which are the reverse of the actual 'r,g,b' colour.
if getkeystate(0x27) :' move right
if (GETPIXEL(w, markx + 15, marky) <> rcol) & (GETPIXEL(w, markx + 15, marky + 10) <> rcol)
if (markx < (sw - 25)) then markx = markx + markspeed * dt
endif
endif

if getkeystate(0x25) :' move left
if (GETPIXEL(w, markx - 5, marky) <> rcol) & (GETPIXEL(w, markx -5, marky + 10) <> rcol)
if (markx > 15) then markx = markx - markspeed * dt
endif
endif

if getkeystate(0x26) :' move Up
if (GETPIXEL(w, markx, marky - 5) <> rcol) & (GETPIXEL(w, markx + 10, marky - 5) <> rcol)
if (marky > 15) then marky = marky - markspeed * dt
endif
endif

if getkeystate(0x28) :' move down
if (GETPIXEL(w, markx, marky + 15) <> rcol) & (GETPIXEL(w, markx + 10, marky + 15) <> rcol)
if (marky < (sh - 25)) then marky = marky + markspeed * dt
endif
endif

rect w,markx,marky,10,10,rgb(20,200,20),rgb(20,200,20)

endif

return

sub launch
' routine to launch a new game ..

'set intial values
markx = 508 :' marker starting x position
marky = 365 :' marker starting y position
markspeed = 0.1 :' marker speed

' set maze parameters ..
nmaze = 90
mcol = rgb(50,50,80) :' maze wall colour in r,g,b format

' set a test pixel at x=0, y=0 to the maze colour.
pset w,0,0,mcol
' read it back to check user's colour settings in Windows (16,24 or 32 bit) ..
scol = getpixel(w,0,0)
' and use this as the reverse colour for GetPixel to check as being the wall colour.
rcol = scol

' horizontal walls ..
m[1].x = 120 : m[1].y = 100 : m[1].wid = 378
m[2].x = 525 : m[2].y = 100 : m[2].wid = 380
m[3].x = 148 : m[3].y = 130 : m[3].wid = 268
m[4].x = 445 : m[4].y = 130 : m[4].wid = 295
m[5].x = 768 : m[5].y = 130 : m[5].wid = 110
m[6].x = 175 : m[6].y = 160 : m[6].wid = 215
m[7].x = 445 : m[7].y = 160 : m[7].wid = 268
m[8].x = 795 : m[8].y = 160 : m[8].wid = 80
m[9].x = 255 : m[9].y = 190 : m[9].wid = 163
m[10].x = 473 : m[10].y = 190 : m[10].wid = 240
m[11].x = 823 : m[11].y = 190 : m[11].wid = 27
m[12].x = 283 : m[12].y = 220 : m[12].wid = 243
m[13].x = 580 : m[13].y = 220 : m[13].wid = 108
m[14].x = 795 : m[14].y = 220 : m[14].wid = 28
m[15].x = 310 : m[15].y = 250 : m[15].wid = 188
m[16].x = 553 : m[16].y = 250 : m[16].wid = 108
m[17].x = 770 : m[17].y = 250 : m[17].wid = 80
m[18].x = 120 : m[18].y = 280 : m[18].wid = 80
m[19].x = 284 : m[19].y = 280 : m[19].wid = 80
m[20].x = 418 : m[20].y = 280 : m[20].wid = 243
m[21].x = 768 : m[21].y = 280 : m[21].wid = 80
m[22].x = 148 : m[22].y = 310 : m[22].wid = 90
m[23].x = 312 : m[23].y = 310 : m[23].wid = 80
m[24].x = 446 : m[24].y = 310 : m[24].wid = 50
m[25].x = 525 : m[25].y = 310 : m[25].wid = 55
m[26].x = 795 : m[26].y = 310 : m[26].wid = 88
m[27].x = 174 : m[27].y = 340 : m[27].wid = 216
m[28].x = 472 : m[28].y = 340 : m[28].wid = 80
m[29].x = 765 : m[29].y = 340 : m[29].wid = 148
m[30].x = 202 : m[30].y = 370 : m[30].wid = 162
m[31].x = 660 : m[31].y = 370 : m[31].wid = 216
m[32].x = 175 : m[32].y = 400 : m[32].wid = 160
m[33].x = 467 : m[33].y = 400 : m[33].wid = 30
m[34].x = 528 : m[34].y = 400 : m[34].wid = 30
m[35].x = 688 : m[35].y = 400 : m[35].wid = 160
m[36].x = 202 : m[36].y = 430 : m[36].wid = 52
m[37].x = 310 : m[37].y = 430 : m[37].wid = 52
m[38].x = 440 : m[38].y = 430 : m[38].wid = 145
m[39].x = 418 : m[39].y = 460 : m[39].wid = 215
m[40].x = 392 : m[40].y = 490 : m[40].wid = 106
m[41].x = 553 : m[41].y = 490 : m[41].wid = 106
m[42].x = 335 : m[42].y = 520 : m[42].wid = 135
m[43].x = 528 : m[43].y = 520 : m[43].wid = 158
m[44].x = 768 : m[44].y = 520 : m[44].wid = 55
m[45].x = 173 : m[45].y = 550 : m[45].wid = 60
m[46].x = 310 : m[46].y = 550 : m[46].wid = 53
m[47].x = 418 : m[47].y = 550 : m[47].wid = 270
m[48].x = 768 : m[48].y = 550 : m[48].wid = 82
m[49].x = 148 : m[49].y = 580 : m[49].wid = 110
m[50].x = 310 : m[50].y = 580 : m[50].wid = 188
m[51].x = 525 : m[51].y = 580 : m[51].wid = 350
m[52].x = 125 : m[52].y = 610 : m[52].wid = 780

for i = 1 to 52
m[i].hgt = 10
next i

' vertical walls ..
m[60].x = 120 : m[60].y = 100 : m[60].hgt = 520
m[61].x = 903 : m[61].y = 100 : m[61].hgt = 520
m[62].x = 147 : m[62].y = 130 : m[62].hgt = 160
m[63].x = 174 : m[63].y = 160 : m[63].hgt = 120
m[64].x = 201 : m[64].y = 190 : m[64].hgt = 100
m[65].x = 228 : m[65].y = 160 : m[65].hgt = 150
m[66].x = 412 : m[66].y = 130 : m[66].hgt = 70
m[67].x = 255 : m[67].y = 190 : m[67].hgt = 130
m[68].x = 283 : m[68].y = 230 : m[68].hgt = 90
m[69].x = 385 : m[69].y = 260 : m[69].hgt = 60
m[70].x = 442 : m[70].y = 160 : m[70].hgt = 60
m[71].x = 520 : m[71].y = 220 : m[71].hgt = 60
m[72].x = 553 : m[72].y = 200 : m[72].hgt = 50
m[73].x = 683 : m[73].y = 220 : m[73].hgt = 122
m[74].x = 710 : m[74].y = 190 : m[74].hgt = 152
m[75].x = 736 : m[75].y = 130 : m[75].hgt = 248
m[76].x = 765 : m[76].y = 130 : m[76].hgt = 130
m[77].x = 793 : m[77].y = 160 : m[77].hgt = 70
m[78].x = 843 : m[78].y = 190 : m[78].hgt = 70
m[79].x = 873 : m[79].y = 160 : m[79].hgt = 150
m[80].x = 765 : m[80].y = 280 : m[80].hgt = 60
m[81].x = 467 : m[81].y = 340 : m[81].hgt = 60
m[82].x = 548 : m[82].y = 340 : m[82].hgt = 60
m[83].x = 440 : m[83].y = 310 : m[83].hgt = 120
m[84].x = 575 : m[84].y = 310 : m[84].hgt = 120
m[85].x = 147 : m[85].y = 310 : m[85].hgt = 275
m[86].x = 173 : m[86].y = 340 : m[86].hgt = 215
m[87].x = 198 : m[87].y = 430 : m[87].hgt = 95
m[88].x = 248 : m[88].y = 430 : m[88].hgt = 155
m[89].x = 223 : m[89].y = 460 : m[89].hgt = 95
m[90].x = 277 : m[90].y = 400 : m[90].hgt = 220
m[91].x = 307 : m[91].y = 430 : m[91].hgt = 130
m[92].x = 332 : m[92].y = 460 : m[92].hgt = 70
m[93].x = 385 : m[93].y = 520 : m[93].hgt = 70
m[94].x = 385 : m[94].y = 340 : m[94].hgt = 160
m[95].x = 493 : m[95].y = 490 : m[95].hgt = 60
m[96].x = 523 : m[96].y = 460 : m[96].hgt = 70
m[97].x = 358 : m[97].y = 370 : m[97].hgt = 130
m[98].x = 413 : m[98].y = 280 : m[98].hgt = 190
m[99].x = 602 : m[99].y = 280 : m[99].hgt = 160
m[100].x = 628 : m[100].y = 310 : m[100].hgt = 160
m[101].x = 655 : m[101].y = 280 : m[101].hgt = 220
m[102].x = 682 : m[102].y = 400 : m[102].hgt = 130
m[103].x = 710 : m[103].y = 430 : m[103].hgt = 160
m[104].x = 737 : m[104].y = 405 : m[104].hgt = 155
m[105].x = 763 : m[105].y = 430 : m[105].hgt = 100
m[106].x = 790 : m[106].y = 400 : m[106].hgt = 95
m[107].x = 817 : m[107].y = 430 : m[107].hgt = 100
m[108].x = 845 : m[108].y = 400 : m[108].hgt = 160
m[109].x = 873 : m[109].y = 370 : m[109].hgt = 220

for i = 60 to 109
m[i].wid = 10
next i

return



I'll include it in the user notes as well if I ever get them finished ..   :)

Graham

(Edit: Program modified to cater for user's Windows colour settings  ie. 16,24, or 32 bit colour)

Tomorrow may be too late ..

aurelCB

Graham your Maze looks great but marker rectangle goes trough maze wals.

GWS

Hi Aurel,

Just a guess, but I think you may not be set for 32-bit colour for Windows - the GetPixel function only returns the correct r,g,b values at the highest setting.  At lower settings, it chooses the nearest values it can - but they are unlikely to match.

That's one snag with using the colour detection method ..  :)

Here's an old query from the Pyxia forum:

__________________________________

My Colors Are Wrong ...

Hi Guys and Gals,

I've been trying to read color values from the screen, and I'm not getting 'accurate' rendition .. :(

Here's a test program:
_________________

def w:WINDOW
def wstyle,key:int
def col,red,green,blue,textW,textH:int
def a$:string

autodefine "OFF"

wstyle = @SIZE|@MINBOX|@MAXBOX

WINDOW w,50,50,500,400,wstyle,0,"Colour Test",handler
CONTROL w,"B, Exit, 210, 300, 70, 35, 0, 1"

'****************************************************
' change the color values to check the RGB result ..

SETWINDOWCOLOR w,RGB(20,10,150)

col = GETPIXEL(w, 380 ,10 )
red = (col & 0x0000ff)
green = (col & 0x00ff00) / 256
blue = (col & 0xff0000) / 65536

a$ = "RGB(" + str$(red)+","+str$(green)+","+str$(blue)+")"
frontpen w, RGB(255,255,255)
SETFONT w, "Times New Roman",14,500
GETTEXTSIZE w, a$, textW, textH
move w,(500-textW)/2,100
PRINT w,a$

'***************************************************

WAITUNTIL w = 0
END

SUB handler
SELECT @CLASS
   case @IDCLOSEWINDOW
CLOSEWINDOW w
   case @IDCHAR
   key = @CODE
      if key = 27 then CLOSEWINDOW w
   case @IDCONTROL
      select @CONTROLID
         case 1
            CLOSEWINDOW w
      endselect
ENDSELECT
RETURN
_________________

You will see that the pixel colors are not quite right .. can be 5 to 10% adrift .. Is this something other folk have noticed - a built in effect of pc graphics maybe ..

A bit more accurate would have been nice .. :)

Graham
_____________________________________________________

Graham,
Depends on your desktop settings. If you use a 16 or 24bit display then the colors are mapped to closest values by windows. The RGB statement specifies 32 bit color quantities 0-255. For a 16 bit screen this would get adjusted to 0-127 for each value.

When converting back Windows uses the reverse of the formula, which might be as simpe as dividing by 2 I suppose. It may be more complex than that as I remember something about color profiles for monitors and such.

Paul.

____________________________________________________

Paul,

Many thanks, you've hit the nail right on the head again as usual .. :)

I was running in 'High Color' 16 bit mode. If I change to 'Truecolor' 32 bit mode the results are exact.

That leaves me with an upcoming application which will work well in Truecolor, but not so well in High Color, depending on the user's settings - problems, problems ... :)

happy days,

Graham

____________________________________________

I hope that's the answer ..  ;D


all the best, :)

Graham
Tomorrow may be too late ..

aurelCB

Yes Graham you right i'm runing in 16bit mode always.
Ok i switch to 32bit and program work ;)
Yes this things looks problematic ::)

Blue Steel

thats why i've learned its better to use arrays or alike to store data in as opposed to the actual window co-ords as you never know what depth the user has setup. on some graphics cards they can't support 32 bit .. only 24 bit tops ..

I used to code on an old C64 where the pixels were always stored in a colour map area and used to use peeks / pokes to read and set them. but when i upgraded (a matter of opinion) to a true computer I learned never to assume anything.. and stored the color and content data in arrays as opposed to off the screen.
  http://www.codingmonkeys.com
Covers many languages including Aurora , IWBasicEbasic (Ebasic, IBasic) , Creative Basic

GWS

What .. ? .. you mean I need to find another solution ..  ;D

The colour one seemed so straightforward - until the snags pop up that is ..  ::)

The only other approach that comes to mind is a cell matrix with data saying wall or non-wall.

Then the marker has to test where it is, top - left - down and up to see if it can move or not.  Another tricky bit of logic needed methinks ..  :)

Hey, this was only supposed to be a throwaway example of using GetKeystate ..  :)  Nothing's easy ..

That makes maze tracing a pretty tricky application - and my daughter would like a button that says 'Click me for another Maze' ..  :o

Oh, yes - it took me ages to specify the layout of that one ..  ;D   An auto maze generator - yep, very interesting.

best wishes, :)

Graham
Tomorrow may be too late ..

ZeroDog

February 21, 2010, 02:22:59 PM #6 Last Edit: February 21, 2010, 02:40:32 PM by ZeroDog
"The only other approach that comes to mind is a cell matrix with data saying wall or non-wall."

I remember coming across these programs with my pacman clone that I wrote.  What I eventually ended up doing was rendering the maze as a sprite, and using sprite collision routines to determine if the user had run into the wall.


I have never used it personally  (all the cool kids are doing it!)  but you could play around with the GetNearestColor() API function in the GDI32.dll. 

GWS

Hi ZD ..  :)

Two great ideas .. thanks.  I never thought of making a big sprite out of it ..  ;D  I'll have to try that.

I should think it would be less work than specifying all those rectangle x,y,wid,hgt details.

I'd not come across the GetNearestColor() API function - that could well solve the problem as well.

You're full of good ideas ..  ;D ;D

best wishes, :)

Graham
Tomorrow may be too late ..

GWS

Hi folks,

It was easier than I'd thought ..  :)

Here's how:


' set a test pixel at x=0, y=0 to the maze colour.
pset w,0,0,mcol
' read it back to check user's colour settings in Windows (16, 24 or 32 bit) ..
scol = getpixel(w,0,0)
' and use this as the reverse colour for GetPixel to check as being the wall colour.
rcol = scol


Then, whatever colours the user's Windows settings are displaying, the readback will discover it, and use it to test the wall colour .. is that sneaky or what ?   ::)

I've updated the program listing to incorporate the change ..

best wishes, :)

Graham
Tomorrow may be too late ..

ZeroDog


celphick