Tasp
Full Member
Posts: 215
|
Post by Tasp on Jan 22, 2021 14:40:52 GMT -5
This code is part of a larger code base and so won't run as is, and yes I apologise immediately, I understand trying to help when the code won't even run or making the helper create files etc is an annoyance. But I can't see a way to include everything without changing the code so it wouldn't merge back into the existing code.
Having said that, their are some amazing coders in here, and the chances are they could see just by looking at the code.
-- The premise here is, when an alarm is received this mapping portion runs. It loads from a txt file the zonenumber, type, coords etc, then if a zonenumber is found it opens a window draws the background map image then calculates the centre of the window, moves the background to the zonenumber object then recalcualtes the positions of the obhects so they display correctly on the map. This all works fine, however.....
Because I'm calling the LoadObjects twice this is clearly slowing down the operation, even if there is a small amount of objects it's still loading the array twice, when you upscale this to 100+ objects it slows down considerably.
I've tried moving things around. But it always seems to be having to reload the arrays again. I know I'm missing something basic here.
There's also the problem I'm drawing objects that aren't even on screen. I'm not even sure where to start testing for that.
Any suggestions?
LOADBMP "image", Mapfile$ #1.g "down ; background image" #1.g "drawsprites"
z=1 'zone object assigned to type=2 'type of object x=3 'x y=4 'y w=5 'width of object h=6 'hight of object 'MaxIcons = 40 Icontype = 0 'IconSize = 40 'Reset found object var to 0 to start found = 0
#1.g "when leftButtonDouble coords"
call LoadObjects
'Search for zonenumber and display on map FOR findzone = 0 to objects IF VAL(EVENT$(CurrentPriorityAlarm,6)) = object(findzone,zone) THEN 'print "***MAP item found!"
'Collect object position from array objectposX = object(findzone, x) objectposY = object(findzone, y) 'Print "Start objectposX :"; objectposX ; " objectposY :" ; objectposY
'Collect Window dimensions then find the center centreWindowX = WindowWidth / 2 centreWindowY = WindowHeight / 2 'print "centreWindowX :"; centreWindowX ; " centreWindowY :" ;centreWindowY
'Calculate how much to move to center BGPX = (objectposX - centreWindowX) BGPY = (objectposY - centreWindowY)
'Reload objects with the new calculation info, so we move the objects with the BackGround CALL LoadObjects
'Print "BGPX: "; BGPX ; " BGPY: ";BGPY
'Move background #1.g "backgroundxy ";BGPX;" "; BGPY
'Draw object in the middle of the screen #1.g "drawsprites"
'print BGPX, BGPY, findzone #1.g "DRAWBMP activation ";object(findzone,x) - BGPX;" "; object(findzone, y) - BGPY RemoveActivationFromMap = 0 'This flag is for when the user clicks Acknowledge button, it renoves the activation bmp from screen #1.g "UP ; GOTO ";object(findzone,x) - BGPX + 60;" ";object(findzone, y) - BGPY ;" DOWN ; COLOR RED ; FONT Trebuchet 16" #1.g "\";object(findzone, zone) #1.g "\"; EVENT$(CurrentPriorityAlarm,9) #1.g "UP ; GOTO 10 20 ; DOWN ; COLOR YELLOW ; BACKCOLOR black ; FONT Trebuchet 16" #1.g "\INCIDENT: "; EVENT$(CurrentPriorityAlarm,2) #1.g "BACKCOLOR WHITE"
found = 1
'Values have to be ABSolute as if window is not the main display window, any display on the left will give negative numbers, 'this causes an error as the window right and bottom are negative values. #1.g "getbmp KeepIt 0 0 " ; ABS(WINDOWPLACEMENT.rcNormalPositionRight.struct) ; " " ; ABS(WINDOWPLACEMENT.rcNormalPositionBottom.struct) #1.g "drawbmp KeepIt 0 0 ; FLUSH" EXIT FOR END IF NEXT WAIT
SUB LoadObjects
OPEN mappath$ + mapID$ + ".txt" FOR INPUT AS #readFile objects=0 WHILE NOT(EOF(#readFile)) objects = objects + 1 INPUTCSV #readFile, a$, b$, c$, d$, e$, f$, g$, h$ object(objects,zone) = VAL(a$) object(objects,type) = VAL(b$) ' Icontype object(objects,x) = VAL(c$) ' x position object(objects,y) = VAL(d$) ' y position object(objects,w) = VAL(e$) object(objects,h) = VAL(f$) object(objects,7) = VAL(g$) object(objects,8) = VAL(h$) #1.g "addsprite s";objects;" i";object(objects,type) #1.g "spritexy s";objects;" ";object(objects,x) - BGPX;" ";object(objects,y) - BGPY WEND #1.g "drawsprites" CLOSE #readFile END SUB
|
|
|
Post by Brandon Parker on Jan 22, 2021 22:10:03 GMT -5
Any way we can get our hands on the current version? You can PM me if you want and I will provide an email address. It is, as you know, very difficult to understand what might be happening overall in the program from just the snippet.
{:0)
Brandon Parker
|
|
|
Post by Chris Iverson on Jan 22, 2021 23:44:42 GMT -5
Why are you reloading the array? From what I can tell, that's not even necessary. None of the calculations you make are actually saved in the array.
Also, you don't need to repeat the addsprite command if it's already been added.
For the second LoadObjects call, would you not be able to simply loop through the sprite array and reposition them all?
Like, something like this?
For i = 1 to objects #1.g "spritexy s";objects;" ";object(objects,x) - BGPX;" ";object(objects,y) - BGPY Next i #1.g "drawsprites"
You might have to make that objects counter global, if it's not already, but you won't have to needlessly parse the entire file all over again.
|
|
|
Post by Rod on Jan 23, 2021 4:43:12 GMT -5
Surely you only need to load the objects once and surely you only need to draw objects within the bounds of the centred map portion. So calculate the background position and so the display x and y offset. Then in load objects load them directly to their offset positions and ignore any that are outside the display limits. So you need the display centre then using the width and height calculate the lower x upper x and lower ya nd upper y that define the map portion on view.
|
|
|
Post by Rod on Jan 23, 2021 4:59:21 GMT -5
Kinda like this but untested.
LOADBMP "image", Mapfile$ #1.g "down ; background image" #1.g "drawsprites"
z=1 'zone object assigned to type=2 'type of object x=3 'x y=4 'y w=5 'width of object h=6 'hight of object 'MaxIcons = 40 Icontype = 0 'IconSize = 40 'Reset found object var to 0 to start found = 0
#1.g "when leftButtonDouble coords"
'call LoadObjects OPEN mappath$ + mapID$ + ".txt" FOR INPUT AS #readFile objects=0 WHILE NOT(EOF(#readFile)) objects = objects + 1 INPUTCSV #readFile, a$, b$, c$, d$, e$, f$, g$, h$ object(objects,zone) = VAL(a$) object(objects,type) = VAL(b$) ' Icontype object(objects,x) = VAL(c$) ' x position object(objects,y) = VAL(d$) ' y position object(objects,w) = VAL(e$) object(objects,h) = VAL(f$) object(objects,7) = VAL(g$) object(objects,8) = VAL(h$) close #readFile
'Search for zonenumber and display on map FOR findzone = 0 to objects IF VAL(EVENT$(CurrentPriorityAlarm,6)) = object(findzone,zone) THEN 'print "***MAP item found!"
'Collect object position from array objectposX = object(findzone, x) objectposY = object(findzone, y) 'Print "Start objectposX :"; objectposX ; " objectposY :" ; objectposY
'Collect Window dimensions then find the center centreWindowX = WindowWidth / 2 centreWindowY = WindowHeight / 2 'print "centreWindowX :"; centreWindowX ; " centreWindowY :" ;centreWindowY
'Calculate how much to move to center BGPX = (objectposX - centreWindowX) BGPY = (objectposY - centreWindowY)
'Move background #1.g "backgroundxy ";BGPX;" "; BGPY lowerlimitx=BGPX-500 upperlimitx=BGPX+500 lowerlimity=BGPY-500 upperlimity=BGPY+500 EXIT FOR END IF NEXT
'add the needed sprites FOR n = 0 to objects if object(n,x)>lowerlimitx and object(n,x)<upperlimitx and object(n,y)> lowerlimity and object(n,y)<upperlimity then #1.g "addsprite s";n;" i";object(n,type) #1.g "spritexy s";n;" ";object(n,x) - BGPX;" ";object(n,y) - BGPY end if next
'Draw object in the middle of the screen #1.g "drawsprites"
'print BGPX, BGPY, findzone #1.g "DRAWBMP activation ";object(findzone,x) - BGPX;" "; object(findzone, y) - BGPY RemoveActivationFromMap = 0 'This flag is for when the user clicks Acknowledge button, it renoves the activation bmp from screen #1.g "UP ; GOTO ";object(findzone,x) - BGPX + 60;" ";object(findzone, y) - BGPY ;" DOWN ; COLOR RED ; FONT Trebuchet 16" #1.g "\";object(findzone, zone) #1.g "\"; EVENT$(CurrentPriorityAlarm,9) #1.g "UP ; GOTO 10 20 ; DOWN ; COLOR YELLOW ; BACKCOLOR black ; FONT Trebuchet 16" #1.g "\INCIDENT: "; EVENT$(CurrentPriorityAlarm,2) #1.g "BACKCOLOR WHITE"
found = 1
'Values have to be ABSolute as if window is not the main display window, any display on the left will give negative numbers, 'this causes an error as the window right and bottom are negative values. #1.g "getbmp KeepIt 0 0 " ; ABS(WINDOWPLACEMENT.rcNormalPositionRight.struct) ; " " ; ABS(WINDOWPLACEMENT.rcNormalPositionBottom.struct) #1.g "drawbmp KeepIt 0 0 ; FLUSH"
WAIT
|
|
Tasp
Full Member
Posts: 215
|
Post by Tasp on Jan 23, 2021 11:22:33 GMT -5
Guys thanks so much for all your input and help.
I think in the early stages of development I was reloading it as that was the only way I could make it work.
I have now shifted things around as suggested and everything seems to function properly, with only reading the file once this has to be better. Fully changed code at the bottom.
I have 2 further queries though if I may?!
Question 1,
Within the full code (bottom) Rod has given a way to only display objects that will appear in the window. In his code he has given arbitrary values of 500, because the user is able to decide globally how much of the screen this map window will take these values have to be dynamic. So in this in mind I tried various ways to make these values correspond to the actual window width and height.
lowerlimitx=BGPX - (WindowWidth / 2) upperlimitx=BGPX + (WindowWidth / 2) lowerlimity=BGPY - (WindowHeight / 2) upperlimity=BGPY + (WindowHeight / 2)
This did not work, in my mind this should of.
I already use the GetWindowPlacement API call, so I tried using the info that provides;
'This is just here to show how I'm calling and Structs used. struct WINDOWPLACEMENT, length as ulong, flags as long, showCmd as long, ptMinPositionX as long, ptMinPositionY as long, ptMaxPositionX as long, ptMaxPositionY as long, rcNormalPositionLeft as long, rcNormalPositionTop as long, rcNormalPositionRight as long, rcNormalPositionBottom as long WINDOWPLACEMENT.length.struct = len(WINDOWPLACEMENT.struct)
Function GetWindowPlacement(hWnd) CallDLL #user32, "GetWindowPlacement", hWnd as ulong, WINDOWPLACEMENT as struct, GetWindowPlacement as long End Function
lowerlimitx=BGPX - WINDOWPLACEMENT.rcNormalPositionLeft.struct upperlimitx=BGPX + WINDOWPLACEMENT.rcNormalPositionRight.struct lowerlimity=BGPY - WINDOWPLACEMENT.rcNormalPositionTop.struct upperlimity=BGPY + WINDOWPLACEMENT.rcNormalPositionBottom.struct
This also failed. I have had issues before due to my monitor configuration, where my main monitor (1) is the centre, making (2) leftmost and (3) rightmost, putting the window on leftmost (2) gives negative values, so I added ABS aswell, however this didn't make a difference. Any suggestions?
Question 2,
With all the drawing/sprites/background changes, I'm aware this takes up memory, if that mapping window is left open all the constant drawing to it may cause issues. After trawling through various help pages and examples, it seems vague to me at least, which commands I should be issuing to clear the memory/screen. I believe just closing the window won't necessarily clear the graphics memory.
There is also an issue where it doesn't matter what commands I use it still leaves the previous objects on screen, despite it reloading the background/sprites. This may have been the first DrawSprites command, removed and it seems to be working I have the following code in an attempt to clear the screen and memory, but do I need them all? Edit: Doing some testing and after 80 events this puts LB at something like 350mb usage, so these clearing techniques aren't working. Closing the window, dropped it immeaditaly to 12.1mb
PRINT "Clearing Screen" #1.g, "CLS" 'Think this clears everything, but mainly used for MAINWIN #1.g, "DELSEGMENT KeepIt" 'Clears the KeepIT segment we drew earlier? #1.g, "DISCARD" 'Discards the sprites? DIM object(520,20) 'Also redimmming the array to clear out any left over objects, don't really want to do this here due to the speed impact
LOADBMP "image", Mapfile$ #1.g "down ; background image" '#1.g "drawsprites"
z=1 'zone object assigned to type=2 'type of object x=3 'x y=4 'y w=5 'width of object h=6 'height of object 'MaxIcons = 40 Icontype = 0 'IconSize = 40 'Reset found object var to 0 to start found = 0
#1.g "when leftButtonDouble coords"
'call LoadObjects OPEN mappath$ + mapID$ + ".txt" FOR INPUT AS #readFile objects=0
WHILE NOT(EOF(#readFile)) objects = objects + 1 INPUTCSV #readFile, a$, b$, c$, d$, e$, f$, g$, h$ object(objects,zone) = VAL(a$) object(objects,type) = VAL(b$) ' Icontype object(objects,x) = VAL(c$) ' x position object(objects,y) = VAL(d$) ' y position object(objects,w) = VAL(e$) object(objects,h) = VAL(f$) object(objects,7) = VAL(g$) object(objects,8) = VAL(h$) WEND CLOSE #readFile
'Search for zonenumber and display on map FOR findzone = 0 to objects IF VAL(EVENT$(CurrentPriorityAlarm,6)) = object(findzone,zone) THEN found = 1
'Collect object position from array objectposX = object(findzone, x) objectposY = object(findzone, y) 'Print "Start objectposX :"; objectposX ; " objectposY :" ; objectposY
'Collect Window dimensions then find the center centreWindowX = WindowWidth / 2 centreWindowY = WindowHeight / 2 'print "centreWindowX :"; centreWindowX ; " centreWindowY :" ;centreWindowY
'Calculate how much to move to center BGPX = (objectposX - centreWindowX) BGPY = (objectposY - centreWindowY)
'Move background #1.g "backgroundxy ";BGPX;" "; BGPY
'Define window sizes to display objects inside lowerlimitx=BGPX - (WindowWidth / 2) upperlimitx=BGPX + (WindowWidth / 2) lowerlimity=BGPY - (WindowHeight / 2) upperlimity=BGPY + (WindowHeight / 2) EXIT FOR END IF NEXT
IF found THEN 'add the needed sprites FOR n = 1 to objects IF object(n,x) > lowerlimitx and object(n,x) < upperlimitx and object(n,y) > lowerlimity and object(n,y) < upperlimity then #1.g "addsprite s";n;" i";object(n,type) #1.g "spritexy s";n;" ";object(n,x) - BGPX;" ";object(n,y) - BGPY END IF NEXT
'Draw object/sprite in the middle of the screen #1.g "drawsprites"
'Swap the found zone original icon for the activation icon #1.g "DRAWBMP "; ActivationType$ ; " " ; object(findzone,x) - BGPX;" "; object(findzone, y) - BGPY
'This flag is for when the user clicks Acknowledge button, it renoves the activation bmp from screen -- Unsure why this ended up inside this part? RemoveActivationFromMap = 0
'Draw Activation details to screen #1.g "UP ; GOTO ";object(findzone,x) - BGPX + 60;" ";object(findzone, y) - BGPY ;" DOWN ; COLOR RED ; FONT Trebuchet 16" #1.g "\";object(findzone, zone) #1.g "\"; EVENT$(CurrentPriorityAlarm,9)
'Draw site name in top left of screen #1.g "UP ; GOTO 10 20 ; DOWN ; COLOR YELLOW ; BACKCOLOR black ; FONT Trebuchet 16" #1.g "\INCIDENT: "; EVENT$(CurrentPriorityAlarm,2) #1.g "BACKCOLOR WHITE"
'Values have to be ABSolute as if window is not the main display window, any display on the left will give negative numbers, 'this causes an error as the window right and bottom are negative values. #1.g "GETBMP KeepIt 0 0 " ; ABS(WINDOWPLACEMENT.rcNormalPositionRight.struct) ; " " ; ABS(WINDOWPLACEMENT.rcNormalPositionBottom.struct) #1.g "DRAWBMP KeepIt 0 0 ; FLUSH" END IF
|
|
|
Post by Rod on Jan 23, 2021 13:14:38 GMT -5
Sprites don't consume memory. Drawing does, drawing multiple times even more so but not sure if you are. So it is your drawing that consumes memory, you are not using flush correctly, you need to name the segment and delete the named segment. So when you do your drawing end with flush namedsegment then head up the drawing routine with delsegment namedsegment. cls and discard are inappropriate. Why is it getting drawn more than once?
The box limits have nothing to do with the screen, they are to do with the the objects x,y vis a vie the alarm position. So perhaps use the alarm objects x,y +- windowwidth/2 windowheight/2 ?
|
|
Tasp
Full Member
Posts: 215
|
Post by Tasp on Jan 23, 2021 15:54:20 GMT -5
Ah I see. Name the flushes. There is only one FLUSH command in the entire program and that's within this snippet. I named the flush segment to match the draw and delsegment command. This now keeps it around 40mb when displaying the map. it jumps while creating to 100mb plus, but that's not an issue. I was concerned it was going to reach the 768mb limit very quickly. For thopse playing along at home, I changed this; #1.g "DRAWBMP KeepIt 0 0 ; FLUSH"
To this; #1.g "DRAWBMP KeepIt 0 0 ; FLUSH KeepIt"
Still looking into the maximum display distances. In my mind, based on a WindowWidth\Height being 400 x 400 If the WindowWidth / 2, would make it 200 (see how quick I did the maths there! ) And BackGroundPosX (BGPX) will be placing the alarmed device centrally say that object happens to be at 300x 300y Means lowerlimitx = BGPX - (WindowWidth / 2) and upperlimitx = BGPX + (WindowWidth / 2) would make lowerlimitx display an object at 100x and upperlimitx up to 500x. To me that looks right, so maybe the issue is actually within this part; IF object(n,x) > lowerlimitx and object(n,x) < upperlimitx and object(n,y) > lowerlimity and object(n,y) < upperlimity then
But that also looks correct!!! As when I run the code with below, the first iteration displays most of the objects, but not all, on the second iteration/alarm the same objects display on the map, despite me clearing the segment and redimming the array. lowerlimitx = BGPX - (WindowWidth / 2) upperlimitx = BGPX + (WindowWidth / 2) lowerlimity = BGPY - (WindowHeight / 2) upperlimity = BGPY + (WindowHeight / 2)
I'm sorry if the last part doesn't make sense, I'm going around in circles and getting even more confused. At one point I decided lower x and lower y would always be 0 0, because I got confused and started to think it was display related rather than being relative to the already moved background image. And I did try using the main objects x y positions which did the same pretty much.
|
|
|
Post by Rod on Jan 23, 2021 16:10:11 GMT -5
BGPX/Y isn't the middle of the map its the placement of the top left hand edge of the map is it not? That might be -1000,-1000 Object(x,y) is the centre of the alarm and where you should calculate your box from.
|
|
Tasp
Full Member
Posts: 215
|
Post by Tasp on Jan 24, 2021 8:56:15 GMT -5
You know what you're correct, I did try using the objects x and y but that didn't work before. Unsure why. But I've tried so many different ways I think I got confused and perhaps used it in the wrong place. Despite Rod saying this twice!!
I clearly either didn't grasp it, or was focused too much on BGPX/Y being the centre.
Thanks Rod, Chris and Brandon for the help. Much appreciated.
|
|