C ++でゲームを書く、パート3/3-ジャンルの古典
こんにちは、Habrahabr!
ハブでゲームを作成することに関する多くのレッスンはありません。国内の開発者をサポートしてみませんか?
SDLを使用してC ++でゲームを作成する方法を教えるレッスンを紹介します。
知っておくべきこと
- 少なくともC ++の基本的な知識(Visual Studioを使用します)
- 忍耐
この部分は何についてですか?
- すべてのゲームのフレームワークを作成し、SDLをレンダラーとして使用します。 これはグラフィックスのライブラリです。
次の投稿では、さらなるアクションがあります。これは単なる準備です:)
SDLを選ぶ理由
私は、このライブラリを最も簡単で習得しやすいものとして選択しました。 確かに、OpenGLまたはDirectXに関する最初の記事を読んでから、ヘビの100,000の再版までに多くの時間がかかります。
これで開始できます。
1.1。 開始しました
公式サイトからSDLをダウンロードします。
Visual StudioでWin32プロジェクトを作成し、SDLライブラリとincludsを接続します(これを行う方法がわからない場合は、Googleがお手伝いします!)
マルチバイト文字エンコーディングを使用する必要もあります。 これを行うには、[プロジェクト]-> [プロパティ]-> [構成プロパティ]-> [文字セット]-> [マルチバイトエンコーディングを使用]に移動します。
main.cppファイルを作成します
#include <Windows.h> int WINAPI WinMain(HINSTANCE,HINSTANCE,LPSTR,int) { return 0; }
彼はまだ何もしていません。
死体の王と神-ゲームクラス
Game.h
#ifndef _GAME_H_ #define _GAME_H_ class Game { private: bool run; public: Game(); int Execute(); void Exit(); }; #endif
Game.cpp
#include "Game.h" Game::Game() { run = true; } int Game::Execute() { while(run); return 0; } void Game::Exit() { run = false; }
Project.hファイルを作成します。これは将来非常に役立ちます。
#ifndef _PROJECT_H_ #define _PROJECT_H_ #include <Windows.h> #include "Game.h" #endif
main.cppを変更する
#include "Project.h" int WINAPI WinMain(HINSTANCE,HINSTANCE,LPSTR,int) { Game game; return game.Execute(); }
もう少し良くなりましたが、それでもどうにか多くはありません。
1.2。 グラフィックス
最大2つのクラスを作成します-グラフィックスを描画するためのグラフィックスと画像を描画するための画像
Graphics.h
#ifndef _GRAPHICS_H_ #define _GRAPHICS_H_ #include "Project.h" #include "Image.h" class Image; class Graphics { private: SDL_Surface* Screen; public: Graphics(int width, int height); Image* NewImage(char* file); Image* NewImage(char* file, int r, int g, int b); bool DrawImage(Image* img, int x, int y); bool DrawImage(Image* img, int x, int y, int startX, int startY, int endX, int endY); void Flip(); }; #endif
Image.h
#ifndef _IMAGE_H #define _IMAGE_H #include "Project.h" class Image { private: SDL_Surface* surf; public: friend class Graphics; int GetWidth(); int GetHeight(); }; #endif
Project.hを変更します
#ifndef _PROJECT_H_ #define _PROJECT_H_ #pragma comment(lib,"SDL.lib") #include <Windows.h> #include <SDL.h> #include "Game.h" #include "Graphics.h" #include "Image.h" #endif
SDL_Surface-画像情報を保存するためのSDLのクラス
グラフィックスを検討する
NewImage-画像を読み込むための2つのオプションがあります。 最初のオプションは単に画像をロードし、その後の2番目のオプションも画像に透明度を与えます。 画像に赤い背景がある場合は、r = 255、g = 0、b = 0を入力します
DrawImage-絵を描くための2つのオプション。 最初の部分は全体を描き、2番目の部分は全体を描きます。 startX、startY-画像の一部の開始の座標。 endX、endY-画像部分の終了座標。 この描画方法は、画像アトラスが使用される場合に使用されます。 アトラスの例を次に示します。
(interesnoe.info Webリソースから取得した画像)
画像を考慮する
彼は表面を保持し、プライベートクラスのメンバーにGraphicsクラスへのアクセスを許可し、表面を変更します。
これは基本的にSDL_Surfaceのラッパーです。 彼はまた、画像のサイズを示します。
Graphics.cpp
#include "Graphics.h" Graphics::Graphics(int width, int height) { SDL_Init(SDL_INIT_EVERYTHING); Screen = SDL_SetVideoMode(width,height,32,SDL_HWSURFACE|SDL_DOUBLEBUF); } Image* Graphics::NewImage(char* file) { Image* image = new Image(); image->surf = SDL_DisplayFormat(SDL_LoadBMP(file)); return image; } Image* Graphics::NewImage(char* file, int r, int g, int b) { Image* image = new Image(); image->surf = SDL_DisplayFormat(SDL_LoadBMP(file)); SDL_SetColorKey(image->surf, SDL_SRCCOLORKEY | SDL_RLEACCEL, SDL_MapRGB(image->surf->format, r, g, b)); return image; } bool Graphics::DrawImage(Image* img, int x, int y) { if(Screen == NULL || img->surf == NULL) return false; SDL_Rect Area; Area.x = x; Area.y = y; SDL_BlitSurface(img->surf, NULL, Screen, &Area); return true; } bool Graphics::DrawImage(Image* img, int x, int y, int startX, int startY, int endX, int endY) { if(Screen == NULL || img->surf == NULL) return false; SDL_Rect Area; Area.x = x; Area.y = y; SDL_Rect SrcArea; SrcArea.x = startX; SrcArea.y = startY; SrcArea.w = endX; SrcArea.h = endY; SDL_BlitSurface(img->surf, &SrcArea, Screen, &Area); return true; } void Graphics::Flip() { SDL_Flip(Screen); SDL_FillRect(Screen,NULL, 0x000000); }
コンストラクターで、SDLが初期化され、画面が作成されます。
Flip関数は、画像をレンダリングした後に毎回呼び出す必要があります。画面上で結果を表し、さらにレンダリングするために画面を黒でクリーンアップします。
残りの機能はほとんど関心がありません。自分で理解することをお勧めします
Image.cpp
#include "Image.h" int Image::GetWidth() { return surf->w; } int Image::GetHeight() { return surf->h; }
いいえ、あなたはすべてを正しくやっています、このファイルは次のようになります:)
Game.h、Game.cpp、main.cppを変更する必要があります
Game.h
#ifndef _GAME_H_ #define _GAME_H_ #include "Project.h" class Graphics; class Game { private: bool run; Graphics* graphics; public: Game(); int Execute(int width, int height); void Exit(); }; #endif
ここで、グラフィックスへのポインターを追加し、実行で画面サイズを追加します
Game.cpp
#include "Game.h" Game::Game() { run = true; } int Game::Execute(int width, int height) { graphics = new Graphics(width,height); while(run); SDL_Quit(); return 0; } void Game::Exit() { run = false; }
特別なことはありません。SDL_Quit関数をスキップしてSDLをクリアします
main.cpp
#include "Project.h" int WINAPI WinMain(HINSTANCE,HINSTANCE,LPSTR,int) { Game game; return game.Execute(500,350); }
ここでは、500 x 350のスクリーンを作成します。
1.3。 入る
キーボード入力で作業する必要があります
Input.hを作成する
#ifndef _INPUT_H_ #define _INPUT_H_ #include "Project.h" class Input { private: SDL_Event evt; public: void Update(); bool IsMouseButtonDown(byte key); bool IsMouseButtonUp(byte key); POINT GetButtonDownCoords(); bool IsKeyDown(byte key); bool IsKeyUp(byte key); byte GetPressedKey(); bool IsExit(); }; #endif
SDL_Eventは何らかのイベントのクラスです。サイクルごとにこのクラスのオブジェクトを作成しないように、入力に保持します
以下は、特に関心のないメソッドです。 注:キーが押されたときにDownで終わるメソッドが呼び出され、呼び出されるとEndで呼び出されます。
Input.cpp
#include "Input.h" void Input::Update() { while(SDL_PollEvent(&evt)); } bool Input::IsMouseButtonDown(byte key) { if(evt.type == SDL_MOUSEBUTTONDOWN) if(evt.button.button == key) return true; return false; } bool Input::IsMouseButtonUp(byte key) { if(evt.type == SDL_MOUSEBUTTONUP) if(evt.button.button == key) return true; return false; } POINT Input::GetButtonDownCoords() { POINT point; point.x = evt.button.x; point.y = evt.button.y; return point; } bool Input::IsKeyDown(byte key) { return (evt.type == SDL_KEYDOWN && evt.key.keysym.sym == key); } bool Input::IsKeyUp(byte key) { return (evt.type == SDL_KEYUP && evt.key.keysym.sym == key); } byte Input::GetPressedKey() { return evt.key.keysym.sym; } bool Input::IsExit() { return (evt.type == SDL_QUIT); }
ここでは、Update関数でイベントオブジェクトを処理し、残りの関数は単にイベントのタイプとその値をチェックします。
Game.hとGame.cppを変更します
#ifndef _GAME_H_ #define _GAME_H_ #include "Project.h" #include "Graphics.h" class Graphics; #include "Input.h" class Input; class Game { private: bool run; Graphics* graphics; Input* input; public: Game(); int Execute(int width, int height); Graphics* GetGraphics(); Input* GetInput(); void Exit(); }; #endif
ご覧のとおり、Inputへのポインターを追加し、GraphicsおよびInput returnメソッドを作成しました
Game.cpp
#include "Game.h" Game::Game() { run = true; } int Game::Execute(int width, int height) { graphics = new Graphics(width,height); input = new Input(); while(run) { input->Update(); } delete graphics; delete input; SDL_Quit(); return 0; } Graphics* Game::GetGraphics() { return graphics; } Input* Game::GetInput() { return input; } void Game::Exit() { run = false; }
1.4。 まとめ
これが最初のレッスンでした。 あなたがこの場所に到着した場合、私はあなたを祝福します! プログラマーに内在する意志があります:)さらに学ぶために、その後のレッスンについては記事の冒頭のリンクを参照してください!
すべての質問については、PMに連絡してください。ハブに登録できない場合は、メールizarizar@mail.ruにご連絡ください。