Double buffering problems.
Double buffering problems.
Hello all,
after tinkering with Hollywood for a few years, some months ago I was asked to code a point 'n' click adventure.
Since there's not much moving graphics involved, I originally elected to use sprites. Despite of apparences, I didn't like the look and feel of some part of the game, so I decided to change my rendering engine, shifting from sprites to double buffering. The only thing was that, being in an advanced state of the project, I postponed this paradigm shift until the game was nearly finished.
Now the project is almost ready, so I finally did, just to discover that .... it doesn't work!!! And I don't know why!!
As a matter of fact, the rendering engine is very simple and it is more or less directly taken from the examples that ships with Hollywood bundle.
Basically:
Flip()
Cls
... update logic...
... render screen ...
WaitTimer(1,40)
If my code just wouldn't work, I'll try to rewrite it from scratch, but the bad part is that it works almost perfectly on my Sam440 @800MHz with 1GB RAM (AmigaOS 4.1.6) , but it crashes on my Windows 8.1 machine (Pentium quade core, 4GB RAM) !!!
After a while, in fact, the game just hungs up, and doesn't recover anymore.
What can I do???
Best regards
g0blin (Gianluca Girelli)
=== EDIT =====
Well, after a couple of uneventful hours .... game hanged up on my Sam too.....
Now what?
after tinkering with Hollywood for a few years, some months ago I was asked to code a point 'n' click adventure.
Since there's not much moving graphics involved, I originally elected to use sprites. Despite of apparences, I didn't like the look and feel of some part of the game, so I decided to change my rendering engine, shifting from sprites to double buffering. The only thing was that, being in an advanced state of the project, I postponed this paradigm shift until the game was nearly finished.
Now the project is almost ready, so I finally did, just to discover that .... it doesn't work!!! And I don't know why!!
As a matter of fact, the rendering engine is very simple and it is more or less directly taken from the examples that ships with Hollywood bundle.
Basically:
Flip()
Cls
... update logic...
... render screen ...
WaitTimer(1,40)
If my code just wouldn't work, I'll try to rewrite it from scratch, but the bad part is that it works almost perfectly on my Sam440 @800MHz with 1GB RAM (AmigaOS 4.1.6) , but it crashes on my Windows 8.1 machine (Pentium quade core, 4GB RAM) !!!
After a while, in fact, the game just hungs up, and doesn't recover anymore.
What can I do???
Best regards
g0blin (Gianluca Girelli)
=== EDIT =====
Well, after a couple of uneventful hours .... game hanged up on my Sam too.....
Now what?
- airsoftsoftwair
- Posts: 5834
- Joined: Fri Feb 12, 2010 2:33 pm
- Location: Germany
- Contact:
Re: Double buffering problems.
Does the program really crash or does it exit with an error message? Have you checked resource management by running the script with the RESOURCEMONITOR argument? Maybe it's running out of memory because you forgot to free some resources. You can check that with the resource monitor. If that's not the case, try to isolate the problem and provide an example script that reproduces the problem.
Re: Double buffering problems.
Hello,
thanks for your prompt answer.
As I said, the program just stops working. It actually freezes (not answering any input) and Windows resource manager indicates its PID waiting for a thread sync.
RAM occupancy is around 200MB both on Windows and on AmigaOS, so there is plenty of memory. But I guess you are referring to stack memory ect.
I couldn't sleep very well tonight, and I actually thought it could be a problem of relinquishing a few resources (mainly unused brushes or stuff) so I'll try to code a routine which loads up (and then frees) the required "room data" on-the-fly without precaching them.
Since main character moving (walking) and scaling showed heavy flickering I actually wrote a "p_DisplaySprite()" routine which emulates Hollywood "DisplaySprite()" command but, using brushes, is doublebuffering compatible.
Anyway, I'll try running the script as you suggested and I'll get back to you soon.
Cheers
Gianluca
thanks for your prompt answer.
As I said, the program just stops working. It actually freezes (not answering any input) and Windows resource manager indicates its PID waiting for a thread sync.
RAM occupancy is around 200MB both on Windows and on AmigaOS, so there is plenty of memory. But I guess you are referring to stack memory ect.
I couldn't sleep very well tonight, and I actually thought it could be a problem of relinquishing a few resources (mainly unused brushes or stuff) so I'll try to code a routine which loads up (and then frees) the required "room data" on-the-fly without precaching them.
Since main character moving (walking) and scaling showed heavy flickering I actually wrote a "p_DisplaySprite()" routine which emulates Hollywood "DisplaySprite()" command but, using brushes, is doublebuffering compatible.
Anyway, I'll try running the script as you suggested and I'll get back to you soon.
Cheers
Gianluca
Re: Double buffering problems.
I ran a few tests using the resource monitor and two different versions of the game.
Version 1 (using double buffering):
BGPics 1
brushes 173
displays 1
musics 11
pointer images 9
sprites on screen 0
sprites (total) 81
text objects 1
timers 8
Version 2 (using sprites)
BGPics 1
brushes 175
displays 1
musics 10
pointer images 9
sprites on screen 2
sprites (total) 117
text objects 0
timers 5
I know the brush number seems outrageous, but before you think I was out of my mind, I'll clearly state that I originally pre-cached the graphic assets using "@BRUSH" preprocessor command. It was done on purpose to pack the assets inside the executable, thus preserving the commisioner intellectual property. Assets will be moved outside and not pre-loaded anymore.
It is also my understanding that the musics are not a big deal, since Hollywood only buffers a small part of them for later use.
Also, despite the fact that Version1 (double buffering) shows that sprites have been created, they are never used, and that part of the code will soon be removed.
In addition,even though Version 1 seems a little bit skinner in terms of resources, IT DOES STALL during runtime after a few minutes even at "idle" (player just sitting and watching), while Version 2 have been running for over an hour now without a single lock.
As I said, I'll write some code to load and free brushes (room data) on the fly, yet I still don't grasp why this is happening, unless double buffering is actually using resources (stacks etc) that are not currently shown in the resource monitor.
Regards
Gianluca
Version 1 (using double buffering):
BGPics 1
brushes 173
displays 1
musics 11
pointer images 9
sprites on screen 0
sprites (total) 81
text objects 1
timers 8
Version 2 (using sprites)
BGPics 1
brushes 175
displays 1
musics 10
pointer images 9
sprites on screen 2
sprites (total) 117
text objects 0
timers 5
I know the brush number seems outrageous, but before you think I was out of my mind, I'll clearly state that I originally pre-cached the graphic assets using "@BRUSH" preprocessor command. It was done on purpose to pack the assets inside the executable, thus preserving the commisioner intellectual property. Assets will be moved outside and not pre-loaded anymore.
It is also my understanding that the musics are not a big deal, since Hollywood only buffers a small part of them for later use.
Also, despite the fact that Version1 (double buffering) shows that sprites have been created, they are never used, and that part of the code will soon be removed.
In addition,even though Version 1 seems a little bit skinner in terms of resources, IT DOES STALL during runtime after a few minutes even at "idle" (player just sitting and watching), while Version 2 have been running for over an hour now without a single lock.
As I said, I'll write some code to load and free brushes (room data) on the fly, yet I still don't grasp why this is happening, unless double buffering is actually using resources (stacks etc) that are not currently shown in the resource monitor.
Regards
Gianluca
Re: Double buffering problems.
Bit off topic, but since I have been thinking of Point'n'click engine for quite long time already actually, and I havent quite figured out what would be best way to do some things, I am asking from curiosity, supposing you are willing to share of course, since perhaps you wish to keep these a secret.
But:
1. How are you doing hot spots in your program? I once did a system where there were two different pictures of the same image. Other one was image of what player sees, another one was color coded version of the same picture which worked as hotspot. That if mouse cursor was over color 1, then it would do hotspot 1:s stuff, if on color 2, then hotspot 2s things.
2. How have you handled the movement? This is a problem I have been pondering on and on in my head, but never figured quite how to do it. My best idea for solution is to make another picture which would show which ways character can go and which not, and also make that picture gray shaded to tell the program what is the distance of the character. For example light grey could mean character is close to screen, and hence character would be drawn big. While dark gray could mean character is distant from screen, and hence character be drawn in small size.
However, it sounds like ther emight be simpler way of fixing the problem, and I also felt problematic in figuring out that pathways for characters movements without restricting creativity in choosing paths. What I am after is that what if someone decides to make pathways in such way that every second pixel line is non accessible, and every second has pathway, making thousands, or actually perhaps even millions of pathways hence. Then that means that the code should be able to look through all these pathways to see how it can best get anywhere, and that would be problematic. On the other hand, I wouldnt want to make big rectangles pathway system which takes lot of freedom away from creating thing, like perhaps there is only a small gap between two, in which case big rectangles might think there is pathway, even when there isnt.
But:
1. How are you doing hot spots in your program? I once did a system where there were two different pictures of the same image. Other one was image of what player sees, another one was color coded version of the same picture which worked as hotspot. That if mouse cursor was over color 1, then it would do hotspot 1:s stuff, if on color 2, then hotspot 2s things.
2. How have you handled the movement? This is a problem I have been pondering on and on in my head, but never figured quite how to do it. My best idea for solution is to make another picture which would show which ways character can go and which not, and also make that picture gray shaded to tell the program what is the distance of the character. For example light grey could mean character is close to screen, and hence character would be drawn big. While dark gray could mean character is distant from screen, and hence character be drawn in small size.
However, it sounds like ther emight be simpler way of fixing the problem, and I also felt problematic in figuring out that pathways for characters movements without restricting creativity in choosing paths. What I am after is that what if someone decides to make pathways in such way that every second pixel line is non accessible, and every second has pathway, making thousands, or actually perhaps even millions of pathways hence. Then that means that the code should be able to look through all these pathways to see how it can best get anywhere, and that would be problematic. On the other hand, I wouldnt want to make big rectangles pathway system which takes lot of freedom away from creating thing, like perhaps there is only a small gap between two, in which case big rectangles might think there is pathway, even when there isnt.
Re: Double buffering problems.
Hello Bugala,
I don't have any problem in sharing concepts and even a few code snippets. After all, a brainstorming could help us both.
Having said that, I'm a bit in a hurry now, so I'll write a proper post tomorrow.
Just let me say that your idea of mapping hotspots is exactly what I tried first, but there are much simpler ways, like using a "bounding box" around the objects:
more code to follow....
Best regards
I don't have any problem in sharing concepts and even a few code snippets. After all, a brainstorming could help us both.
Having said that, I'm a bit in a hurry now, so I'll write a proper post tomorrow.
Just let me say that your idea of mapping hotspots is exactly what I tried first, but there are much simpler ways, like using a "bounding box" around the objects:
Code: Select all
Case 1:
If MouseX()>234 And MouseX()<280 And MouseY()>216 And MouseY()<270
CreateTextObject(1, investigation_text$[1][0], {Align=#LEFT, wordwrap=450})
box_width=IIf(StrLen(investigation_text$[1][0])*12>450,470,StrLen(investigation_text$[1][0])*12)
If box_width=470 Then box_height=70
Box(#CENTER, 420, box_width, box_height, $f8f9c9, {RoundLevel = 25})
DisplayTextObject(1, #CENTER, 430)
SetPointer(9)
If GetTimer(5)>200
p_PointerAnimation()
ResetTimer(5)
EndIf
If state=3
change_room_condition=True
p_Move_Cox()
new_room=3
EndIfBest regards
Re: Double buffering problems.
Not sure how much help this is, since this is quite terrible code. I did it 4 years ago, and it was my first try of this kind. Notice that I hadnt figured out the name "Hotspot" at this point yet, and hence I am using "Touch Sensitive" or "ts" as describing hotspots.
I am having trouble reading this even myself. But what I can remember is that room is a table that contains all the necessary stuff for this, heres example room:
Notice that when you run this piece, it will create home.bin from this code, which is simply a table that can be loaded at later point in the main program, which uses for example that p_CheckTouchSensitiveAreas(currentroom)
And that currentroom, is for example this home.bin that is being created here.
So it checks what is the color in that hidden picture at current mouse x,y spot. And then depending upon the color it jumps to home.bins table place. For example, if color is 5, then it jumps to that:
If i correctly remember how this works is that textover and answers are related to each other in that answers[1] is what happens when textover[1] is selected.
Idea is that when you first time move your mouse over that color 5, then it will use textover[0] spot, which in this case is to display text of "Look at papers" and change mouse pointer into eye.
If player clicks it, then happens the Answers[0] place, which in this case is to display text of "Just standard empty papers..
After this, if mouse pointer is moved to same place (color) again, then it will next time be using Textover[1], which means it will display "Take paper", and change mouse pointer to hands picture.
If user clicks, then it will go to Answers[1], which in this case will just display "I dont need any paper, i have all the paper i need in here if i want.".
After this, if once again player moves mouse pointer over this same hotspot area (color 5), it will go to Textover[2], which will simply show text "paper" and not change the mouse pointer indicating the player that there is no use in clicking here anymore. And hence there isnt Answers[2] even existing, since player cant do anything anymore.
amountofdifferenttexts, had perhaps to do with possibility of displaying different texts based upon which mouse pointer you were using, I think there were two different options for mouse pointer from users point of view. That right click mouse and it would change between "Look" and "use", or something like that. But I am not sure anymore at this point.
Anyway, this how the rooms worked.
I cant quite remember what that first snippet is precisely doing and why.
Code: Select all
Function p_CheckTouchSensitiveAreas(currentroom)
mx = MouseX()
my = MouseY()
If my > 100 And mx > 0 And mx < 1800
SelectBGPic(2)
col = ReadPixel(MouseX(), MouseY())
EndSelect()
If Not (col = at.currentcolors[at.currentcolors.currentcolor])
If Not at.mainstatus = 2 Then at.mousepointerstatus=0
For i = 1 To currentroom.numberoftsareas
If col = at.currentcolors[i]
at.currentcolors.currentcolor=i
If at.mainstatus=2
tempnum = currentroom.tsarea[i].textover[0].currenttext
Else
If Not RawGet(currentroom.tsarea[i].textover[at.mousepointerstatus], "currenttext") = Nil
tempnum = currentroom.tsarea[i].textover[at.mousepointerstatus].currenttext
Else
tempnum = currentroom.tsarea[i].textover[0].currenttext
EndIf
EndIf
If at.mainstatus=2
DebugPrint("currentitemname:"..at.item.currentitem.." tsarea:"..i.." text:"..tempnum)
tempstring = "Use "..at.item[at.item.currentitem].name.." with "..currentroom.tsarea[i].textover[2].text[tempnum].text
Else
tempstring = currentroom.tsarea[i].textover[at.mousepointerstatus].text[tempnum].text
p_ChangeMousePointer(currentroom.tsarea[i].textover[at.mousepointerstatus].text[tempnum].mousepointer)
EndIf
p_DisplayNormalText(tempstring)
EndIf
Next
EndIf
If col = at.currentcolors[0]
If at.textdisplaystatus=1
If Not at.mainstatus = 2 Then at.mousepointerstatus=0
at.currentcolors.currentcolor=0
RemoveLayer("textdisplaybox")
RemoveLayer("text-displayed")
nextfreelayer=nextfreelayer-1
nextfreelayer=nextfreelayer-1
at.textdisplaystatus=0
p_ChangeMousePointer("normalpointer")
EndIf
EndIf
ElseIf my < 101 Or my > 1200
If at.textdisplaystatus=1
RemoveLayer("textdisplaybox")
RemoveLayer("text-displayed")
nextfreelayer=nextfreelayer-1
nextfreelayer=nextfreelayer-1
at.textdisplaystatus=0
EndIf
EndIf
EndFunctionCode: Select all
mytable = {}
mytable = { status=1, numberofitems=0, numberoftsareas=5,
music="Easy Lemon.mp3",
filename="home-1800x1200.jpg",
bgfilename="homets-1800x1200.png",
type=1
}
mytable.tsarea = { /* tsarea = Touch Sensitive Area */
[1] = { textover = {
[0] = { amountofdifferenttexts=1, currenttext=1,
text = {
[1] = { text = "Go Out", name="Out",
mousepointer="arrowright" }
}
},
[1] = {
text = {
[1] = { text = "Go Out",
mousepointer="arrowright" }
}
},
[2] = { text = {
[1] = { text = "Out" }
}
}
},
/* Answer types: 1 = normal, just type the text and move To Next one on Line If there is any more
2 = grant an item
3 = go To Next Screen
4 = conversation
*/
answers = {
[0] = { amountofdifferentanswers = 1, currenttext=1,
[1] = { type = 3, roomname="turkumap" }
},
[1] = { amountofdifferentanswers = 1, currenttext=1,
[1] = { type = 3, roomname = "turkumap" }
}
}
},
[2] = { textover = {
[0] = { amountofdifferenttexts=1, currenttext=1,
text = {
[1] = { text = "Look at Computer", name="Computer",
mousepointer="eye" }
}
},
[1] = { amountofdifferenttexts=1, currenttext=1,
text = {
[1] = { text = "Turn on Computer",
mousepointer="hand" }
}
},
[2] = { text = {
[1] = { text = "computer" }
}
}
},
/* Answer types: 1 = normal, just type the text and move To Next one on Line If there is any more
*/
answers = {
[0] = { amountofdifferentanswers=1, currenttext=1,
[1] = { type = 1, text = "Thats my computer."
}
},
[1] = { amountofdifferentanswers=1, currenttext=1,
[1] = { type = 1, text = "I have no reason to" }
}
}
},
[3] = { textover = {
[0] = { amountofdifferenttexts=1, currenttext=1,
text = {
[1] = { text = "Look at Chair", name="Chair",
mousepointer="eye" }
}
},
[1] = { amountofdifferenttexts=1,
text = {
[1] = { text = "Sit on Chair",
mousepointer="hand" }
}
},
[2] = { text = {
[1] = { text = "Chair" }
}
}
},
/* Answer types: 1 = normal, just type the text and move To Next one on Line If there is any more
*/
answers = {
[0] = { amountofdifferentanswers=1, currenttext=1,
[1] = { type = 1, text = "Just ordinary Chair." }
},
[1] = { amountofdifferentanswers=1,
[1] = { type = 1, text = "I dont have time to sit down now." }
}
}
},
[4] = { textover = {
[0] = { amountofdifferenttexts=1, currenttext=1,
text = {
[1] = { text = "Look at Laser Printer", name="Laser Printer",
mousepointer="eye" }
}
},
[1] = { amountofdifferenttexts=1,
text = {
[1] = { text = "Use Laser Printer",
mousepointer="hand" }
}
},
[2] = { text = {
[1] = { text = "Laser Printer" }
}
}
},
/* Answer types: 1 = normal, just type the text and move To Next one on Line If there is any more
*/
answers = {
[0] = { amountofdifferentanswers=1, currenttext=1,
[1] = { type = 1, text = "It is Laser Printer." }
},
[1] = { amountofdifferentanswers=1,
[1] = { type = 1, text = "No point when Computer is not turned on." }
}
}
},
[5] = { textover = {
[0] = { amountofdifferenttexts=1, currenttext=1,
text = {
[1] = { text = "Look at Papers", name="Paper",
mousepointer="eye" }
}
},
[1] = { amountofdifferenttexts=1,
text = {
[1] = { text = "Take Paper",
mousepointer="hand" }
}
},
[2] = { text = {
[1] = { text = "Paper" }
}
}
},
/* Answer types: 1 = normal, just type the text and move To Next one on Line If there is any more
*/
answers = {
[0] = { amountofdifferentanswers=1, currenttext=1,
[1] = { type = 1, text = "Just standard empty white papers." }
},
[1] = { amountofdifferentanswers=1,
[1] = { type = 1, text = "I dont need any paper, i have all the paper i need in here if i want." }
}
}
}
}
mytable.item = {}
OpenFile(1, "home.bin", #MODE_WRITE)
WriteTable(1, mytable)
CloseFile(1)Notice that when you run this piece, it will create home.bin from this code, which is simply a table that can be loaded at later point in the main program, which uses for example that p_CheckTouchSensitiveAreas(currentroom)
And that currentroom, is for example this home.bin that is being created here.
So it checks what is the color in that hidden picture at current mouse x,y spot. And then depending upon the color it jumps to home.bins table place. For example, if color is 5, then it jumps to that:
Code: Select all
[5] = { textover = {
[0] = { amountofdifferenttexts=1, currenttext=1,
text = {
[1] = { text = "Look at Papers", name="Paper",
mousepointer="eye" }
}
},
[1] = { amountofdifferenttexts=1,
text = {
[1] = { text = "Take Paper",
mousepointer="hand" }
}
},
[2] = { text = {
[1] = { text = "Paper" }
}
}
},
/* Answer types: 1 = normal, just type the text and move To Next one on Line If there is any more
*/
answers = {
[0] = { amountofdifferentanswers=1, currenttext=1,
[1] = { type = 1, text = "Just standard empty white papers." }
},
[1] = { amountofdifferentanswers=1,
[1] = { type = 1, text = "I dont need any paper, i have all the paper i need in here if i want." }
}
}
}Idea is that when you first time move your mouse over that color 5, then it will use textover[0] spot, which in this case is to display text of "Look at papers" and change mouse pointer into eye.
If player clicks it, then happens the Answers[0] place, which in this case is to display text of "Just standard empty papers..
After this, if mouse pointer is moved to same place (color) again, then it will next time be using Textover[1], which means it will display "Take paper", and change mouse pointer to hands picture.
If user clicks, then it will go to Answers[1], which in this case will just display "I dont need any paper, i have all the paper i need in here if i want.".
After this, if once again player moves mouse pointer over this same hotspot area (color 5), it will go to Textover[2], which will simply show text "paper" and not change the mouse pointer indicating the player that there is no use in clicking here anymore. And hence there isnt Answers[2] even existing, since player cant do anything anymore.
amountofdifferenttexts, had perhaps to do with possibility of displaying different texts based upon which mouse pointer you were using, I think there were two different options for mouse pointer from users point of view. That right click mouse and it would change between "Look" and "use", or something like that. But I am not sure anymore at this point.
Anyway, this how the rooms worked.
I cant quite remember what that first snippet is precisely doing and why.
Re: Double buffering problems.
@ airsoftsoftwair
I did some checks with the prototype using sprites. It has run nicely on my win laptop for over 24h straight hours, successfully "surviving" the system sleep state and the subsequent warm reboot.
In other words, memory occupancy itself (huge number of brushes ect) seems not to be the problem, IMHO.
The double buffering prototype keeps crashing. Tomorrow I'll finally write that piece of code to load only the required resources on "room change".
Total number of brushes should drastically be cut down. I hope it does help.....
@Bugala
Your code does not seem as bad as you think it is. If you would like to confirm me your e-mail address (via PM) I can send you my considerations on it, together with a working (although still far from perfect) movement demo (including brush scaling and path finding).
Cheers
g0blin
I did some checks with the prototype using sprites. It has run nicely on my win laptop for over 24h straight hours, successfully "surviving" the system sleep state and the subsequent warm reboot.
In other words, memory occupancy itself (huge number of brushes ect) seems not to be the problem, IMHO.
The double buffering prototype keeps crashing. Tomorrow I'll finally write that piece of code to load only the required resources on "room change".
Total number of brushes should drastically be cut down. I hope it does help.....
@Bugala
Your code does not seem as bad as you think it is. If you would like to confirm me your e-mail address (via PM) I can send you my considerations on it, together with a working (although still far from perfect) movement demo (including brush scaling and path finding).
Cheers
g0blin
- airsoftsoftwair
- Posts: 5834
- Joined: Fri Feb 12, 2010 2:33 pm
- Location: Germany
- Contact:
Re: Double buffering problems.
Have you tried to run one of the examples that come with Hollywood and use a double buffer? Do they work or do they also crash sooner or later?
Re: Double buffering problems.
your examples run nicely, but I'm now starting an extended session just to be absolutely positive.