作者:龙飞
6.1:用bool作为命令是不是画蛇添足了?
不知道为什么,我总觉得总是用if结构来调用命令让人读起程序来很不连贯。所以,我决定重新修改下,并且异常抛出改为使用类对象,这样是不是更C++一点呢?:)
6.2:修改后的代码。
//
FileName: SurfaceClass.h
#ifndef SURFACE_CLASS_H
#define
SURFACE_CLASS_H
#include
<
iostream
>
#include
<
string
>
#include
"
SDL/SDL.h
"
using
std::
string
;
class
ScreenSurface
{
private
:
static
int
screenNum;
int
width;
int
height;
int
bpp;
Uint32 flags;
SDL_Surface
*
pScreen;
public
:
ScreenSurface();
ScreenSurface(
int
w,
int
h,
int
b
=
0
, Uint32 f
=
0
);
~
ScreenSurface();
SDL_Surface
*
point()
const
;
void
flip()
const
;
};
class
DisplaySurface
{
private
:
string
fileName;
SDL_Surface
*
pSurface;
SDL_Surface
*
pScreen;
public
:
DisplaySurface(
string
file_name,
const
ScreenSurface
&
screen);
~
DisplaySurface();
SDL_Surface
*
point()
const
;
void
blit()
const
;
void
blit(
int
at_x,
int
at_y)
const
;
void
blit(
int
at_x,
int
at_y,
int
from_x,
int
from_y,
int
w,
int
h,
int
delta_x
=
2
,
int
delta_y
=
2
)
const
;
void
blitToSurface(
const
DisplaySurface
&
dst_surface,
int
at_x
=
0
,
int
at_y
=
0
)
const
;
void
blitToSurface(
const
DisplaySurface
&
dst_surface,
int
at_x,
int
at_y,
int
from_x,
int
from_y,
int
w,
int
h,
int
delta_x
=
2
,
int
delta_y
=
2
)
const
;
};
class
ErrorInfo
{
private
:
string
info;
public
:
ErrorInfo():info(
"
Unknown ERROR!
"
)
{}
ErrorInfo(
const
char
*
c_str)
{
info
=
string
(c_str);
}
ErrorInfo(
const
string
&
str):info(str)
{}
void
show()
const
{
std::cerr
<<
info
<<
std::endl;
}
};
#endif
#include
"
SurfaceClass.h
"
//
VVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVV
//
class ScreenSurface
int
ScreenSurface::screenNum
=
0
;
ScreenSurface::ScreenSurface():
width(
640
), height(
480
), bpp(
32
), flags(
0
)
{
if
( screenNum
>
0
)
throw
ErrorInfo(
"
DONOT create more than ONE screen!
"
);
if
( SDL_Init(SDL_INIT_VIDEO
<
0
) )
throw
ErrorInfo(SDL_GetError());
pScreen
=
SDL_SetVideoMode(width, height, bpp, flags);
screenNum
++
;
}
ScreenSurface::ScreenSurface(
int
w,
int
h,
int
b, Uint32 f):
width(w), height(h), bpp(b), flags(f)
{
if
( screenNum
>
0
)
throw
ErrorInfo(
"
DONOT create more than ONE screen!
"
);
if
( SDL_Init(SDL_INIT_VIDEO
<
0
) )
throw
ErrorInfo(SDL_GetError());
pScreen
=
SDL_SetVideoMode(width, height, bpp, flags);
screenNum
++
;
}
ScreenSurface::
~
ScreenSurface()
{
SDL_Quit();
}
SDL_Surface
*
ScreenSurface::point()
const
{
return
pScreen;
}
void
ScreenSurface::flip()
const
{
if
( SDL_Flip(pScreen)
<
0
)
throw
ErrorInfo(SDL_GetError());
}
//
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
//
VVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVV
//
class DisplaySurface
DisplaySurface::DisplaySurface(std::
string
file_name,
const
ScreenSurface
&
screen):
fileName(file_name)
{
pSurface
=
SDL_LoadBMP(file_name.c_str());
if
( pSurface
==
0
)
throw
ErrorInfo(SDL_GetError());
pScreen
=
screen.point();
}
DisplaySurface::
~
DisplaySurface()
{
SDL_FreeSurface(pSurface);
}
SDL_Surface
*
DisplaySurface::point()
const
{
return
pSurface;
}
void
DisplaySurface::blit()
const
{
if
( SDL_BlitSurface(pSurface,
0
, pScreen,
0
)
<
0
)
throw
ErrorInfo(SDL_GetError());
}
void
DisplaySurface::blit(
int
at_x,
int
at_y)
const
{
SDL_Rect offset;
offset.x
=
at_x;
offset.y
=
at_y;
if
( SDL_BlitSurface(pSurface,
0
, pScreen,
&
offset)
<
0
)
throw
ErrorInfo(SDL_GetError());
}
void
DisplaySurface::blit(
int
at_x,
int
at_y,
int
from_x,
int
from_y,
int
w,
int
h,
int
delta_x,
int
delta_y)
const
{
SDL_Rect offset;
offset.x
=
at_x
-
delta_x;
offset.y
=
at_y
-
delta_y;
SDL_Rect dest;
dest.x
=
from_x
-
delta_x;
dest.y
=
from_y
-
delta_y;
dest.w
=
w
+
delta_x
*
2
;
dest.h
=
h
+
delta_y
*
2
;
if
( SDL_BlitSurface(pSurface,
&
dest, pScreen,
&
offset)
<
0
)
throw
ErrorInfo(SDL_GetError());
}
void
DisplaySurface::blitToSurface(
const
DisplaySurface
&
dst_surface,
int
at_x,
int
at_y)
const
{
SDL_Rect offset;
offset.x
=
at_x;
offset.y
=
at_y;
if
(
&
dst_surface
==
this
)
throw
ErrorInfo(
"
Cannot blit surface to itself!
"
);
if
( SDL_BlitSurface(pSurface,
0
, dst_surface.point(),
&
offset)
<
0
)
throw
ErrorInfo(SDL_GetError());
}
void
DisplaySurface::blitToSurface(
const
DisplaySurface
&
dst_surface,
int
at_x,
int
at_y,
int
from_x,
int
from_y,
int
w,
int
h,
int
delta_x,
int
delta_y)
const
{
SDL_Rect offset;
offset.x
=
at_x
-
delta_x;
offset.y
=
at_y
-
delta_y;
SDL_Rect dest;
dest.x
=
from_x
-
delta_x;
dest.y
=
from_y
-
delta_y;
dest.w
=
w
+
delta_x
*
2
;
dest.h
=
h
+
delta_y
*
2
;
if
(
&
dst_surface
==
this
)
throw
ErrorInfo(
"
Cannot blit surface to itself!
"
);
if
( SDL_BlitSurface(pSurface,
&
dest, dst_surface.point(),
&
offset)
<
0
)
throw
ErrorInfo(SDL_GetError());
}
//
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
#include
"
SurfaceClass.h
"
int
game(
int
argc,
char
*
argv[]);
int
main(
int
argc ,
char
*
argv[])
{
int
mainRtn
=
0
;
try
{
mainRtn
=
game(argc, argv);
}
catch
(
const
ErrorInfo
&
info ) {
info.show();
return
-
1
;
}
return
mainRtn;
}
int
game(
int
argc ,
char
*
argv[])
{
//
Create a SDL screen.
const
int
SCREEN_WIDTH
=
640
;
const
int
SCREEN_HEIGHT
=
480
;
ScreenSurface screen(SCREEN_WIDTH, SCREEN_HEIGHT);
//
Create 2 SDL surface for the screen that just created.
DisplaySurface backGround(
"
bg.bmp
"
, screen);
DisplaySurface frontImage(
"
image.bmp
"
, screen);
//
VVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVV
//
way2: If use blitToSurface, must get a copy of backGround.
/*
DisplaySurface backGroundCopy("bg.bmp", screen);
*/
//
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
//
Blit backGround surface to screen and flip the screen.
backGround.blit();
screen.flip();
//
variable for main loop.
//
key event for up, down, left and right.
Uint8
*
keys;
//
moving image's coordinate.
int
xpos
=
0
;
int
ypos
=
0
;
//
moving image's size.
const
int
IMG_WIDTH
=
128
;
const
int
IMG_HEIGHT
=
128
;
//
main loop.
bool
gameOver
=
false
;
while
( gameOver
==
false
){
//
press ESC or click X to quit.
SDL_Event gameEvent;
while
( SDL_PollEvent(
&
gameEvent)
!=
0
){
if
( gameEvent.type
==
SDL_QUIT ){
gameOver
=
true
;
}
if
( gameEvent.type
==
SDL_KEYUP ){
if
( gameEvent.key.keysym.sym
==
SDLK_ESCAPE ){
gameOver
=
true
;
}
}
}
//
key event to move image.
keys
=
SDL_GetKeyState(
0
);
if
( keys[SDLK_UP]
||
keys[SDLK_w] ){
ypos
-=
1
;
}
if
( keys[SDLK_DOWN]
||
keys[SDLK_s] ){
ypos
+=
1
;
}
if
( keys[SDLK_LEFT]
||
keys[SDLK_a] ){
xpos
-=
1
;
}
if
( keys[SDLK_RIGHT]
||
keys[SDLK_d] ){
xpos
+=
1
;
}
//
Hold moving image on the backGround area.
if
( xpos
<=
0
)
xpos
=
0
;
if
( xpos
>=
SCREEN_WIDTH
-
IMG_WIDTH )
xpos
=
SCREEN_WIDTH
-
IMG_WIDTH;
if
( ypos
<=
0
)
ypos
=
0
;
if
( ypos
>=
SCREEN_HEIGHT
-
IMG_HEIGHT )
ypos
=
SCREEN_HEIGHT
-
IMG_HEIGHT;
//
VVVVVVVVVVVVVVVVVVVVVVVVVVVVVV
//
way1: blit surface to screen
//
Blit a part of backGround ( a rectangular area ) to screen,
//
then the original blitted backGround can be "cleaned".
backGround.blit(xpos, ypos, xpos, ypos, IMG_WIDTH, IMG_HEIGHT);
//
Blit the image to screen.
frontImage.blit(xpos, ypos);
//
Flip the screen
screen.flip();
//
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
//
VVVVVVVVVVVVVVVVVVVVVVVVVVVVVV
//
way2: blit surface to surface, then blit the last surface to screen
/*
backGroundCopy.blitToSurface(backGround, xpos, ypos, xpos, ypos, IMG_WIDTH, IMG_HEIGHT);
frontImage.blitToSurface(backGround, xpos, ypos);
backGround.blit();
screen.flip();
*/
//
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
}
return
0
;
}