Nodachisoft Nodachi Sword Icon
  
@あまじ✎ 2021年3月8日に更新

第2章56 三角関数

イチからゲーム作りで覚えるC言語
第2章55 バッファの利用 : PREV
NEXT : 第2章57 キャッシュを利用した図形描画 :

概要

C言語では、数学的な計算をするための関数を math.h をインクルードすることで使うことができるようになります。

今回位は簡単な三角関数である sin、cos について確認していきます。 sin や cos は 2D でも 3D でも頻繁に使われ、物理的な挙動を定義したり、計算するために使います。

さらに三角関数と一次変換という計算方法を組み合わせることで、 画像データの移動、拡大縮小、回転などが自由自在に処理できるようになって、とても便利です。

sin, cos, tan の利用

三角関数を扱うとき、弧度法とラジアンの関係を把握しておく必要があります。

下の用な関係式です。

ラジアンと弧度法の関係

C言語の三角関数では、ラジアンの値を使います。

例えば cos (60度)を求めたい場合は、下のような式になります。

cos60deg.c
#include <stdio.h>
#include <math.h>
int main() {
    double degree = 60; // 60度
    double radian = (degree * 3.1415) / 180.0;
    double val = cos(radian);
    printf("cos(%2.0lf度) = cos(%1.2lf ラジアン) = %2.3lf\n", degree, radian, val);
}

実行すると、下のような結果になります。

実行結果
cos(60) = cos(1.05 ラジアン) = 0.500

定数 M_PI

三角関数でよく利用する円周率 π は math.h の中で 定数 M_PI として定義されています。

Microsoft の開発環境(Microsoft Visual Studio Community など)を使って開発する場合では、 MPI などの数学関係の定数を使うために、 `#define _USEMATH_DEFINES` を math.h をインクルードする前に 書いてあげる必要があります。 (※他の環境ではこの行は無視されますので、とりあえず書いておけば問題なく動くかと思います)

M_PIの定義
#define M_PI 3.14159265358979323846264338327950288

ご参考までに幾つかの計算結果を確認してみます。

 
#include <stdio.h>
#define _USE_MATH_DEFINES
#include <math.h>
int main () {
    printf(" 0度 = %lf\n", cos(  0.0 * M_PI / 180.0 ));
    printf("60度 = %lf\n", cos( 60.0 * M_PI / 180.0));
    printf("90度 = %lf\n", cos( 90.0 * M_PI / 180.0));
    printf("150度 = %lf\n", cos( 150.0 * M_PI / 180.0));
    printf("180度 = %lf\n", cos( 180.0 * M_PI / 180.0));
    printf("270度 = %lf\n", cos( 270.0* M_PI / 180.0));
    printf("390度 = %lf\n", cos( 390.0* M_PI / 180.0));
    printf("-60度 = %lf\n", cos( -60.0* M_PI / 180.0));
}

実行した結果は下のようになります。 マイナスの値や、弧度法ベースで 360度を超えている値でも問題なく扱えます。

結果
 0度 = 1.000000
60度 = 0.500000
90度 = 0.000000
150度 = -0.866025
180度 = -1.000000
270度 = -0.000000
390度 = 0.866025
-60度 = 0.500000

cos関数で正弦波を描画

cos 関数を使って、簡単な正弦波を描画してみます。

 
cos_wave.c
#include <stdio.h>
#define _USE_MATH_DEFINES
#include <math.h>
#define HEIGHT 10

int main () {
    for ( int y = 0; y < HEIGHT; y++) {
        for ( int x = 0 ; x < 80 ; x++ ) {
            char c = '#';
            if ( cos((double)x * M_PI * 10 / 180.0 ) * HEIGHT/2.0 + HEIGHT/2.0 < y ) {
                c = '-';
            }
            printf("%c", c);
        }
        printf("\n");
    }
}

実行すると、cos の角度 0 度~800度(つまり、2回転 + 80度ぶん)の cos 関数の 結果を描画します。

結果
################################################################################
###############-------#############################-------######################
#############-----------#########################-----------####################
############-------------#######################-------------###################
###########---------------#####################---------------##################
##########------------------##################------------------################
########---------------------###############---------------------###############
#######-----------------------#############-----------------------#############-
######-------------------------###########-------------------------###########--
####-----------------------------#######-----------------------------#######----

cos 関数を sin 関数に置き換えて実行すると、下のような結果となります。

sin結果
################################################################################
########################-------#############################-------#############
######################-----------#########################-----------###########
#####################-------------#######################-------------##########
####################---------------#####################---------------#########
###################------------------##################------------------#######
--###############---------------------###############---------------------######
---#############-----------------------#############-----------------------#####
----###########-------------------------###########-------------------------####
------#######-----------------------------#######-----------------------------##

視覚的に結果が見えると面白いですね!

円を描画する

math.h には sin 関数、cos 関数だけでなく、平方根を求めるための sqrt関数、 小数点以下を切り捨てる floor 関数、四捨五入するための round 関数などがそろっています。

三角関数つながりで、sqrt 関数を使って円を描画してみます。

 
draw_circle.c
#include <stdio.h>
#include <math.h>
#define HEIGHT 10
int isCircleInside( double x, double y) {
    double cx = 5.0; // 円の中心点 x成分
    double cy = 4.0; // 円の中心点 y成分
    double r = 3.0;  // 円の半径 
    if ( r < sqrt((x-cx)*(x-cx) + (y-cy)*(y-cy)) ) {
        return 0;
    }
    return 1;
}
int main () {
    for ( int y = 0; y < HEIGHT; y++) {
        for ( int x = 0 ; x < 40 ; x++ ) {
            char c = '.';
            if ( isCircleInside( x, y ) ) {
                c = '#';    // 円の内側
            }
            printf("%c", c);
        }
        printf("\n");
    }
}

これを実行すると下のような結果となります。

........................................
.....#..................................
...#####................................
...#####................................
..#######...............................
...#####................................
...#####................................
.....#..................................
........................................
........................................

なんだかちょっと縦長につぶれてしまっているように見えますが、 コンソール上にテキストで円が描画されました。

コードの中の isCircleInside 関数で、 指定の位置(x,y) が円の内側か、外側かを判別し、 内側なら 1 、外側なら 0 を返すようにプログラムしています。

ある点(x, y) が円の外側かを判別するためには、下の図のように、 円の中心点(cx, cy)と調べたい点(x,y)との距離と、円の半径 r を比較することで判別できます。

円の内側、外側半径

ある点(x, y) が円の外側かを判別するため式は下の通りです。

 
draw_circle.c
    if ( r < sqrt((x-cx)*(x-cx) + (y-cy)*(y-cy)) ) {

sqrt 関数は、平方根を計算するための関数です。 ここでは、点(cx, cy) と点(x,y)の距離を計算するために、三平方の定理を使っています。 2点間の距離は sqrt((x-cx)*(x-cx) + (y-cy)*(y-cy)) で計算できますので、

  • 2点間の距離より r は大きければ、点は内側
  • 2点間の距離より r が小さければ、点は外側

という判定ができます。

この判定方法は、2D や 3D 空間での円と円、円と点の衝突判定にも応用できます。

参考文献

イチからゲーム作りで覚えるC言語
第2章55 バッファの利用 : PREV
NEXT : 第2章57 キャッシュを利用した図形描画 :
 
 
送信しました!

コメント、ありがとうございます。

なんかエラーでした

ごめんなさい。エラーでうまく送信できませんでした。ご迷惑をおかけします。しばらくおいてから再度送信を試していただくか、以下から DM などでご連絡頂ければと思います。

Twitter:@NodachiSoft_jp
お名前:
 
連絡先:
 
メッセージ:
 
戻る
内容の確認!

以下の内容でコメントを送信します。よろしければ、「送信」を押してください。修正する場合は「戻る」を押してください

お名前:
 
連絡先:
 
メッセージ:
 
Roboto からの操作ではないという確認のため確認キーを入れてください。
確認キー=95
戻る
 / 
送信確認へ
コメント欄
コメント送信確認へ

関連ありそうな記事(5件)です!

第4章3 C言語コンソール上で迷路脱出プログラム・迷路の自動生成

#C11仕様#C言語#ゲームプログラミング✎ 2021-05-15
C言語のコンソールゲームで迷路脱出ゲームプログラムの作り方を確認します。迷路は自動生成されます
広告領域
追従 広告領域
目次
第2章56 三角関数
第2章56 三角関数
概要
概要
sin, cos, tan の利用
sin, cos, tan の利用
定数 M_PI
定数 M_PI
cos関数で正弦波を描画
cos関数で正弦波を描画
円を描画する
円を描画する
参考文献
参考文献
Nodachisoft © 2021