SDL2游戏制作实例

项目说明

SDL实现一个比较复杂的实例,游戏制作

设计思想

UI设计

关卡设置

(1)屏幕上有两只鸭子从左向右水平移动,鸭子一共有四种走路姿势。当你第一下点击左键,第一只鸭子停止运动,点击第二下左键,第二只鸭子停止运动。
当两只鸭子停止时的动作相同时,玩家就赢了;当两只鸭子停止时的动作不同或者有一只鸭子到达屏幕的另一端时,则玩家就输了。
(2)屏幕上有三只猫从屏幕的左侧向右侧移动,三只猫的移动方向各不相同。猫一共有六种姿势状态。当你第一下点击左键,第一只猫停止运动,点击第二下左键,第二只猫子停止运动,当你第三下点击左键,第一只猫停止运动。
当三只猫停止时的动作相同时,玩家就赢了;当三只猫停止时的动作不同或者有一只猫到达屏幕的另一端时,则玩家就输了。
(3)游戏开始时在屏幕随机位置出现一个方块,方块向任意方向飞行。在方块飞出屏幕之前点击中方块区域,则玩家获胜;当玩家在方块飞出屏幕前没有点击或者点击位置在方块区域外,玩家没有获胜。

header & cpp

这里写图片描述
这里写图片描述

UML

这里写图片描述

代码展示

main.cpp

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
#include "Game.h"
#include "utility.h"
#include "Vector2D.h"
const int FPS = 60;
const int DELAY_TIME = 1000.0f / FPS;
int main(int argc, char* argv[])
{
Uint32 frameStart, frameTime;
cout << "game init attempt...\n";
if(TheGame::Instance()->init("Chapter 1", 100, 50, WINDOW_WIDTH, WINDOW_HEIGHT,
false))
{
cout << "game init success!\n";
while(TheGame::Instance()->running())
{
frameStart = SDL_GetTicks();
TheGame::Instance()->handleEvents();
TheGame::Instance()->update();
TheGame::Instance()->render();
frameTime = SDL_GetTicks() - frameStart;
if(frameTime< DELAY_TIME)
{
SDL_Delay((int)(DELAY_TIME - frameTime));
}
}
}
else
{
cout << "game init failure - " << SDL_GetError() << "\n";
return -1;
}
cout << "game closing...\n";
TheGame::Instance()->clean();
return 0;
}

BackGround

BackGround.h

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
#ifndef _EEEEE_
#define _EEEEE_
#include "utility.h"
#include "GameObject.h"
class Enemy : public GameObject
{
public:
Enemy(const LoaderParams* pParams) : GameObject(pParams) {}
void update();
//void clean() {}
};
#endif

Game

Game.h

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
#ifndef __GGGG__
#define __GGGG__
#include "utility.h"
#include "TextureManager.h"
#include "GameObject.h"
#include "Player.h"
#include "GameStateMachine.h"
typedef class Game
{
public:
~Game() {}
bool init(const char* title, int xpos, int ypos, int width, int height, int flags);
void render();
void update();
/*void draw();*/
void handleEvents();
void clean();
bool running() { return m_bRunning; }
SDL_Renderer* getRenderer() const { return m_pRenderer; }
static Game* Instance();
void quit() { SDL_Quit(); exit(0); } //!
GameStateMachine* getStateMachine(){ return m_pGameStateMachine; }
private:
Game() {}
private:
static Game* s_pInstance;
SDL_Window* m_pWindow;
SDL_Renderer* m_pRenderer;
bool m_bRunning;
vector<GameObject*> m_gameObjects;
GameStateMachine* m_pGameStateMachine;
}TheGame;
#endif /* defined(__Game__) */

Game.cpp

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
#include "Game.h"
#include "TextureManager.h"
#include "Player.h"
#include "Enemy.h"
#include "BackGround.h"
#include "GameStateMachine.h"
#include "InputHandler.h"
#include "MenuState.h"
#include "PlayState.h"
Game* Game::s_pInstance = 0;
Game* Game::Instance()
{
if(s_pInstance == 0)
{
s_pInstance = new Game();
return s_pInstance;
}
return s_pInstance;
}
bool Game::init(const char* title, int xpos, int ypos, int width, int height, int flags)
{
// attempt to initialize SDL
if(SDL_Init(SDL_INIT_EVERYTHING) == 0)
{
std::cout << "SDL init success\n";
// init the window
m_pWindow = SDL_CreateWindow(title, xpos, ypos, width, height, flags);
if(m_pWindow != 0) // window init success
{
cout << "window creation success\n";
m_pRenderer = SDL_CreateRenderer(m_pWindow, -1, 0);
if(m_pRenderer != 0) // renderer init success
{
cout << "renderer creation success\n";
SDL_SetRenderDrawColor(m_pRenderer, 0, 0, 0, 0);
if(1)
{
m_pGameStateMachine = new GameStateMachine();
m_pGameStateMachine->changeState(new MenuState());
/* m_gameObjects.push_back(new BackGround(new LoaderParams(0, 0, 800, 501, "back")));
m_gameObjects.push_back(new Player(new LoaderParams(100, 100, 128, 82, "a", 200)));
m_gameObjects.push_back(new Player(new LoaderParams(200, 200, 128, 82, "a", 300)));*/
}
else
{
return false;
}
}
else
{
cout << "renderer init fail\n";
return false; // renderer init fail
}
}
else
{
cout << "window init fail\n";
return false; // window init fail
}
}
else
{
std::cout << "SDL init fail\n";
return false; // SDL init fail
}
std::cout << "init success\n";
m_bRunning = true; // everything inited successfully,start the main loop
return true;
}
//void Game::draw()
//{
// for(std::vector<GameObject*>::size_type i = 0; i !=
// m_gameObjects.size(); i++)
// {
// m_gameObjects[i]->draw();
// }
//}
void Game::render()
{
SDL_RenderClear(m_pRenderer);
m_pGameStateMachine->render();
SDL_RenderPresent(m_pRenderer);
}
void Game::handleEvents()
{
TheInputHandler::Instance()->update();
//if(TheInputHandler::Instance()->isKeyDown(SDL_SCANCODE_RETURN))
//{
// m_pGameStateMachine->changeState(new PlayState());
//}
}
//void Game::handleEvents()
//{
// SDL_Event event;
// if(SDL_PollEvent(&event))
// {
// switch (event.type)
// {
// case SDL_QUIT:
// m_bRunning = false;break;
// case SDL_KEYDOWN:
// switch( event.key.keysym.sym )
// {
// case SDLK_a: SDL_Delay(1000); break;
// }
// break;
// default:
// break;
// }
// }
//}
void Game::update()
{
m_pGameStateMachine->update();
}
void Game::clean()
{
std::cout << "cleaning game\n";
TheInputHandler::Instance()->clean();
SDL_DestroyWindow(m_pWindow);
SDL_DestroyRenderer(m_pRenderer);
SDL_Quit();
}

GameObject

GameObject.h

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
#ifndef __GSMGSM__
#define __GSMGSM__
#include "GameState.h"
class GameStateMachine
{
public:
void pushState(GameState* pState);
void changeState(GameState* pState);
void popState();
void update();
void render();
private:
vector<GameState*> m_gameStates;
};
#endif

GameObject.cpp

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
#include "Game.h"
#include "TextureManager.h"
#include "Player.h"
#include "Enemy.h"
#include "BackGround.h"
#include "GameStateMachine.h"
#include "InputHandler.h"
#include "MenuState.h"
#include "PlayState.h"
Game* Game::s_pInstance = 0;
Game* Game::Instance()
{
if(s_pInstance == 0)
{
s_pInstance = new Game();
return s_pInstance;
}
return s_pInstance;
}
bool Game::init(const char* title, int xpos, int ypos, int width, int height, int flags)
{
// attempt to initialize SDL
if(SDL_Init(SDL_INIT_EVERYTHING) == 0)
{
std::cout << "SDL init success\n";
// init the window
m_pWindow = SDL_CreateWindow(title, xpos, ypos, width, height, flags);
if(m_pWindow != 0) // window init success
{
cout << "window creation success\n";
m_pRenderer = SDL_CreateRenderer(m_pWindow, -1, 0);
if(m_pRenderer != 0) // renderer init success
{
cout << "renderer creation success\n";
SDL_SetRenderDrawColor(m_pRenderer, 0, 0, 0, 0);
if(1)
{
m_pGameStateMachine = new GameStateMachine();
m_pGameStateMachine->changeState(new MenuState());
/* m_gameObjects.push_back(new BackGround(new LoaderParams(0, 0, 800, 501, "back")));
m_gameObjects.push_back(new Player(new LoaderParams(100, 100, 128, 82, "a", 200)));
m_gameObjects.push_back(new Player(new LoaderParams(200, 200, 128, 82, "a", 300)));*/
}
else
{
return false;
}
}
else
{
cout << "renderer init fail\n";
return false; // renderer init fail
}
}
else
{
cout << "window init fail\n";
return false; // window init fail
}
}
else
{
std::cout << "SDL init fail\n";
return false; // SDL init fail
}
std::cout << "init success\n";
m_bRunning = true; // everything inited successfully,start the main loop
return true;
}
//void Game::draw()
//{
// for(std::vector<GameObject*>::size_type i = 0; i !=
// m_gameObjects.size(); i++)
// {
// m_gameObjects[i]->draw();
// }
//}
void Game::render()
{
SDL_RenderClear(m_pRenderer);
m_pGameStateMachine->render();
SDL_RenderPresent(m_pRenderer);
}
void Game::handleEvents()
{
TheInputHandler::Instance()->update();
//if(TheInputHandler::Instance()->isKeyDown(SDL_SCANCODE_RETURN))
//{
// m_pGameStateMachine->changeState(new PlayState());
//}
}
//void Game::handleEvents()
//{
// SDL_Event event;
// if(SDL_PollEvent(&event))
// {
// switch (event.type)
// {
// case SDL_QUIT:
// m_bRunning = false;break;
// case SDL_KEYDOWN:
// switch( event.key.keysym.sym )
// {
// case SDLK_a: SDL_Delay(1000); break;
// }
// break;
// default:
// break;
// }
// }
//}
void Game::update()
{
m_pGameStateMachine->update();
}
void Game::clean()
{
std::cout << "cleaning game\n";
TheInputHandler::Instance()->clean();
SDL_DestroyWindow(m_pWindow);
SDL_DestroyRenderer(m_pRenderer);
SDL_Quit();
}

GameOverState

GameOverState.h

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
#ifndef __GOSGOS__
#define __GOSGOS__
#include "GameState.h"
#include "GameObject.h"
enum over_states
{
LOSE = 0,
WIN = 1,
};
class GameOverState : public GameState
{
public:
GameOverState(int state) : m_state(state) {}
virtual void update();
virtual void render();
virtual bool onEnter();
virtual bool onExit();
virtual void setS(int s) { m_state = s; }
virtual void setPS(int ps) { pre_sta = ps;}
virtual std::string getStateID() const {return s_gameOverID;}
private:
static void s_gameOverToMain();
static void s_restartPlay();
static const string s_gameOverID;
std::vector<GameObject*> m_gameObjects;
int m_state; //要显示输赢的状态
static int pre_sta; //OVER之前的状态
};
#endif

GameOverState.cpp

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
#include "GameOverState.h"
#include "Game.h"
#include "MenuState.h"
#include "PlayState.h"
#include "MenuButton.h"
#include "InputHandler.h"
#include "BackGround.h"
#include "LevelState.h"
const string GameOverState::s_gameOverID = "GAMEOVER";
int GameOverState::pre_sta = LEVEL1;
void GameOverState::s_gameOverToMain()
{
TheGame::Instance()->getStateMachine()->changeState(new
MenuState());
}
//*********************************************************
void GameOverState::s_restartPlay()
{
GameState *p = new PlayState();
p->setS(pre_sta);
TheGame::Instance()->getStateMachine()->changeState(p);
}
bool GameOverState::onEnter()
{
TheInputHandler::Instance()->reset();
if(m_state == LOSE)
{
if(!TheTextureManager::Instance()->load("setting/gameover.png",
"over", TheGame::Instance()->getRenderer()))
{
return false;
}
}
else
{
if(!TheTextureManager::Instance()->load("setting/win.png",
"over", TheGame::Instance()->getRenderer()))
{
return false;
}
}
if(!TheTextureManager::Instance()->load("setting/main.png",
"mainbutton", TheGame::Instance()->getRenderer()))
{
return false;
}
if(!TheTextureManager::Instance()->load("setting/restart.png",
"restartbutton", TheGame::Instance()->getRenderer()))
{
return false;
}
GameObject* gameOverText = new BackGround(new LoaderParams(400, 100, 190, 50, "over"));
GameObject* button1 = new MenuButton(new LoaderParams(350, 200,
300, 120, "mainbutton"), s_gameOverToMain);
GameObject* button2 = new MenuButton(new LoaderParams(350, 400,
300, 120, "restartbutton"), s_restartPlay);
m_gameObjects.push_back(gameOverText);
m_gameObjects.push_back(button1);
m_gameObjects.push_back(button2);
cout << "entering GaveOverState\n";
return true;
}
void GameOverState::update()
{
for(int i = 0; i < m_gameObjects.size(); i++)
{
m_gameObjects[i]->update();
}
}
void GameOverState::render()
{
for(int i = 0; i < m_gameObjects.size(); i++)
{
m_gameObjects[i]->draw();
}
}
bool GameOverState::onExit()
{
for(int i = 0; i < m_gameObjects.size(); i++)
{
m_gameObjects[i]->clean();
}
m_gameObjects.clear();
TheTextureManager::Instance()->clearFromTextureMap("mainbutton");
TheTextureManager::Instance()->clearFromTextureMap("restartbutton");
TheTextureManager::Instance()->clearFromTextureMap("gameover");
std::cout << "exiting GaveOverState\n";
return true;
}

GameState

GameState.h

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
#ifndef _GSGSGS_
#define _GSGSGS_
#include "utility.h"
class GameState
{
public:
virtual void update() = 0;
virtual void render() = 0;
virtual bool onEnter() = 0;
virtual bool onExit() = 0;
virtual void setS(int s) {}
virtual void setPS(int ps) {}
virtual string getStateID() const = 0;
};
#endif

GameStateMachine.h

GameStateMachine.h

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
#ifndef __GSMGSM__
#define __GSMGSM__
#include "GameState.h"
class GameStateMachine
{
public:
void pushState(GameState* pState);
void changeState(GameState* pState);
void popState();
void update();
void render();
private:
vector<GameState*> m_gameStates;
};
#endif

GameStateMachine.cpp

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
#include "GameStateMachine.h"
void GameStateMachine::pushState(GameState *pState)
{
m_gameStates.push_back(pState);
m_gameStates.back()->onEnter();
}
void GameStateMachine::popState()
{
if(!m_gameStates.empty())
{
if(m_gameStates.back()->onExit())
{
delete m_gameStates.back();
m_gameStates.pop_back();
}
}
}
void GameStateMachine::changeState(GameState *pState)
{
if(!m_gameStates.empty())
{
if(m_gameStates.back()->getStateID() == pState->getStateID())
{
return; // do nothing
}
for(int i=0; i<m_gameStates.size(); i++)
{
m_gameStates[i]->onExit();
delete m_gameStates[i];
m_gameStates.clear();
}
}
// push back our new state
m_gameStates.push_back(pState);
// initialise it
m_gameStates.back()->onEnter();
}
void GameStateMachine::update()
{
if(!m_gameStates.empty())
{
m_gameStates.back()->update();
}
}
void GameStateMachine::render()
{
if(!m_gameStates.empty())
{
m_gameStates.back()->render();
}
}

InputHandler

InputHandler.h

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
#ifndef __IHIHIH__
#define __IHIHIH__
#include "utility.h"
#include "Game.h"
enum mouse_buttons
{
LEFT = 0,
MIDDLE = 1,
RIGHT = 2
};
typedef class InputHandler
{
public:
static InputHandler* Instance();
void reset();
// update and clean the input handler
void update();
void clean() {}
// keyboard events
bool isKeyDown(SDL_Scancode key) const;
// mouse events
bool getMouseButtonState(int buttonNumber) const;
Vector2D* getMousePosition() const;
private:
InputHandler();
~InputHandler();
InputHandler(const InputHandler&);
InputHandler& operator=(const InputHandler&);
// handle keyboard events
void onKeyDown();
void onKeyUp();
// handle mouse events
void onMouseMove(SDL_Event& event);
void onMouseButtonDown(SDL_Event& event);
void onMouseButtonUp(SDL_Event& event);
private:
static InputHandler* s_pInstance;
// keyboard specific
const Uint8* m_keystates;
// mouse specific
vector<bool> m_mouseButtonStates;
Vector2D* m_mousePosition;
}TheInputHandler;
#endif

InputHandler.cpp

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
#include "InputHandler.h"
InputHandler* InputHandler::s_pInstance = 0;
InputHandler* InputHandler::Instance()
{
if(s_pInstance == 0)
{
s_pInstance = new InputHandler();
}
return s_pInstance;
}
InputHandler::InputHandler() : m_keystates(0),m_mousePosition(new Vector2D(0,0))
{
// create button states for the mouse
for(int i = 0; i < 3; i++)
{
m_mouseButtonStates.push_back(false);
}
}
InputHandler::~InputHandler()
{
// delete anything we created dynamically
delete m_keystates;
delete m_mousePosition;
m_mouseButtonStates.clear();
}
void InputHandler::reset()
{
m_mouseButtonStates[LEFT] = false;
m_mouseButtonStates[RIGHT] = false;
m_mouseButtonStates[MIDDLE] = false;
}
bool InputHandler::isKeyDown(SDL_Scancode key) const
{
if(m_keystates != 0)
{
if(m_keystates[key] == 1)
{
return true;
}
else
{
return false;
}
}
return false;
}
bool InputHandler::getMouseButtonState(int buttonNumber) const
{
return m_mouseButtonStates[buttonNumber];
}
Vector2D* InputHandler::getMousePosition() const
{
return m_mousePosition;
}
void InputHandler::update()
{
SDL_Event event;
while(SDL_PollEvent(&event))
{
switch (event.type)
{
case SDL_QUIT:
TheGame::Instance()->quit();
break;
case SDL_MOUSEMOTION:
onMouseMove(event);
break;
case SDL_MOUSEBUTTONDOWN:
onMouseButtonDown(event);
break;
case SDL_MOUSEBUTTONUP:
onMouseButtonUp(event);
break;
case SDL_KEYDOWN:
onKeyDown();
break;
case SDL_KEYUP:
onKeyUp();
break;
default:
break;
}
}
}
void InputHandler::onKeyDown()
{
m_keystates = SDL_GetKeyboardState(0);
}
void InputHandler::onKeyUp()
{
m_keystates = SDL_GetKeyboardState(0);
}
void InputHandler::onMouseMove(SDL_Event &event)
{
m_mousePosition->setX(event.motion.x);
m_mousePosition->setY(event.motion.y);
}
void InputHandler::onMouseButtonDown(SDL_Event& event)
{
if(event.button.button == SDL_BUTTON_LEFT)
{
m_mouseButtonStates[LEFT] = true;
}
if(event.button.button == SDL_BUTTON_MIDDLE)
{
m_mouseButtonStates[MIDDLE] = true;
}
if(event.button.button == SDL_BUTTON_RIGHT)
{
m_mouseButtonStates[RIGHT] = true;
}
}
void InputHandler::onMouseButtonUp(SDL_Event &event)
{
if(event.button.button == SDL_BUTTON_LEFT)
{
m_mouseButtonStates[LEFT] = false;
}
if(event.button.button == SDL_BUTTON_MIDDLE)
{
m_mouseButtonStates[MIDDLE] = false;
}
if(event.button.button == SDL_BUTTON_RIGHT)
{
m_mouseButtonStates[RIGHT] = false;
}
}

LevelState

LevelState.h

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
#ifndef __LSLSLS__
#define __LSLSLS__
#include "utility.h"
#include "GameState.h"
#include "GameObject.h"
enum p_states
{
LEVEL1 = 1,
LEVEL2 = 2,
LEVEL3 = 3
};
class LevelState : public GameState
{
virtual void update();
virtual void render();
virtual bool onEnter();
virtual bool onExit();
virtual string getStateID() const {return s_menuID ;}
private:
static void s_ToLevel1();
static void s_ToLevel2();
static void s_ToLevel3();
private:
static const string s_menuID;
vector< GameObject* > m_gameObjects;
};
#endif

LevelState.cpp

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
#include "LevelState.h"
#include "Game.h"
#include "InputHandler.h"
#include "MenuButton.h"
#include "BackGround.h"
#include "PlayState.h"
#include "LevelState.h"
const string LevelState::s_menuID = "LEVELSTATE";
void LevelState::update()
{
for(int i = 0; i < m_gameObjects.size(); i++)
{
m_gameObjects[i]->update();
}
}
void LevelState::render()
{
for(int i = 0; i < m_gameObjects.size(); i++)
{
m_gameObjects[i]->draw();
}
}
bool LevelState::onEnter()
{
TheInputHandler::Instance()->reset();
if(!TheTextureManager::Instance()->load("setting/level1.png",
"level1", TheGame::Instance()->getRenderer()))
{
return false;
}
if(!TheTextureManager::Instance()->load("setting/level2.png",
"level2", TheGame::Instance()->getRenderer()))
{
return false;
}
if(!TheTextureManager::Instance()->load("setting/level3.png",
"level3", TheGame::Instance()->getRenderer()))
{
return false;
}
if(!TheTextureManager::Instance()->load("setting/bg.png",
"bg", TheGame::Instance()->getRenderer()))
{
return false;
}
GameObject* Button1 = new MenuButton(new LoaderParams(100, 225, 250,
63, "level1"), s_ToLevel1);
GameObject* Button2 = new MenuButton(new LoaderParams(100, 325, 250,
63, "level2"), s_ToLevel2);
GameObject* Button3 = new MenuButton(new LoaderParams(100, 425, 250,
63, "level3"), s_ToLevel3);
GameObject* back = new BackGround(new LoaderParams(0, 0, WINDOW_WIDTH, WINDOW_HEIGHT, "bg"));
m_gameObjects.push_back(back);
m_gameObjects.push_back(Button1);
m_gameObjects.push_back(Button2);
m_gameObjects.push_back(Button3);
cout << "entering MenuState\n";
return true;
}
bool LevelState::onExit()
{
for(int i = 0; i < m_gameObjects.size(); i++)
{
m_gameObjects[i]->clean();
}
m_gameObjects.clear();
TheTextureManager::Instance()->clearFromTextureMap("bg");
TheTextureManager::Instance()->clearFromTextureMap("level1");
TheTextureManager::Instance()->clearFromTextureMap("level2");
TheTextureManager::Instance()->clearFromTextureMap("level3"); //my add
cout << "exiting MenuState\n";
return true;
}
void LevelState::s_ToLevel1()
{
GameState *p = new PlayState();
p->setS(LEVEL1);
TheGame::Instance()->getStateMachine()->changeState(p);
}
void LevelState::s_ToLevel2()
{
GameState *p = new PlayState();
p->setS(LEVEL2);
TheGame::Instance()->getStateMachine()->changeState(p);
}
void LevelState::s_ToLevel3()
{
GameState *p = new PlayState();
p->setS(LEVEL3);
TheGame::Instance()->getStateMachine()->changeState(p);
}

LoaderParams

LoaderParams.h

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
#ifndef _LLLL_
#define _LLLL_
#include "utility.h"
class LoaderParams
{
public:
LoaderParams(int x, int y, int width, int height, string
textureID) : m_x(x), m_y(y), m_width(width), m_height(height), m_textureID(textureID) {}
int getX() const { return m_x; }
int getY() const { return m_y; }
int getWidth() const { return m_width; }
int getHeight() const { return m_height; }
string getTextureID() const { return m_textureID; }
private:
int m_x;
int m_y;
int m_width;
int m_height;
string m_textureID;
};
#endif
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
#ifndef __MBMBMB__
#define __MBMBMB__
#include "GameObject.h"
class MenuButton : public GameObject
{
public:
MenuButton(const LoaderParams* pParams, void (*callback)());
virtual void update();
/*virtual void draw(); */
private:
enum button_state
{
MOUSE_OUT = 0,
MOUSE_OVER = 1,
CLICKED = 2
};
void (*m_callback)();
bool m_bReleased;
};
#endif
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
#include "MenuButton.h"
#include "InputHandler.h"
MenuButton::MenuButton(const LoaderParams* pParams, void (*callback)()) : GameObject(pParams), m_callback(callback),
m_bReleased(false) {}
//void MenuButton::draw()
//{}
void MenuButton::update()
{
Vector2D* pMousePos = TheInputHandler::Instance()->getMousePosition();
if(pMousePos->getX() < (m_position.getX() + m_width)
&& pMousePos->getX() > m_position.getX()
&& pMousePos->getY() < (m_position.getY() + m_height)
&& pMousePos->getY() > m_position.getY())
{
if(TheInputHandler::Instance()->getMouseButtonState(LEFT)
/*&& m_bReleased*/)
{
m_currentFrame = CLICKED;
m_callback(); // call our callback function
/*m_bReleased = false;*/
}
else if(!TheInputHandler::Instance()->getMouseButtonState(LEFT))
{
/*m_bReleased = true;*/
m_currentFrame = MOUSE_OVER;
}
}
else
{
m_currentFrame = MOUSE_OUT;
}
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
#ifndef __MSMSMS__
#define __MSMSMS__
#include "GameState.h"
#include "GameObject.h"
class MenuState : public GameState
{
public:
virtual void update();
virtual void render();
virtual bool onEnter();
virtual bool onExit();
virtual std::string getStateID() const { return s_menuID; }
// call back functions for menu items
private:
static void s_menuToPlay();
static void s_exitFromMenu();
private:
static const std::string s_menuID;
vector<GameObject*> m_gameObjects;
};
#endif
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
#include "MenuState.h"
#include "TextureManager.h"
#include "Game.h"
#include "MenuButton.h"
#include "GameStateMachine.h"
#include "PlayState.h"
#include "BackGround.h"
#include "InputHandler.h"
#include "LevelState.h"
const string MenuState::s_menuID = "MENU";
void MenuState::update()
{
for(int i = 0; i < m_gameObjects.size(); i++)
{
m_gameObjects[i]->update();
}
}
void MenuState::render()
{
for(int i = 0; i < m_gameObjects.size(); i++)
{
m_gameObjects[i]->draw();
}
}
bool MenuState::onEnter()
{
TheInputHandler::Instance()->reset();
if(!TheTextureManager::Instance()->load("setting/f.png",
"first", TheGame::Instance()->getRenderer()))
{
return false;
}
if(!TheTextureManager::Instance()->load("setting/play.png",
"playbutton", TheGame::Instance()->getRenderer()))
{
return false;
}
if(!TheTextureManager::Instance()->load("setting/exit.png",
"exitbutton", TheGame::Instance()->getRenderer()))
{
return false;
}
GameObject* button1 = new MenuButton(new LoaderParams(100, 225, 250,
63, "playbutton"), s_menuToPlay);
GameObject* button2 = new MenuButton(new LoaderParams(100, 375, 250,
63, "exitbutton"), s_exitFromMenu);
GameObject* back = new BackGround(new LoaderParams(0, 0, WINDOW_WIDTH, WINDOW_HEIGHT, "first"));
m_gameObjects.push_back(back);
m_gameObjects.push_back(button1);
m_gameObjects.push_back(button2);
cout << "entering MenuState\n";
return true;
}
bool MenuState::onExit()
{
for(int i = 0; i < m_gameObjects.size(); i++)
{
m_gameObjects[i]->clean();
}
m_gameObjects.clear();
TheTextureManager::Instance()->clearFromTextureMap("first"); //my add
TheTextureManager::Instance()->clearFromTextureMap("playbutton");
TheTextureManager::Instance()->clearFromTextureMap("exitbutton");
cout << "exiting MenuState\n";
return true;
}
void MenuState::s_menuToPlay()
{
TheGame::Instance()->getStateMachine()->changeState(new LevelState());
}
void MenuState::s_exitFromMenu()
{
TheGame::Instance()->quit();
}

PauseState

PauseState.h

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
#ifndef __PPSPPS__
#define __PPSPPS__
#include "GameState.h"
#include "GameObject.h"
class PauseState : public GameState
{
public:
virtual void update();
virtual void render();
virtual bool onEnter();
virtual bool onExit();
virtual string getStateID() const { return s_pauseID; }
private:
static void s_pauseToMain();
static void s_resumePlay();
static const string s_pauseID;
vector<GameObject*> m_gameObjects;
};
#endif

PauseState.cpp

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
#include "Enemy.h"
void Enemy::update()
{
m_x = int ((SDL_GetTicks() / 10));
m_currentFrame = int(((SDL_GetTicks() / 100) % 6));
}
//void Enemy::draw(SDL_Renderer* pRenderer)
//{
// GameObject::draw(pRenderer);
//}
//void Enemy::load(int x, int y, int width, int height, string
// textureID)
//{
// GameObject::load(x, y, width, height, textureID);
//}

Player

Player.h

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
#ifndef __PLA__
#define __PLA__
#include "GameObject.h"
#include "Vector2D.h"
class Player : public GameObject
{
public:
Player(const LoaderParams* pParams, Vector2D* V , int n=1 ,int t = 200, int initial = 0);
virtual void update();
/*virtual void setN(int n) { m_n = n; }
virtual void setVelocity(float x, float y) { m_velocity.setX(x); m_velocity.setY(y); }*/
virtual ~Player() {}
/*void clean() {}*/
private:
/*static int id;*/
Vector2D m_velocity;
int m_t; //m_t越大,动作速度越小
int m_n;
int m_init;
};
#endif

Player.cpp

1
2
3
4
5
6
7
8
9
10
11
12
13
14
#include "Player.h"
Player::Player(const LoaderParams* pParams, Vector2D* V, int n, int t , int initial) :
GameObject(pParams), m_n(n), m_t(t), m_init(initial)
{
m_velocity.setX(V->getX());
m_velocity.setY(V->getY());
}
void Player::update()
{
m_position += m_velocity;
m_currentFrame = int( (( m_init + (SDL_GetTicks() / m_t )) % m_n ) );
}

PlayState

PlayState.h

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
#ifndef __PSPSPS__
#define __PSPSPS__
#include "GameState.h"
#include "GameObject.h"
class PlayState : public GameState
{
public:
virtual void update();
virtual void render();
virtual bool onEnter();
virtual bool onExit();
virtual void setS(int s) { m_s = s; }
virtual string getStateID() const { return s_playID; }
private:
static const string s_playID;
int p_id; //若改成全局变量,会出错???
int m_s; //哪个难度的游戏状态
vector<GameObject*> m_gameObjects;
};
#endif

PlayState.cpp

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
#include "PlayState.h"
#include "TextureManager.h"
#include "Game.h";
#include "BackGround.h"
#include "InputHandler.h"
#include "PauseState.h"
#include "GameOverState.h"
#include "LevelState.h"
const string PlayState::s_playID = "PLAY";
void PlayState::update()
{
if(TheInputHandler::Instance()->getMouseButtonState(RIGHT))
{
TheGame::Instance()->getStateMachine()->pushState(new PauseState());
}
if(m_s == LEVEL3)
{
if(InputHandler::Instance()->getMouseButtonState(LEFT))
{
SDL_Delay(1000);
Vector2D *mou_pos = TheInputHandler::Instance()->getMousePosition();
//鼠标点击位置
int xpos = mou_pos->getX();
int ypos = mou_pos->getY();
Vector2D tar_pos = m_gameObjects[1]->getPosition();
//目标位置
int _xpos_ = tar_pos.getX();
int _ypos_ = tar_pos.getY();
int width = m_gameObjects[1]->getWidth();
int height = m_gameObjects[1]->getHeight();
if(xpos > _xpos_ && xpos < (_xpos_ + width) && ypos > _ypos_ && ypos < (_ypos_ + height))
{
GameState * o = new GameOverState(WIN);
o->setPS(m_s);
TheGame::Instance()->getStateMachine()->changeState(o);
}
else
{
GameState * o = new GameOverState(LOSE);
o->setPS(m_s);
TheGame::Instance()->getStateMachine()->changeState(o);
}
}
}
else
{
if(TheInputHandler::Instance()->getMouseButtonState(LEFT) &&
p_id < m_gameObjects.size())
{
p_id++;
if(p_id == m_gameObjects.size())
{
SDL_Delay(1000);
int tmpFrame = m_gameObjects[1]->getFrame();
for(int i = 2 ; i < p_id; i++)
{
if(m_gameObjects[i]->getFrame() != tmpFrame)
{
GameState * o = new GameOverState(LOSE);
o->setPS(m_s);
TheGame::Instance()->getStateMachine()->changeState(o);
return;
}
}
GameState * o = new GameOverState(WIN);
o->setPS(m_s);
TheGame::Instance()->getStateMachine()->changeState(o);
}
TheInputHandler::Instance()->reset();
}
}
for(int i = p_id; i < m_gameObjects.size(); i++)
{
m_gameObjects[i]->update();
}
//走出窗口,认为游戏失败
for(int i = 1; i < m_gameObjects.size(); i++)
{
int xpos = m_gameObjects[i]->getPosition().getX();
int ypos = m_gameObjects[i]->getPosition().getY();
if( !( (xpos <= WINDOW_WIDTH) && (xpos >= 0) && (ypos <= WINDOW_HEIGHT) && (ypos >= 0) ) )
{
GameState * o = new GameOverState(LOSE);
o->setPS(m_s);
TheGame::Instance()->getStateMachine()->changeState(o);
}
}
}
void PlayState::render()
{
for(int i = 0; i < m_gameObjects.size(); i++)
{
m_gameObjects[i]->draw();
}
}
bool PlayState::onEnter()
{
PlayState::p_id = 1;
TheInputHandler::Instance()->reset();
if(m_s == LEVEL1)
{
if(!TheTextureManager::Instance()->load("setting/d.png",
"c", TheGame::Instance()->getRenderer()))
{
return false;
}
if(!TheTextureManager::Instance()->load("setting/back.png",
"back", TheGame::Instance()->getRenderer()))
{
return false;
}
GameObject* back = new BackGround(new LoaderParams(0, 0, WINDOW_WIDTH, WINDOW_HEIGHT, "back"));
GameObject* player1 = new Player(new LoaderParams(100, 100, 71, 90, "c"), new Vector2D(2.0, 0.0), 4, 500, 1);
GameObject* player2 = new Player(new LoaderParams(100, 300, 71, 90, "c"), new Vector2D(1.0, 0.0), 4, 500, 3);
m_gameObjects.push_back(back);
m_gameObjects.push_back(player1);
m_gameObjects.push_back(player2);
}
else if(m_s == LEVEL2)
{
if(!TheTextureManager::Instance()->load("setting/a.png",
"c", TheGame::Instance()->getRenderer()))
{
return false;
}
if(!TheTextureManager::Instance()->load("setting/third.png",
"back", TheGame::Instance()->getRenderer()))
{
return false;
}
GameObject* back = new BackGround(new LoaderParams(0, 0, WINDOW_WIDTH, WINDOW_HEIGHT, "back"));
GameObject* player1 = new Player(new LoaderParams(50, 50, 128, 82, "c"), new Vector2D(1.0, 1.0), 6, 500, 0);
GameObject* player2 = new Player(new LoaderParams(50, 300, 128, 82, "c"), new Vector2D(1.0,0.0), 6, 200, 3);
GameObject* player3 = new Player(new LoaderParams(50, 600, 128, 82, "c"), new Vector2D(1.0,-1.0), 6, 300, 5);
m_gameObjects.push_back(back);
m_gameObjects.push_back(player1);
m_gameObjects.push_back(player2);
m_gameObjects.push_back(player3);
}
else if(m_s == LEVEL3)
{
if(!TheTextureManager::Instance()->load("setting/z.png",
"c", TheGame::Instance()->getRenderer()))
{
return false;
}
if(!TheTextureManager::Instance()->load("setting/second.png",
"back", TheGame::Instance()->getRenderer()))
{
return false;
}
GameObject* back = new BackGround(new LoaderParams(0, 0, WINDOW_WIDTH, WINDOW_HEIGHT, "back"));
GameObject* player[4];
player[0] = new Player(new LoaderParams(50, 50, 40, 40, "c"), new Vector2D(20.0, 8.0), 1, 100);
player[1] = new Player(new LoaderParams(50, 550, 40, 40, "c"), new Vector2D(0.0, -10.0), 1, 100);
player[2] = new Player(new LoaderParams(900, 550, 40, 40, "c"), new Vector2D(-15.0, 0.0), 1, 100);
player[3] = new Player(new LoaderParams(550, 550, 40, 40, "c"), new Vector2D(8.0, -10.0), 1, 100);
int x = rand()%4;
m_gameObjects.push_back(back);
m_gameObjects.push_back(player[x]);
}
std::cout << "entering PlayState\n";
return true;
}
bool PlayState::onExit()
{
for(int i = 0; i < m_gameObjects.size(); i++)
{
m_gameObjects[i]->clean();
}
m_gameObjects.clear();
TheTextureManager::Instance()->clearFromTextureMap("c");
TheTextureManager::Instance()->clearFromTextureMap("back");
std::cout << "exiting PlayState\n";
return true;
}

Text

Text.h

1
2
3
4
5
6
7
8
9
10
#ifndef __TTTTTT__
#define __TTTTTT__
class Text : public GameObject
{
public:
};
#endif

TextureManager

TextureManager.h

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
#ifndef __TEXTUREMANAGER__
#define __TEXTUREMANAGER__
#include "utility.h"
class TextureManager
{
public:
bool load(string fileName, string id, SDL_Renderer* pRenderer);
void draw(string id, int x, int y, int width, int height, SDL_Renderer* pRenderer, SDL_RendererFlip flip = SDL_FLIP_NONE);
void drawFrame(string id, int x, int y, int width, int height,
int currentRow, int currentFrame, SDL_Renderer* pRenderer, SDL_RendererFlip flip = SDL_FLIP_NONE);
static TextureManager* Instance();
void clearFromTextureMap(string id);
private:
TextureManager() {}
private:
static TextureManager* s_pInstance;
map<string, SDL_Texture*> m_textureMap;
};
typedef TextureManager TheTextureManager;
#endif

TextureManager.cpp

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
#include "TextureManager.h"
TextureManager* TextureManager::s_pInstance = 0;
TextureManager* TextureManager::Instance()
{
if(s_pInstance == 0)
{
s_pInstance = new TextureManager();
return s_pInstance;
}
return s_pInstance;
}
bool TextureManager::load(string fileName, string id, SDL_Renderer* pRenderer)
{
SDL_Surface* pTempSurface = IMG_Load(fileName.c_str());
if(pTempSurface == 0)
{
return false;
}
SDL_Texture* pTexture = SDL_CreateTextureFromSurface(pRenderer, pTempSurface);
SDL_FreeSurface(pTempSurface);
if(pTexture != 0)
{
m_textureMap[id] = pTexture;
return true;
}
return false;
}
void TextureManager::draw(string id, int x, int y, int width, int height,
SDL_Renderer* pRenderer ,SDL_RendererFlip flip)
{
SDL_Rect srcRect;
SDL_Rect destRect;
srcRect.x = 0;
srcRect.y = 0;
srcRect.w = destRect.w = width;
srcRect.h = destRect.h = height;
destRect.x = x;
destRect.y = y;
SDL_RenderCopyEx(pRenderer, m_textureMap[id], &srcRect, &destRect, 0, 0, flip);
}
void TextureManager::drawFrame(string id, int x, int y, int width, int height,
int currentRow, int currentFrame, SDL_Renderer* pRenderer, SDL_RendererFlip flip)
{
SDL_Rect srcRect;
SDL_Rect destRect;
srcRect.x = width * currentFrame;
srcRect.y = height * (currentRow - 1);
srcRect.w = destRect.w = width;
srcRect.h = destRect.h = height;
destRect.x = x;
destRect.y = y;
SDL_RenderCopyEx(pRenderer, m_textureMap[id], &srcRect, &destRect, 0, 0, flip);
}
void TextureManager::clearFromTextureMap(string id)
{
m_textureMap.erase(id);
}

utility

utility.h

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
#ifndef __UTILITY__
#define __UTILITY__
#include <iostream>
#include <string>
#include <map>
#include <string.h>
#include <time.h>
#include <math.h>
#include <vector>
#include <stdlib.h>
#include "SDL.h"
#include "SDL_image.h"
using namespace std ;
#define WINDOW_WIDTH 1000
#define WINDOW_HEIGHT 650
#endif

Vector2D

Vector2D.h

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
#ifndef __VDVD__
#define __VDVD__
#include "utility.h"
class Vector2D
{
public:
Vector2D(): m_x(0.0), m_y(0.0) {}
Vector2D(float x, float y): m_x(x), m_y(y) {}
Vector2D(const Vector2D& V) { m_x = V.m_x ; m_y = V.m_y ; }
float getX() { return m_x; }
float getY() { return m_y; }
void setX(float x) { m_x = x; }
void setY(float y) { m_y = y; }
float length() { return sqrt(m_x * m_x + m_y * m_y); }
//void operator=(const Vector2D& v2);
Vector2D operator+(const Vector2D& v2) const;
friend Vector2D& operator+=(Vector2D& v1, const Vector2D& v2);
Vector2D operator*(float scalar);
Vector2D& operator*=(float scalar);
Vector2D operator-(const Vector2D& v2) const;
friend Vector2D& operator-=(Vector2D& v1, const Vector2D& v2);
Vector2D operator/(float scalar);
Vector2D& operator/=(float scalar);
void normalize();
private:
float m_x;
float m_y;
};
#endif

Vector2D.cpp

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
#include "Vector2D.h"
Vector2D Vector2D::operator+(const Vector2D& v2) const
{
return Vector2D(m_x + v2.m_x, m_y + v2.m_y);
}
Vector2D& operator+=(Vector2D& v1, const Vector2D& v2){
v1.m_x += v2.m_x;
v1.m_y += v2.m_y;
return v1;
}
Vector2D Vector2D::operator*(float scalar){
return Vector2D(m_x * scalar, m_y * scalar);
}
Vector2D& Vector2D::operator*=(float scalar){
m_x *= scalar;
m_y *= scalar;
return *this;
}
Vector2D Vector2D::operator-(const Vector2D& v2) const{
return Vector2D(m_x - v2.m_x, m_y - v2.m_y);
}
Vector2D& operator-=(Vector2D& v1, const Vector2D& v2){
v1.m_x -= v2.m_x;
v1.m_y -= v2.m_y;
return v1;
}
Vector2D Vector2D::operator/(float scalar)
{
return Vector2D(m_x / scalar, m_y / scalar);
}
Vector2D& Vector2D::operator/=(float scalar)
{
m_x /= scalar;
m_y /= scalar;
return *this;
}
void Vector2D::normalize()
{
float l = length();
if ( l > 0) // we never want to attempt to divide by 0
{
(*this) *= 1 / l;
}
}

项目成果

菜单界面

这里写图片描述

关卡选择界面

这里写图片描述

关卡一

这里写图片描述

关卡二

这里写图片描述

关卡三

这里写图片描述

Game Over

这里写图片描述

You Win

这里写图片描述

Resume

这里写图片描述


*特别说明

我最近把我所写的代码都上传到github上了,由于代码文件过多,建议读者去github上clone一下,具体成果读者可以去github上查看README.pdf,内附如何打开应用程序的说明。

https://github.com/TonyZhang94/Projects-Base-On-SDL2.git