Hi im making my first project-game with the allegro library.Im trying to make the first level of super mario bros for NES on C++ .Im using an Intel Mac with the latest version of allegro 5 that is supported.
Im trying to do basic scrolling without any collision at the moment.Im using different bitmap layer for the background and different for the action(terrain) and in my render function i draw each layer to the backbuffer after i drew the key color first.
My problem is that while scrolling sometimes the tiles of both the background and the terrain are staying at the same place as before while drawing it again at the place it supposed to be after i scrolled. After a lot of running I noticed that this happens only when I scroll with more than 1 layers.While scrolling with 1 layer i don't have that problem. I will attach a screenshot of a moment when it's ok and when it has the problem . The weirdest thing is that its happening randomly and not at the same place of the level when it happens..
Any idea what is the cause of that?
It could be that you're not clearing the back layer properly, or it could be something else, but you'll need to show some code to get the help you need.
]]>Yes of course . This is my render function which runs in my game loop:
the layer class:
And the implementation of the display function:
Basic scroll func for testing:
void TileLayer::Scroll (float dx, float dy){ auto w = GetViewWindow(); w.x+=dx; w.y+=dy; SetViewWindow(w); this->GetGrid()->SetViewWindow(w); }
And the scroll part from the input function
else if (event.type == ALLEGRO_EVENT_KEY_CHAR && !terrain->CanScrollHoriz(8)) { int dx = 4; if (event.keyboard.keycode == ALLEGRO_KEY_RIGHT) { background->Scroll(dx, 0); terrain->Scroll(dx, 0); break; }
]]>
Quick tip, you should wrap your code in "<code>" tags to make it easier to read
I can't see anywhere that you clear the dpyBuffer in the tile class. I see you clear the display backbuffer, but you will need to clear the dpyBuffer so when you draw the tiles, the old tiles will be cleared first. So before you call PutTile(), you should be calling ClearTiles(), that will clear the previous dpyBuffer.
EDIT:
Nevermind, I guess you're drawing all the tiles in one big hit....
]]>Im sorry for the inconvenience. Just edited it .
I thought i could clear the buffer with "al_destroy_bitmap(GetBuffer());" am i wrong?
edit: i have the tileset bitmap and i draw the tiles that supposed to be visible. from the tileset bitmap
]]>al_clear_to_color and al_destroy_bitmap do two pretty different things...
]]>Yes i know , i just misunderstood about clear. Although i already use clear .before each layer i use clear to color the key color that i ignore from the tiles. And i use al_destroy_bitmap to free the recourses of the layer's buffer
]]>In your Display() function, you're creating bitmaps (Allocate()) and destroying bitmaps - this is not the way.
I also suspect there's some issues with the math that you eventually use when calling BlitBitmapScaled.
I can't quite work it out, but it looks like you're calling BlitBitmapScaled to draw to the display backbuffer, but shifting the x/y drawing co-ordinates using dpx/dpy. The layers should always be drawn at 0/0, but the tiles should be drawn onto their bitmaps to imitate scrolling.
You shouldn't be destroying the tile layers, you should create them at startup, and then draw->clear->draw->clear.
]]>Just rechecked it taking in mind your advice and i think it works now.Thank you very much! I really appreciate your time to help.About the math part i think it works good , it was the first thing i worked before i continue to multiple layers. It works but I'll do more testing later to be 100% sure.
I removed the al_destroy_bitmap() (although im thinking using it to destroy the buffer when i call the destructor of the class)
and then added this part when the dpy is changed:
al_set_target_bitmap(Buffer()); al_clear_to_color(TRAN); al_unlock_bitmap(Buffer());
The updated display function:
void TileLayer::Display(ALLEGRO_BITMAP *dest, const Rect &displayArea){ if(Buffer()==nullptr) Allocate(); if (dpyChanged) { al_set_target_bitmap(GetBuffer()); al_clear_to_color(TRAN); al_unlock_bitmap(GetBuffer()); /** dpychange math **/ } BitmapBlitScaled(Buffer(),{x,y,w,h},destination,0,0); }
]]>
Cool, glad it’s all working!
]]>What's the difference between Buffer() and GetBuffer()?
Also you shouldn't al_unlock_bitmap unless you locked it at some point (which I don't think you did?)
]]>FYI, this is also called parallax. Multiple backgrounds scrolling at different rates and offsets.
]]>