Sign in to follow this  

soo slow (3 seconds a frame!)

This topic is 4814 days old which is more than the 365 day threshold we allow for new replies. Please post a new topic.

If you intended to correct an error in the post then please contact us.

Recommended Posts

ok, so im making a scorched earth style game, you know, with little tanks aiming and setting power, anyway, im using sdl. so here is my problem, i wrote a class to hold the terrain, which is pretty much this, an array [800][600] of bools, and then i have some functions to turn on pixels and turn them off. pretty simple right. ok, so when i call the initTerrain function, it takes like 5 seconds, then when i call the setpixel function, it takes like 3 more. terrain.h
#include "sdl.h"
#include <iostream>

class cTerrain {
public:	
	void InitTerrain(SDL_Color k, int smooth);
	void PixelOn(int x, int y);
	void PixelOff(int x, int y);
	void SetColor(SDL_Color k);
	SDL_Color GetColor();
	void draw(SDL_Surface* screen);
private:
	bool PixArray[SCREEN_WIDTH][SCREEN_HEIGHT];
	SDL_Color drawcolor;
};


terrain.cpp
#include "sdl.h"
#include <iostream>
#include <cmath>
#include "pixelwar.h"
#include "helper.h"
#include "terrain.h"

void cTerrain::InitTerrain(SDL_Color k, int smooth) {
	int highY = rand()%200 + 200;
	for (int x = 0; x < SCREEN_WIDTH; x++) {
		highY += (rand()%smooth) - (smooth / 2);
		//if (highY > SCREEN_HEIGHT) highY -= smooth;
		for (int y = SCREEN_HEIGHT; y > 0; y--){
			if (y > highY) PixArray[x][y] = true;
			else PixArray[x][y] = false;
		}
	}
	drawcolor = k;
}

void cTerrain::PixelOn(int x, int y) {
	PixArray[x][y] = true;
}

void cTerrain::PixelOff(int x, int y) {
	PixArray[x][y] = false;
}

void cTerrain::SetColor(SDL_Color k) {
	drawcolor = k;
}

SDL_Color cTerrain::GetColor() {
	return drawcolor;
}	

void cTerrain::draw(SDL_Surface* screen) {
	for (int x = 0; x < SCREEN_WIDTH; x++) {
		for (int y = 0; y < SCREEN_HEIGHT; y++) {
			if (PixArray[x][y]) SetPixel(screen, x, y, drawcolor.r, drawcolor.b, drawcolor.g);
			else SetPixel(screen, x, y, 0, 0, 0);
		}
	}
}
	


ok, so my question is this, how would i go about speeding this up, you know, like pointers or memory fills or some crap like that thanks in advance -- Jake

Share this post


Link to post
Share on other sites
Simple answer: Dont do per pixel drawing

Long answer:

Games like worms (2d) used a texture for the map and an alpha channel that held where to draw. IMO this would be a good solution if you are to go with DX or OpenGL.

For Windows, dont draw per pixel, you can construct some more complex shapes for the map, try doing it as a polygon or as more then one polygon. You could draw a rectangle to fill the lowest portion of the map (solid area). Instead of drawing just the terrain how about drawing a simpler terrain and filling in the non active areas with the background color. Height checking would still be pretty simple since it would still be a 1D heightmap (each point has 1 y).

Hope that helped somewhat

Share this post


Link to post
Share on other sites
You're having to manually iterate through and act on each boolean. That's slooooooooow. Store your level in such a structure that you can simply blit it to the screen, but can still identify which pixels are ground and which aren't.

Share this post


Link to post
Share on other sites
Quote:
Original post by shade13
how do pictures work then, cause each pixel is bigger then a bool, and their really fast?

-- Jake


Well... first of all usually you can use hardware to draw pictures.

Also, I'll explain how it used to work (now adays there's a little more you need to remember). Let's say you have an 8bit palette, so each pixel is 8bit (a char) and the image is 320x200 pixels.

So, the picture is a big array. char pictureArray[320*200];

char pixel = pictureArray[y * 320 + x];

With me so far?!

Anyway, now you want to show this picture on the screen, which is also a big array (320x200, we're doing this like in the good'ol DOS days).

So you'd copy one pixel at the time.

for(int y = 0; y < 240; y++)
for(int x = 0; x < 320; x++)
screen[y*320 + x] = pictureArray[y*320 + x];

That my dear sir is: SLOW! and you're version was even slower as you called SetPixel() for each pixel, you could have made SetPixel as an "inline" function, that means the function isn't called but copied in the SetPixels()'s place when compiled.

First of all, the computer works with 32bits, this is 4 bytes (4 chars) so you can copy four bytes at the same speed as one.

Anyway, back to the point of speeding this up. You have two arrays that are the same size and you just want to copy over the pixels.

Secondly this would have been faster:

for(int i = 0; i < 320*240; i++) screen[i] = pictureArray[i];

But that would also just copy one byte at the time. It also does stuff that isn't really needed for each pixel. Better option would be to use memcpy()

memcpy(screen,pictureArray,320*240);

But memcpy also copies stuff on a byte level. So that's basicly four times slower then it has to be. You'll probably find a 32bit memcpy function on the web if you google. there's probably the ultimate asm written version somewhere out there.

The thing you need to remember with today's surfaces is that the scanline's width isn't allways what you want it to.

Say you have a backbuffer that's 800x600, in reality the backbuffer might be 1024 pixels wide because the hardware works like this. But there's a "pitch" variable with the surface that tells this.

So you could memcopy(preferable with the 32bit version) one scanline at the time. and then jump (Pitch - TheWidthYouWanted) pixels(8,16 or 32bit, whatever you set it to) in the array to get to the next scanline.


Hopefully any of this made sense.

/MindWipe

[Edited by - MindWipe on October 10, 2004 7:39:17 AM]

Share this post


Link to post
Share on other sites
Quote:
Original post by MindWipe
But memcpy also copies stuff on a byte level. So that's basicly four times slower then it has to be. You'll probably find a 32bit memcpy function on the web if you google. there's probably the ultimate asm written version somewhere out there.
Actually, even the version of memcpy() that comes with MSVC 6.0 copies 4 bytes at a time. Look at memcpy.asm, and you'll see that it copies a few bytes to word-align, then it copies 4 byte chunks until it reaches the end, and it then copies the last few bytes.
</offtopic>

Share this post


Link to post
Share on other sites

This topic is 4814 days old which is more than the 365 day threshold we allow for new replies. Please post a new topic.

If you intended to correct an error in the post then please contact us.

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