SDL2で音を鳴らす
前回はウィンドウ上に画像を表示する方法を調べた。
今回はSDL2を使用して音を鳴らす方法を調べて行きたい。
音楽ファイルの準備
今回は、.ogg
ファイルと.wav
の2種類の音源を用意した。
.ogg
は、.mp3
のような圧縮ファイルらしいが同じビットレートだと.mp3
より音質がいいらしい。
.wav
ファイルは音を非常に高音質に録音できる形式で、音を録音する際の「原音」の形式としてよく使われてるとのこと。 詳細はググって見てもらえればと思う。
今回用意したファイルは-> 魔王魂というフリー素材を扱っているサイトからダウロードさせてもらった。
いずれは音楽も作りたいので調べたところ、フリーのDTMソフトである-> LMMS というソフトが良さそうだった。 今回を皮切りにしてDTMも少しずつ学んでいこうと思う。
LMMS
を使用しての音源ファイルの作成については別記事でまとめながら覚えてていきたい。
音を鳴らす
では、さっそく、音を鳴らすためのコードを書いていこう。
ファイルの階層はこんな感じにしてある。
sdl2_test/ |--sdl2_mixer.c |--jingle.wav |--piano.ogg
調べて書いたところ以下のようなソースになった。
音楽関連の用語の知識がないためにマニュアルを見てもいまいちピンと来なかったりするが
以下のソースでひとまず音を鳴らすことはできた。
#include <SDL2/SDL.h> #include <SDL2/SDL_mixer.h> #define WAV_PATH "jingle.wav" #define MUS_PATH "piano.ogg" Mix_Chunk *wave = NULL; Mix_Music *music = NULL; int main(int argc, char* argv[]){ // Initialize SDL. if (SDL_Init(SDL_INIT_AUDIO) < 0) return -1; // Initialize SDL_mixer if( Mix_OpenAudio( 22050, MIX_DEFAULT_FORMAT, 2, 4096 ) == -1 ) return -1; // 効果音のロード wave = Mix_LoadWAV(WAV_PATH); if (wave == NULL) return -1; // 音楽ファイルのロード music = Mix_LoadMUS(MUS_PATH); if (music == NULL) return -1; // 効果音を一度だけ再生 if ( Mix_PlayChannel(-1, wave, 0) == -1 ) return -1; // 音楽を無限ループで再生 if ( Mix_PlayMusic( music, -1) == -1 ) return -1; while ( Mix_PlayingMusic() ) ; Mix_FreeChunk(wave); Mix_FreeMusic(music); // quit SDL_mixer Mix_CloseAudio(); return 0; }
使用した関数のメモ。
-> Mix_Chunk
-> Mix_Music
-> Mix_OpenAudio
-> Mix_LoadWAV
-> Mix_LoadMUS
-> Mix_PlayChannel
-> Mix_PlayMusic
-> Mix_PlayingMusic
-> Mix_FreeChunk
-> Mix_FreeMusic
-> Mix_CloseAudio
コンパイル
gcc -g -o sdl2_mixer sdl2_mixer.c `sdl2-config --cflags --libs` -lSDL2_mixer
このような形でコンパイルを行う。
文字は-lSDL2_ttf
を追加、画像の場合は-lSDL2_image
を追加、
音源の場合は-lSDL2_mixer
を使用する。
実行結果
./sdl2_mixer
で実行する。
無事に音を鳴らすことができた。
終わりに
わからない部分がまだ多いがひとまず音を鳴らすことができた。
次回は画像に戻ってアニメーションの表示を行ってみようと思う。
SDL2で画像を表示する
前回はウィンドウ上に文字を表示する方法を調べた。
今回はウィンドウ上に画像を表示する方法を調べていこうと思う。
表示する画像の用意
今回表示に使う画像は以下である。
この画像は、KonaLinuxに標準で入っていたAzPainterを使用して作成した。
WEBで探した猫を真似してドット絵打ってみたけど下手くそなのはご愛嬌。これから頑張っていこうと思う。
AzPainterはLinuxでフリー使用できるペイントソフトで、私が使用している古いノートPC(どれくらい古いかは環境設定の項目参照)でもサクサク動く軽さが魅力的である。詳細は-> ここを確認されたし。
AzPainterを使用してドット絵を書くために調べたことは、後日別記事にまとめようと思う。
オリジナルを打てるように頑張っていきたい。
これを、表示するためにひとまずテストコードと同じ階層に置いておく。階層はこんな感じ
sdl2_test/ |--sdl2_img.c |--cat.bmp
ちなみに、画像の背景色はRGB(255, 0, 255)になっている。
これは、SDL2の関数を用いて背景色を透過するためにドット絵に使用しない色を指定している。
画像の表示
#include <SDL2/SDL.h> #include <SDL2/SDL_image.h> #include <stdio.h> const int SCREEN_WIDTH = 640; const int SCREEN_HEIGHT = 480; int main( int argc, char* args[] ) { SDL_Window* window = NULL; SDL_Renderer *renderer = NULL; SDL_Surface *image = NULL; SDL_Texture *image_texture = NULL; // 今回は使用していないがJPGとPNG形式の画像を読み込めるようにするには以下を設定する int flags=IMG_INIT_JPG|IMG_INIT_PNG; int initted=IMG_Init(flags); if(initted&flags != flags) { printf("IMG_Init: JPGとPNGの読み込みの初期化に失敗した!\n"); printf("IMG_Init: %s\n", IMG_GetError()); } //Initialize SDL if( SDL_Init( SDL_INIT_VIDEO ) < 0 ) { printf( "SDL could not initialize! SDL_Error: %s\n", SDL_GetError() ); } else { //Create window window = SDL_CreateWindow( "DRAW IMAGE TEST", SDL_WINDOWPOS_UNDEFINED, SDL_WINDOWPOS_UNDEFINED, SCREEN_WIDTH, SCREEN_HEIGHT, SDL_WINDOW_SHOWN ); if( window == NULL ) { printf( "Window could not be created! SDL_Error: %s\n", SDL_GetError() ); } else { renderer = SDL_CreateRenderer(window, -1, SDL_RENDERER_ACCELERATED); // 画像の読み込み image = IMG_Load("cat.bmp"); if(!image) { printf("IMG_Load: %s\n", IMG_GetError()); } // 透過色の設定 SDL_SetColorKey( image, SDL_TRUE, SDL_MapRGB(image->format, 255, 0, 255)); image_texture = SDL_CreateTextureFromSurface(renderer, image); int iw,ih; SDL_QueryTexture(image_texture, NULL, NULL, &iw, &ih); SDL_Rect imageRect=(SDL_Rect){0,0,iw,ih}; SDL_Rect drawRect=(SDL_Rect){300,220,iw,ih}; SDL_SetRenderDrawColor(renderer, 200, 200, 200, 255); SDL_RenderClear(renderer); SDL_RenderCopy(renderer, image_texture, &imageRect, &drawRect); SDL_RenderPresent(renderer); SDL_Delay( 3000 ); } } IMG_Quit(); SDL_FreeSurface(image); SDL_DestroyTexture(image_texture); SDL_DestroyRenderer(renderer); SDL_DestroyWindow(window); SDL_Quit(); return 0; }
新規に使用した関数は以下。メモっておく。
-> IMG_Init
-> IMG_Load
-> SDL_SetColorKey
-> SDL_SetRenderDrawColor
-> IMG_Quit
コンパイル
gcc -g -o sdl2_img sdl2_img.c `sdl2-config --cflags --libs` -lSDL2_image
このような形でコンパイルを行う。前回、文字を表示した時は-lSDL2_ttf
を追加したが、画像の場合は-lSDL2_image
を追加する必要がある。
実行結果
./sdl2_img
で実行する。
無事に画像を背景色透過で表示させることができた。
終わりに
文字、画像、と来たので次回は音を鳴らす方法を調べようと思う。今回はこれで以上!
SDL2で文字を表示する
先日は、C言語+SDL2でプログラムをするための環境を整えてウィンドウを表示するコードを書いた。
今回はそのウィンドウ上に文字を表示してみようと思う。
ちなみに、SDL2の日本語リファレンスは-> ここを参照。
使用する関数はリファレンスを確認しながら使おう思う。
フォントの用意
まずは、文字を表示するためにフォントを用意する。
ゲームっぽいフォントを探していたら以下のフォントが見つかった。
-> PixelMplus 8bitビットマップふうフリーフォント - itouhiroはてなブログ
これを、ダウンロードして展開しテストコードと同じ階層に置いておく。階層はこんな感じ。
sdl2_test/ |--sdl2_ttf.c |--PixelMplus12-Regular.ttf
文字の表示
文字を表示するために以下のテストコードを作成した。
基本的には前回ウィンドウを表示するために作成したコードに文字表示分を追加した形になっている。
#include <SDL2/SDL.h> #include <SDL2/SDL_ttf.h> #define FONT_PATH "PixelMplus12-Regular.ttf" const int SCREEN_WIDTH = 640; const int SCREEN_HEIGHT = 480; int main( int argc, char* args[] ) { SDL_Window* window = NULL; SDL_Renderer* renderer = NULL; SDL_Surface *surface; SDL_Texture *texture; SDL_Event ev; TTF_Font *font; //Initialize SDL if( SDL_Init( SDL_INIT_VIDEO ) < 0 ) { printf( "SDL could not initialize! SDL_Error: %s\n", SDL_GetError() ); } else { window = SDL_CreateWindow("Draw Text Test", SDL_WINDOWPOS_UNDEFINED, SDL_WINDOWPOS_UNDEFINED, SCREEN_WIDTH, SCREEN_HEIGHT, SDL_WINDOW_SHOWN ); renderer = SDL_CreateRenderer(window, -1, SDL_RENDERER_ACCELERATED); if( window == NULL ) { printf( "Window could not be created! SDL_Error: %s\n", SDL_GetError() ); } else { //Initialize TTF if ( TTF_Init() < 0 ) { printf("TTFcould not initialize! TTF_Error: %s\n", TTF_GetError()); } else { font = TTF_OpenFont(FONT_PATH, 40); if (!font) { printf("TTF_OpenFont: %s\n", TTF_GetError()); }else { //TTF_SetFontOutline(font, 1);//枠抜きで描写するとき surface = TTF_RenderUTF8_Blended(font, "HelloWorld!", (SDL_Color){255,255,255,255}); //surfaceからTextureを作る texture = SDL_CreateTextureFromSurface(renderer, surface); SDL_SetRenderDrawColor(renderer, 0, 0, 0, 255); SDL_RenderClear(renderer); //文字を描写したTextureのサイズを取得する int iw,ih; SDL_QueryTexture(texture, NULL, NULL, &iw, &ih); SDL_Rect txtRect=(SDL_Rect){0,0,iw,ih}; SDL_Rect pasteRect=(SDL_Rect){200,200,iw,ih}; //Textureを描写する //描写元の描写する部分,描写先の描写する部分) //サイズが違うと勝手にTextureを伸展してくれる SDL_RenderCopy(renderer, texture, &txtRect, &pasteRect); //windowにレンダリングする SDL_RenderPresent(renderer); SDL_Delay(3000); } } } } SDL_FreeSurface(surface); SDL_DestroyTexture(texture); SDL_DestroyRenderer(renderer); SDL_DestroyWindow(window); SDL_Quit(); TTF_CloseFont(font); TTF_Quit(); return 0; }
使用した関数についてメモっておく。使用方法は、リンク先に書いてある。
-> TTF_Init
-> TTF_OpenFont
-> TTF_RenderUTF8_Blended
-> SDL_CreateTextureFromSurface
-> SDL_QueryTexture
-> SDL_RenderCopy
-> SDL_SetRenderDrawColor
-> SDL_FreeSurface
-> SDL_DestroyTexture
-> TTF_CloseFont
-> TTF_Quit
コンパイル
gcc -g -o sdl2_ttf sdl2_ttf.c `sdl2-config --cflags --libs` -lSDL2_ttf
このような形でコンパイルを行う。
SDL2_ttfを使用するためには、前回ウィンドウを表示したコードをコンパイルした引数に加え、-lSDL2_ttf
を追加する必要がある。
実行結果
./sdl2_ttf
で実行する。
このように、ウィンドウにHelloWorld
を表示することができた。
終わりに
今回は、SDL2で文字を扱う方法を調べた。次回は、画像の扱い方を調べようかなと思う。
ゲームを作るための環境設定
SDL2のインストール
特に理由はないが、C言語+SDL2を使ってゲームを作っていこうと思った。
趣味で作るものなのであまり深く考えず使いたい言語で行こうと思う。
私は現在、Debian系のkonalinuxを使用している。調べたところ、SDL2は以下のコマンドで簡単にインストールできるようだ。
sudo apt-get install libsdl2-dev
さらに、.bmp
以外の画像ファイルを扱うときはsdl2_image
、フォントを扱うときはsdl2_ttf
などが必要なようだ。
音楽を扱う場合はsdl2_mixer
、ネットワークを扱う場合はsdl2_net
があるといいらしいので追加でインストールする。
ちなみに、インストールしなくても自力でコーディングすれば画像だろうがフォントだろうが扱えるっぽいが使えるものは使っていこうと思う。
インストールコマンドは以下。
apt-get install libsdl2-image-dev libsdl2-mixer-dev libsdl2-net-dev libsdl2-ttf-dev
Debian系ではない場合は、yumからのインストールもしくはソースからのMakeが可能なようだ。他の環境に入れる時があれば追記しようと思う。
動作確認
簡単なコードを書いて動作確認を行う。 SDL2に初めて触ったので、使用する関数等が妥当かはわからないが、とりあえず以下のコードで画面を出力できた。
- コード
#include <SDL2/SDL.h> #include <stdio.h> const int SCREEN_WIDTH = 640; const int SCREEN_HEIGHT = 480; int main( int argc, char* args[] ) { SDL_Window* window = NULL; SDL_Renderer *renderer = NULL; //Initialize SDL if( SDL_Init( SDL_INIT_VIDEO ) < 0 ) { printf( "SDL could not initialize! SDL_Error: %s\n", SDL_GetError() ); } else { //Create window window = SDL_CreateWindow( "Hello SDL", SDL_WINDOWPOS_UNDEFINED, SDL_WINDOWPOS_UNDEFINED, SCREEN_WIDTH, SCREEN_HEIGHT); if( window == NULL ) { printf( "Window could not be created! SDL_Error: %s\n", SDL_GetError() ); } else { renderer = SDL_CreateRenderer(window, -1, SDL_RENDERER_ACCELERATED); SDL_RenderClear(renderer); SDL_RenderPresent(renderer); SDL_Delay(3000); } } SDL_DestroyRenderer(renderer); SDL_DestroyWindow(window); SDL_Quit(); return 0; }
gcc -g -o hello_sdl hello_sdl.c `sdl2-config --cflags --libs`
使用した関数は以下。メモっておく。
-> SDL_Init
-> SDL_CreateWindow
-> SDL_CreateRenderer
-> SDL_RenderClear
-> SDL_RenderPresent
-> SDL_Delay
-> SDL_DestroyRenderer
-> SDL_DestroyWindow
-> SDL_Quit
環境設定終了
とりあえずこれでSDL2が使用できるようになった。次からは、この環境でゲーム作りに必要なことを勉強していこうと思う。
Blog記事をVim+Markdownで書きたいと思った
私は普段何かを書くとき(プログラムなり文章なり)大抵Vimを使用している。 そんなこともあって、Blog記事もできれば書き慣れてるVimで書きたいと思った。 Hatenaブログの設定を見ると記事をMarkdown記法で書けるそうな。
ここからが、本題。
書こうと決めたは良いが、書くためには環境設定が必要だ。 Vimは、普段使っているがMarkdownを書く設定は入れてない。 今回は、VimでMarkdownを書くための設定方法をまとめようと思う。
使用環境
DISTRIB_ID=Debian #DISTRIB_RELEASE=8.0 DISTRIB_CODENAME=jessie DISTRIB_DESCRIPTION="Kona Linux 3.0"
ちなみに、私が使っているマシンは15年も前に買った、NECのノートPC。 ぶっちゃけ、ウェブブラウジングもしんどいレベルのスペックの低さである。 しかしながら、長く使っているからかタイピングはこのマシンが一番しっくりくる。
dein.vim
githubにある(https://github.com/Shougo/dein.vim )説明文によると
ということらしい
設定
早速、説明を見ながら設定していく
1. 必要要件としてはVimの8.0以上が必要なようだ
vim --version
で、確認したところ8.1が入っていた。要件は問題なし。
2. インストール用のディレクトリを用意する
mkdir ~/.cache/dein
3. インストール用のスクリプトを作る
cd ~/.cache/dein curl https://raw.githubusercontent.com/Shougo/dein.vim/master/bin/installer.sh > installer.sh
ちなみに、インストール用のスクリプトを作るには、gitとcurlがインストールされている必要がある
私の端末にはインストールされていなかったのでインストールを行った
sudo apt-get install git sudo apt-get install curl
4. スクリプトを実行する
sh installer.sh ~/.cache/dein
スクリプトを実行すると、最後に以下のような設定が表示される。それを、.vimrcに設定する必要がある
""dein Scripts----------------------------- if &compatible set nocompatible " Be iMproved endif " Required: set runtimepath+=/home/K38/.cache/dein/./repos/github.com/Shougo/dein.vim " Required: if dein#load_state('/home/K38/.cache/dein/.') call dein#begin('/home/K38/.cache/dein/.') " Let dein manage dein " Required: call dein#add('/home/K38/.cache/dein/./repos/github.com/Shougo/dein.vim') " Add or remove your plugins here: call dein#add('Shougo/neosnippet.vim') call dein#add('Shougo/neosnippet-snippets') " You can specify revision/branch/tag. call dein#add('Shougo/deol.nvim', { 'rev': '01203d4c9' }) " Required: call dein#end() call dein#save_state() endif " Required: filetype plugin indent on syntax enable " If you want to install not installed plugins on startup. " if dein#check_install() " call dein#install() " endif ""End dein Scripts-------------------------
5. deinで管理するプラグインを追加する
先ほど、.vimrcに追加した記述の中の
" Add or remove your plugins here: call dein#add('Shougo/neosnippet.vim') call dein#add('Shougo/neosnippet-snippets')
の下に、以下の3つを追加する
call dein#add('plasticboy/vim-markdown') call dein#add('kannokanno/previm') call dein#add('tyru/open-browser.vim')
- plasticboy/vim-markdown
- kannokanno/previm
- プレビューを行うためのプラグイン
- tyru/open-browser.vim
- プレビューをブラウザ表示するプラグイン
これら、3つを入れることでMarkdown記法がVimでも容易にできるようになる。とのこと。
加えて、拡張子の設定を.vimrcにを入れる
autocmd BufNewFile,BufRead *.{md,mdwn,mkd,mkdn,mark*} set filetype=markdown
最後に、プラグインがインストールされているかチェックを行うために下3行のコメントを外す
" If you want to install not installed plugins on startup. if dein#check_install() call dein#install() endif
最終的に、今回.vimrcの中身は以下のようになった。
autocmd BufNewFile,BufRead *.{md,mdwn,mkd,mkdn,mark*} set filetype=markdown ""dein Scripts----------------------------- if &compatible set nocompatible " Be iMproved endif " Required: set runtimepath+=/home/K38/.cache/dein/./repos/github.com/Shougo/dein.vim " Required: if dein#load_state('/home/K38/.cache/dein/.') call dein#begin('/home/K38/.cache/dein/.') " Let dein manage dein " Required: call dein#add('/home/K38/.cache/dein/./repos/github.com/Shougo/dein.vim') " Add or remove your plugins here: call dein#add('Shougo/neosnippet.vim') call dein#add('Shougo/neosnippet-snippets') call dein#add('plasticboy/vim-markdown') call dein#add('kannokanno/previm') call dein#add('tyru/open-browser.vim') " You can specify revision/branch/tag. call dein#add('Shougo/deol.nvim', { 'rev': '01203d4c9' }) " Required: call dein#end() call dein#save_state() endif " Required: filetype plugin indent on syntax enable " If you want to install not installed plugins on startup. if dein#check_install() call dein#install() endif ""End dein Scripts-------------------------
6. プラグインのインストール
最後に、設定に加えたプラグインをインストールして終了
vimを起動して以下のコマンドを打つ
:call dein#install()
2018/10/08(月) 追記
Vimで書いたMarkdownの記事をプレビューするためのコマンドは以下
:PrevimOpen
設定終了!
長々と書いてきたが、これで設定終了。Vim+Markdownの環境ができた。
今回のこの記事も早速設定した環境で書いているが中々快適に使えている。
この記事のように今後も勉強したこと(調べたこと)をまとめていければ良いなと思う。
今日から
Blogを始めようと思う。Blogの説明にも書いたように、ゲームを作るために勉強したことを、まとめていきたい。記事を増やせるように頑張っていこう。自分。