前几天为了忽悠一个大一小弟弟答应他给他写个打砖块。。。用了SDL,顺便试了一下beta版本的SDL1.3。。。发现用3D api作底层的SDL1.3的新加入的2D绘图接口的绘图速度跟以前相比真是逆天了。。。(相较之用DX由底层堆起来的2D程序绘制效率都逊色了。。。)果断弃SDL1.2用1.3。
然后这几天折腾好LINUX MINT 12,发现源里的SDL是1.2。。。 于是,下载,编译。
然后去源里扒SDL_ttf与SDL_image,还要靠这俩绘制文本哪。。。
然后,发现了个大问题:源里这俩库是依赖与SDL库的。装这俩前提是装SDL1.2。
于是去网上下了SDL_ttf,SDL_image的源码包,编译,安装,其间还特别留意了它们所使用的SDL的路径是我编译的版本。。。
然后。。。所有使用SDL相关的小游戏都不能运行了。 初始化失败,然后提示段错误。
而我写的那玩意儿即使编译通过也会直接初始化失败,错在 SDL_CreateRender函数失败,错误提示找不到显示设备(具体怎么提示的我也忘了)。总之是非常奇怪的错误。
后来卸掉编译安装的SDL_ttf与SDL_image,原来的SDL游戏都能用了。
然后,通过链接自行编译的SDL_1.3,还有源里的SDL_ttf和SDL_image,我在win里写的东西终于成功编译运行了。。。
gcc -o blockRevolutionNew testSDL1.c -I/usr/local/include/SDL -I/usr/include/SDL -Wl,-rpath,/usr/local/lib -L/usr/local/lib -lSDL -L/usr/lib -lSDL_image -lSDL_ttf -std=c99
回头查看了一下SDL_image的编译指令,发现了某些参数:
-g -O2 -D_REENTRANT -I/usr/local/include/SDL -o .libs/showimage showimage.o -Wl,-rpath -Wl,/usr/local/lib ./.libs/libSDL_image.so -L/usr/local/lib /usr/local/lib/libSDL.so
我这个菜鸟也看不太懂,只是发现它生成的文件是调试版本,链接的是我编译的SDL的链接库,而且其中还强制指向动态链接库的位置为我编译的SDL的位置。
顺便,把写得死烂的代码贴上(到处都是全局变量,各种混乱我自重,而且小球与挡板碰撞检测的代码逻辑有问题,总之雷雷更健康)
#include "SDL.h"
#include "SDL_render.h"
#include <stdio.h>
#include <stdlib.h>
#include <SDL_image.h>
#include <SDL_ttf.h>
#include <time.h> //time library of c
//define width and height of the window
#define WIDTH 800
#define HEIGHT 600
#define BLOCKNUM 36
#define BOARDY 420
#define BALLY 300
#define SPEED 1
#define BOARDSPEED 3
#define BLOCKSPERLINE 6 //the amount of blocks per line
//SDL_Surface* screen;
SDL_Event MyEvent;
SDL_Window* win = NULL;
SDL_Renderer* renderer = NULL;
SDL_Texture* bgTex = NULL; //texture of background image
SDL_Texture* boardTex = NULL; //texture of board
SDL_Texture* ballTex = NULL; //texture of ball
SDL_Texture* scoreTex = NULL;
//height and width of the board
int boardWidth = 0;
int boardHeight = 0;
//height and of the ball
int ballWidth = 0;
int ballHeight = 0;
//score
int score = 0;
//lives
int lives = 5;
// rects...
SDL_Rect boardRect;
SDL_Rect ballRect;
SDL_Rect scoreRect;
//font
TTF_Font* font;
//declarations of functions that will be defined
int WindowInit();
int GameMain();
int LoadBitmap();
int GameQuit();
int UpdateBall();
int UpdateBoard();
void GameInit();
int UpdateBlocks();
int DrawScore();
//struct of a brick
struct MyBrick{
Uint8 r;
Uint8 g;
Uint8 b;
Uint8 a;
int unhit;
int x;
int y;
};
//bricks
struct MyBrick blocks[BLOCKNUM];
int blockStep = ( WIDTH - 40 ) / BLOCKSPERLINE;
int blockWidth = 0;
int blockHeight = 0;
int boardMoved = 0;
int main(int argc, char *argv[]) {
if(!WindowInit())
exit(1);
printf("SDL initialized.\n");
if(!LoadBitmap())
exit(1);
GameInit();
if(!(GameMain()))
exit(1);
printf("Quiting SDL.\n");
/* Shutdown all subsystems */
GameQuit();
SDL_Quit();
printf("Quiting....\n");
exit(0);
}
//Initialization
int WindowInit()
{
//set position, size and window tittle
win = SDL_CreateWindow("BlocksRevolution -- By: Adolfans", 100, 100, WIDTH, HEIGHT, 0);
if(!win)
return 0;
renderer = SDL_CreateRenderer(win, -1, SDL_RENDERER_ACCELERATED);
if(!renderer)
{
printf("%s\n",SDL_GetError());
return 0;
}
if(TTF_Init()==-1) {
printf("TTF_Init: %s\n", TTF_GetError());
exit(2);
}
//msyh.ttf
font=TTF_OpenFont("Ubuntu-BI.ttf", 64);
if(!font)
printf("TTF_OpenFont: %s\n", TTF_GetError());
// handle error
return 1;
}
//game main loop
int GameMain()
{
//static time_t timeNow = time(0);
//static int timeNow = SDL_GetTicks();
static clock_t timeNow;
timeNow = clock();
while(1)
{
SDL_PollEvent( &MyEvent );
// if clicked quit, quit game main loop
if( MyEvent.type == SDL_QUIT)
return 1;
// if( SDL_GetTicks() - timeNow >= 1)
if( clock() - timeNow >= (10/SPEED) )
{
// timeNow = SDL_GetTicks();
timeNow = clock();
if( MyEvent.type == SDL_KEYDOWN )
{
boardMoved = 0;
//printf("some key is pressed");
if(MyEvent.key.keysym.sym == SDLK_LEFT)
{/* boardRect.x--;*/
boardMoved = -1;
//UpdateBoard(-1);
}else
if(MyEvent.key.keysym.sym == SDLK_RIGHT)
{
/* boardRect.x++;*/
boardMoved = 1;
//UpdateBoard(1);
}
if(MyEvent.key.keysym.sym == SDLK_ESCAPE)
{
return 1;
}
UpdateBoard();
}
UpdateBall();
boardMoved = 0;
}
SDL_RenderClear(renderer);
SDL_RenderCopy(renderer, bgTex, NULL, NULL);
SDL_RenderCopy(renderer, boardTex, NULL, &boardRect);
SDL_RenderCopy(renderer, ballTex, NULL, &ballRect);
UpdateBlocks();
DrawScore();
SDL_RenderPresent(renderer);
}
return 1;
}
int LoadBitmap()
{
//SDL_SetAlpha( image, SDL_SRCALPHA, 0);
SDL_Surface* image;
image = IMG_Load("c.png");
if (image == NULL) {
fprintf( stderr, "Couldn't load %s: %s\n", "c.png", SDL_GetError() );
return 0;
}
bgTex = SDL_CreateTextureFromSurface( renderer, image );
SDL_FreeSurface( image );
image = IMG_Load("board.png");
boardWidth = image->w;
boardHeight = image->h;
boardTex = SDL_CreateTextureFromSurface( renderer, image );
SDL_FreeSurface( image );
image = 0;
image = IMG_Load("BALL.png");
ballWidth = image->w;
ballHeight = image->h;
ballTex = SDL_CreateTextureFromSurface( renderer, image );
SDL_FreeSurface( image );
return 1;
}
void GameInit()
{
//initialize game data
blockWidth = blockStep - 2;
//init rects
boardRect.y = BOARDY;
boardRect.x = WIDTH/2 - boardWidth/2;
boardRect.h = boardHeight;
boardRect.w = boardWidth;
ballRect.y = BALLY - ballHeight/2;
ballRect.x = WIDTH/2 - ballWidth/2;
ballRect.h = ballHeight;
ballRect.w = ballWidth;
//initialize blocks, set it to 0 means it is not hit
memset( blocks, 0, sizeof(blocks) );
blockHeight = 50;
//Initialize color of the blocks
for( int i = 0; i < BLOCKNUM; i++ )
{
blocks[i].r = rand()%255;
blocks[i].g = rand()%255;
blocks[i].b = rand()%255;
blocks[i].a = rand()%255;
blocks[i].x = 20 + i%6*blockStep;
blocks[i].y = 20 + i/6*(blockHeight+2);
}
}
int GameQuit()
{
/* Free the allocated BMP surface */
//SDL_FreeSurface(image);
SDL_DestroyTexture( bgTex );
SDL_DestroyTexture( boardTex );
SDL_DestroyTexture( ballTex );
// SDL_DestroyTexture( scoreTex );
SDL_DestroyRenderer( renderer );
SDL_DestroyWindow( win );
return 1;
}
int UpdateBlocks()
{
static SDL_Rect rectTmp;
rectTmp.w = blockWidth;
rectTmp.h = blockHeight;
for( int i = 0; i < BLOCKNUM; i++ )
{
if( blocks[i].unhit == 0 )
{
rectTmp.x = blocks[i].x;
rectTmp.y = blocks[i].y;
SDL_SetTextureColorMod( boardTex, blocks[i].r, blocks[i].g, blocks[i].b );
SDL_RenderCopy(renderer, boardTex, NULL,&rectTmp);
}
}
return 1;
}
int UpdateBall()
{
static int leftBorder = 0;
static int rightBorder ;
rightBorder = WIDTH - ballWidth;
static int topBorder = 0;
static int bottomBorder;
bottomBorder = HEIGHT - ballHeight;
static int criticalBorder;
criticalBorder = boardRect.y;
//velocity of that ball
static int ballVelX = 1;
static int ballVelY = 3;
//position of the ball
// static int ballX = WIDTH/2;
// static int ballY = BALLY;
//update
// ballX += ballVelX;
// ballY += ballVelY;
ballRect.x += ballVelX;
ballRect.y += ballVelY;
if( ballRect.x <= leftBorder || ballRect.x >= rightBorder )
ballVelX = -ballVelX;
else
if( ballRect.y <= topBorder || ballRect.y >= bottomBorder )
ballVelY = -ballVelY;
if( ballRect.y >= bottomBorder )
lives--;
//hit on the board
/* if( ballRect.y + ballRect.h >= criticalBorder && \
ballRect.x >= boardRect.x && \
ballRect.x <= boardRect.x + boardRect.w)
ballVelY = -ballVelY;
*/
if( ballVelY > 0 && \
ballRect.x <= boardRect.x + boardRect.w && \
ballRect.y + ballRect.h >= criticalBorder && \
ballRect.y + ballRect.h < criticalBorder + boardHeight && \
ballRect.x >= boardRect.x )
{
ballVelY = -ballVelY;
if( boardMoved < 0 )
{
ballVelX -= rand()%2;
}else if( boardMoved > 0 )
{
ballVelX += rand()%2;
}
}
for( int i = 0; i < BLOCKNUM; i++ )
{
/*
if( ballRect.x + ballWidth > blocks[i].x && \
ballRect.x + ballWidth < blocks[i].x + blockWidth && \
ballRect.y + ballHeight > blocks[i].y && \
ballRect.y + ballWidth < blocks[i].y + blockHeight)
{
if
}*/
//if( ballRect.x + ballWidth >= blocks[i].x && ballRect.x < blocks[i].x) //×ó
if( blocks[i].unhit==1 )
continue;
int a = blocks[i].x - ballWidth;
int b = blocks[i].y - ballHeight;
int a2 = blocks[i].x + blockWidth;
int b2 = blocks[i].y + blockHeight;
if( ballRect.x >= a && ballRect.x <= a2 && \
ballRect.y >= b && ballRect.y <= b2)
{
if( (ballRect.x - a < ballRect.x - a && ballRect.x - a < b2 - ballRect.y) ||\
(a2-ballRect.x < ballRect.x - a && a2-ballRect.x < b2 - ballRect.y))
ballVelX = -ballVelX;
else
ballVelY = -ballVelY;
blocks[i].unhit=1;
score++;
}
}
return 1;
}
int UpdateBoard( )
{
static int leftBorder = 0;
static int rightBorder;
rightBorder = WIDTH - boardWidth;
if( boardMoved < 0 )
{
if( boardRect.x-1 < leftBorder )
return 1;
else
boardRect.x-=BOARDSPEED;
}else
{
if( boardRect.x+1 > rightBorder )
return 1;
else
boardRect.x+=BOARDSPEED;
}
return 1;
}
int DrawScore()
{
SDL_Color color={0,0,0};
SDL_Surface *text_surface;
char scoreText[100];
sprintf( scoreText, "score: %d lives: %d", score, lives );
if(!(text_surface=TTF_RenderText_Blended(font,scoreText,color))) {
printf("text_surface drawing error");
//handle error here, perhaps print TTF_GetError at least
return 0;
}
scoreRect.w = text_surface->w;
scoreRect.h = text_surface->h;
scoreRect.x = WIDTH/2 - text_surface->w/2;
scoreRect.y = HEIGHT - 70;
scoreTex = SDL_CreateTextureFromSurface( renderer, text_surface );
//perhaps we can reuse it, but I assume not for simplicity.
SDL_FreeSurface(text_surface);
SDL_RenderCopy(renderer, scoreTex, NULL, &scoreRect);
SDL_DestroyTexture( scoreTex );
return 1;
}
另外发现:NEHE的opengl教程,用SDL1.3编译可能会出一些问题,其中有一个检测键盘输入的API名字被改了。。。
=================================================================
今天过生日,发现这个博客快被荒废了,于是偶尔来写点东西,虽然是意义不大的东西啦。。。点进来的各位见笑了。