Sign in to follow this  
soundsystem

smooth tile scrolling?

Recommended Posts

soundsystem    138
The way I have my scrolling now, it moves in steps of tile size, 16 pixels each step, for example.. and it looks choppy. How would I make it so it moves smooth?

Share this post


Link to post
Share on other sites
Telastyn    3777
By rendering slightly more than the camera can see and moving the camera [or the tile surface] by smaller increments, loading tiles as needed.

There are a few better explinations than that online, as it's a common question. I've put off implimenting the scrolling for my game, so don't have much more insight, sorry :[

My game will likely move each tile's rect since it doesn't have a camera, and since the map bounds are unknown to the client.

Share this post


Link to post
Share on other sites
Daishim    244
You can reduce the choppiness by reducing the amount of pixels per time/step that the camera and character travel. Instead of having the character move from tile to tile with every step, you can have him move less pixels per time and 'walk' to the next tile through several steps.

Share this post


Link to post
Share on other sites
soundsystem    138
Thanks for the replies.
I have a problem with scrolling in general (not smooth scrolling)..I can get a camera to work fine, but I can't get the camera to follow the hero.. when the hero moves, the camera does also but the hero goes past it.. below is the function that draws the map, the heros x/y (in tile coords, not pixels) are passed to this function.


void DrawMap(int off_x, int off_y) {
off_x -= SW/2;
off_y -= SH/2;
if (off_x < 0) off_x = 0;
if (off_y < 0) off_y = 0;

for (int x=0; x<SW; ++x)
for (int y=0; y<SH; ++y)
DrawTile(x, y, map[x+off_x][y+off_y]);
}



Share this post


Link to post
Share on other sites
ekrax    128
instead of moving your character keep him stationary and move the map around him. so basically when the user pushes a key it scrolls the map and doesnt move the character.

Share this post


Link to post
Share on other sites
soundsystem    138
Is that how the other side scrollers are done? in mind I have Streets of Rage / Megaman / Sonic.. etc. I want to eventually make the game 2 (or more) players.

Share this post


Link to post
Share on other sites
sSimontis    100
I've seen it done like described above. Like this, you can scroll the map, and just rotate between two or more pictures of the character to make it look like they're walking in you want to.

Share this post


Link to post
Share on other sites
drarem    100
Yes that is WAY too inefficient..

Bitblit the entire screen on your backbuffer by OFFSET amount, eg.. 1,2,3,4,.. in your case 16..

only replace a ROW or COLUMN of tiles (one FOR loop now instead of a double loop) that you lose when the screen shifts.. you will have to create four steps for it.. such as to determine which direction you are going and which tiles to replace. It means you will bitblt the tile offset size of width and height, so if you lose 4 pixels on a shift, what I did on mine was blit the main tile width and height difference to replace it, such as:

tempWidth = tileXPosition - 4;
tempHeight = tileYPosition - 4;

invoke BitBlt(or bltFast for Directx)...,x,y,tempWidth,tempHeight

etc..

You may have to decrease the 16 down to a lower number because you will fly all around, the speed increase will be tremendous.

Please rate me too :) <lower left>

Above method c2004 BrainDead Software, All Rights Reserved.

Share this post


Link to post
Share on other sites
soundsystem    138
hmm.. right now I am blitting the character to the middle of the screen and just movin the camera around.. and it looks normal unless you hit the edge.. he doesn't keep going as he should. Does anyone have any basic scrolling example? the ones I've found are too complex, they add a lot of other things to the examples, like sound, collision detection, projectiles, animation..

drarem: alright, I want to get this working properly first before optimizing it though. I just want a character that is able to move through a map that is larger than the screen..

Share this post


Link to post
Share on other sites
Guest Anonymous Poster   
Guest Anonymous Poster
Quote:
Original post by ekrax
instead of moving your character keep him stationary and move the map around him. so basically when the user pushes a key it scrolls the map and doesnt move the character.


Heh, this idea sparked an argument in a video game forum. The question was "does the character move along the background or does the background move around the character?" Now I know most people here code it to be the latter. At least that's how it is with 2D scrollers.

Share this post


Link to post
Share on other sites
Pete_    198
Not sure if this helps, but here's my main rendering function for RPGtd:



POINT WorldToScreen(Entity::Location cam, float x, float y, int w, int h)
{
POINT p;
p.x = (LONG)((x - cam.x) * TILE_SPACING) + w/2;
p.y = (LONG)((y - cam.y) * TILE_SPACING) + h/2;
return p;
}

void GameWindowInset::Paint(Surface* target)
{
Surface& buff = *target;

Timer timerSetup;
timerSetup.Start();
buff.Clear(MAKEPIXEL(0,0,0,255));
Blitter<Rops::Copy> blitter(&buff);
timerSetup.End();

Entity::Location cam = world->GetCameraLoc();
int ntilesx = buff.Width() / TILE_SPACING;
int ntilesy = buff.Height() / TILE_SPACING;
int xs=(int)cam.x - ntilesx/2, xe=(int)cam.x + ntilesx/2;
int ys=(int)cam.y - ntilesy/2, ye=(int)cam.y + ntilesy/2;
xs-=2;xe+=2;ys-=2;ye+=2;

Timer timerBlits;
timerBlits.Start();
for(int x = 0; x < cam.sector->GetWidth(); ++x)
{
for(int y = cam.sector->GetHeight()-1; y != 0 ; --y)
{
if(x >= xs && x <= xe && y >= ys && y <= ye)
{
cam.sector->CreateRenderedTile(x, y);

POINT p = WorldToScreen(cam, (float)x, (float)y, buff.Width(), buff.Height());
p.x -=TILE_SPACING/2;
p.y -= TILE_SPACING/2;
blitter.Blit(cam.sector->GetRenderedTile(x, y), p.x, p.y);
}
else
cam.sector->DestroyRenderedTile(x, y);
}
}

Blitter<Rops::AlphaBlend> blendblitter(&buff);
for(Entity::List::iterator i = world->GetEntitiesBegin(); i != world->GetEntitiesEnd(); ++i)
{
Entity::Location loc = (*i)->Loc();
if(loc.sector == cam.sector)
{
POINT p = WorldToScreen(cam, loc.x, loc.y, buff.Width(), buff.Height()); p.y +=TILE_SPACING/2;
Surface* s = (*i)->GetTexture().Surface();
blendblitter.Blit(s, p.x - s->Width()/2, p.y - s->Height());
}
}

// Inventory
{
Entity* cament = world->GetCameraEnt();
Item::List& inventory = cament->GetInventory();
int itemx = 15;
int itemy = buff.Height() - 52;

ShapeBlitter shapeblitter(&buff);
shapeblitter.FillRect(itemx-5, itemy-5, (int)inventory.size()*42, 32+10, MAKEPIXEL(255,255,255, 100));

for(Item::List::iterator i = inventory.begin(); i != inventory.end(); ++i)
{
if((int)(i - inventory.begin()) == cament->GetSelectedItem())
shapeblitter.FillRect(itemx, itemy, 32,32, MAKEPIXEL(255,255,255, 100));
blendblitter.Blit(i->item_icon.Surface(), itemx, itemy);
itemx += i->item_icon.Width() + 10;
}
}

timerBlits.End();

FontBlitter fontblitter(&buff);
fontblitter.DrawString(font, std::string(fpsText), 10, 10);
}



Rather sloppy right now, but I'm doing a bunch of refactoring, killing pointers, etc., and have almost got to that part. Basically, I move my entity, attach the camera to it, and calculate the screen location of everything based on that.

- Pete

Share this post


Link to post
Share on other sites
soundsystem    138
This is what I have right now, I finally got the camera and character to cooperate. source should compile on Windows/Linux.. includes makefile, 1 source file and tile sheet.. the map is hedious and there is no collision detection right now. How's my pixel art? ;)

Anyway, now I am going to work on getting it to scroll smoothly. Thanks for the replies.

http://24.90.109.143/~maddumb/tile2src.tar.gz

Share this post


Link to post
Share on other sites

Create an account or sign in to comment

You need to be a member in order to leave a comment

Create an account

Sign up for a new account in our community. It's easy!

Register a new account

Sign in

Already have an account? Sign in here.

Sign In Now

Sign in to follow this