Advertisement

Tetr*s clone problem (SDL and code - long post)

Started by August 19, 2002 09:05 AM
1 comment, last by Joe Bob 22 years, 6 months ago
So I want to be a game programmer, and I''m following some advice I''ve seen here: write a tetris clone. I''m trying to do this on a Win2K machine using the SDL api. I''ve run into my first problem - I can''t seem to make my tetris-blocks display, and I don''t know why. All I''m trying to do is get it to create a new shape and move the block down the screen. When the block gets to the bottom of the screen, I want it to reset, get a new shape type, and start all over. Some notes on what I''m doing: I decided to break up the play area into a 17x17 array of 32x32 surfaces for my little blocks, and my "in play" shape class keeps track of the subscripts to use with that array. It made sense to me, hopefully it will to you also! Anyway, any advice would be appreciated on the code below. (I hope I''m not breaking any rules or ettiquett by posting the whole thing here, it''s kind of long for a post.) Thanks alot in advance for any help and suggestions!!!!
  
/////////////////////////////////////////////////

// structs.h

/////////////////////////////////////////////////


enum TYPE { BLOCK,LINE,RIGHT_L,LEFT_L,HUMP };

struct block_t {
	SDL_Rect		dim;
	SDL_Surface *	srf;
	Uint32			on;
};

class shape { 
private:
	Uint32		blocks[4][2];	// Each shape consists of four blocks, which each has a row and column value;

	TYPE		type;			// Controls the type of shape

	
public:
	/********************
	* Class Functions
	********************/
	
	// Constructor / Destructor:
	shape();

	int reset_shape();
	int move_shape();
	int cleanup_bg();
	int check_collision();

};

/////////////////////////////////////////////////
// gamemain.cpp
/////////////////////////////////////////////////
#include <SDL/SDL.h>
#include "structs.h"

/******************************
*	GLOBALS
******************************/
block_t play_surface[17][17];
SDL_Surface * textures[5];	// Five block textures (if you will...) 

/******************************
	FUNCTIONS
******************************/
int init_play_surface();
int draw_scene(SDL_Surface * screen);

//////////////////////////////////////
int main (int argc, char * argv[])
{
	SDL_Init(SDL_INIT_VIDEO);
	atexit(SDL_Quit);

	SDL_WM_SetCaption("Window Test",NULL);
	SDL_Surface *screen = SDL_SetVideoMode(800,600,0,SDL_ANYFORMAT);
	SDL_Event event;

	shape inplay;
	init_play_surface();
	inplay.reset_shape();
	Uint32 last_tick_count = SDL_GetTicks();

	for( ; ; )
	{
		if((SDL_GetTicks() - last_tick_count) > 500)
		{
			inplay.move_shape();
			inplay.cleanup_bg();
			last_tick_count = SDL_GetTicks();
		}

		draw_scene(screen);

		if(SDL_PollEvent(&event))
		{
			if(event.type == SDL_QUIT) break;
		}
	}
	
	return(0);
}

////////////////////////////////////////////

int init_play_surface()
{
	////////////////////////////////////////////////////////////
	// Divide the playing surface into a 17x17 grid of 32x32 
	// pixel surfaces.  Runtime will consist of turning these
	// surfaces on and off.  Start at y_pos = 544 so I can have 
	// row ''0'' at the bottom of the screen.
	////////////////////////////////////////////////////////////

	Uint32 y_pos = 544;
	Uint32 x_pos = 0;
	for(int row = 0; row < 17; row++)
	{
		for(int col = 0; col < 17; col++)
		{
			play_surface[row][col].dim.x = x_pos;
			play_surface[row][col].dim.y = y_pos;
			play_surface[row][col].dim.w = 32;
			play_surface[row][col].dim.h = 32;
			play_surface[row][col].on    = 0;
			play_surface[row][col].srf   = NULL;

			x_pos += 32;
		}
		y_pos += 32;
	}

	return(0);
}

///////////////////////////////////////////////////////

int draw_scene(SDL_Surface * screen)
{
	for(int row = 0; row < 17; row++)
	{
		for(int col = 0; col < 17; col++)
		{
			SDL_BlitSurface(play_surface[row][col].srf,NULL,screen,&play_surface[row][col].dim);
		}
	}
	return(0);
}
/////////////////////////////////////////////////
// shape.cpp
/////////////////////////////////////////////////
#include <SDL/SDL.h>
#include <stdio.h>
#include <stdlib.h>
#include "structs.h"

extern block_t play_surface[17][17];
extern SDL_Surface * textures[5];
/*
class shape { 
	Uint32		blocks[4][2];	// Each shape consists of four blocks, which each has a row and column value;
	TYPE		type;			// Controls the type of shape
	
	/********************
	* Class Functions
	********************
	
	// Constructor / Destructor:
	shape();

	int reset_shape();
	int move_shape();

};
*/

shape::shape()
{
	this->reset_shape();
}

int shape::reset_shape()
{
	////////////////////////////////

	// Get a new TYPE for our shape

	////////////////////////////////


	srand(SDL_GetTicks());
	this->type = TYPE(rand()%5);

///////////////////////////////////////

// NOTE!! Blocks init 1 row higher than they should

// Due to the move function.

	switch(this->type)
	{
	case BLOCK:
		{
			this->blocks[0][0] = 17;
			this->blocks[1][0] = 17;
			this->blocks[2][0] = 18;
			this->blocks[3][0] = 18;

			this->blocks[0][1] = 8;
			this->blocks[1][1] = 9;
			this->blocks[2][1] = 9;
			this->blocks[3][1] = 8;
		}break;

	case LINE:
		{
			this->blocks[0][0] = 18;
			this->blocks[1][0] = 18;
			this->blocks[2][0] = 18;
			this->blocks[3][0] = 18;

			this->blocks[0][1] = 7;
			this->blocks[1][1] = 8;
			this->blocks[2][1] = 9;
			this->blocks[3][1] = 10;
		}break;

	case RIGHT_L:
		{
			this->blocks[0][0] = 17;
			this->blocks[1][0] = 17;
			this->blocks[2][0] = 17;
			this->blocks[3][0] = 18;

			this->blocks[0][1] = 8;
			this->blocks[1][1] = 9;
			this->blocks[2][1] = 10;
			this->blocks[3][1] = 10;
		}break;
	case LEFT_L:
		{
			this->blocks[0][0] = 18;
			this->blocks[1][0] = 18;
			this->blocks[2][0] = 18;
			this->blocks[3][0] = 17;

			this->blocks[0][1] = 8;
			this->blocks[1][1] = 9;
			this->blocks[2][1] = 10;
			this->blocks[3][1] = 10;
		}break;
	case HUMP:
		{
			this->blocks[0][0] = 17;
			this->blocks[1][0] = 17;
			this->blocks[2][0] = 17;
			this->blocks[3][0] = 18;

			this->blocks[0][1] = 8;
			this->blocks[1][1] = 9;
			this->blocks[2][1] = 10;
			this->blocks[3][1] = 9;
		}break;

	}// END SWITCH

///////////////////////////////////////


	return(0);
}

int shape::move_shape()
{
	Uint32 row,col;
	int block; // used in for loops

	for(block = 0; block < 4; block++)
	{
		int less_than_zero = this->blocks[block][0] - 1;
		if (0 > less_than_zero)
		{
			this->reset_shape();
			return(0);
		}
	}

	for(block = 0; block < 4; block++)
	{
		row = this->blocks[block][0];
		col = this->blocks[block][1];

		if(row <= 17) //to avoid doing it the first time

		{
			play_surface[row][col].on = 0;
		}

		this->blocks[block][0] = row - 1;
		play_surface[row - 1][col].srf = textures[this->type];
		play_surface[row - 1][col].on  = 1;
		
	}
	return(0);
}

int shape::cleanup_bg()
{
	for(int row = 0; row < 17; row++)
	{
		for(int col = 0; col < 17; col++)
		{
			if(play_surface[row][col].on == 0)
			{
				play_surface[row][col].srf = NULL;
			}
		}
	}
	return(0);
}
  
So, I took care of the most glaring problem - ie, initializing my textures [sheepish], and the problem persists.

code==========
int init_play_surface()
{
textures[BLOCK] = SDL_LoadBMP("BMP/block_yellow.bmp");
textures[LINE] = SDL_LoadBMP("BMP/block_red.bmp");
textures[RIGHT_L] = SDL_LoadBMP("BMP/block_green.bmp");
textures[LEFT_L] = SDL_LoadBMP("BMP/block_blue.bmp");
textures[HUMP] = SDL_LoadBMP("BMP/block_white.bmp");
///rest of init function
===============
Advertisement
You don't seem to update the screen. If you blit you sortof send the data to the "video memory" but not to the screen. You have to tell when and how this has happen.

After you blitted everything you have to update the screen using SDL_Flip, SDL_UpdateRect or SDL_UpdateRects. The first one updates the entire screen in hardware if you requested a hardware surface with double buffering (using SDL_HWSURFACE|SDL_DOUBLEBUF in SDL_SetVideoMode). SDL_UpdateRect does the same for a SDL_SWSURFACE. I do not know if you have to at least indicate what kind of surface you want (SW or HW). In you code you only have SDL_ANYFORMAT which only make that the blits go direct to videomemory without being buffered in ram (yes, the name anyformat is silly). The SDL_UpdateRects let you specify multiple rectangles where the screen is updated. This can be used to update only the parts of the screen that were changed. For a software surface this is usually faster then updateing the entire screen using SDL_UpdateRect.

It is important to note that you do NOT update the screen after every blit you make. That's very slow. First you blit everything untill you completed the whole picture and then you update your screen (if you use sdl_updaterectS you have to keep track of every sdl_rect where you blitted....).

[edited by - smilydon on August 19, 2002 7:26:30 PM]

This topic is closed to new replies.

Advertisement