第15章 マップチップを使った背景表示

15-3 マップデータを小さくする方法

マップチップデータは、用意したチップの数だけ種類があり、0からの連番を付ける。15章1,2のデータは、多くても2桁までということを前提にし、データを作成している。

《加工前のデータ》

02,02,02,02,00,00,00,00,00,00,00,02,02,02,02,02,02,02,02,02
02,00,00,00,00,00,00,21,02,00,00,02,02,02,02,02,02,02,02,02



02,02,02,02,02,02,02,02,02,02,02,02,02,02,02,00,02,02,02,02

《加工後のデータ》

02
02
02
02
00
00
00
00
00
00
00
02
02
02
02
02
02
02
02
02


 加工後のデータを見てみると、1件のデータに対して2バイト+改行の1バイトで、計3バイト使っていることが分かる。20×15のマップデータであるため、データサイズは20×15×3で900バイトとなる。
 データサイズはそのまま読み込み時間に影響する。当然、サイズが大きければ大きいほど読み込みに時間がかかる。では、このデータサイズを小さくできないだろうか?

1. データ変換プログラムの変更

 マップチップの種類は、100や200を超えることはまずありえない。とすると、その大きさの数を表現するのに1バイト(8ビット)あれば十分であることが分かる(1バイトは0〜255までを表現できる)。ならば、データを%dで2桁の文字にするのではなく、文字として出力してはどうだろうか?
 データ変換プログラムを次のように修正する。

《修正済みのデータ変換プログラム》

/*
	マップデータを読み込み、ゲームデータ用のファイルを作成する
*/
#include <stdio.h>
#include <stdlib.h>
#include <ctype.h>

void main(void)
{
    char InputFileName[] = "MapData.txt";
    char OutputFileName[] = "MapData2.txt";
    char data[3];
    int c, i;
    FILE *fp1, *fp2;

    if ((fp1 = fopen(InputFileName, "r")) == NULL)
    {
        printf("入力ファイル「%s」のオープンに失敗しました。処理を中止します。\n", InputFileName);
        exit(1);
    }
    fp2 = fopen(OutputFileName, "w");

    i = 0;
    while ((c = getc(fp1)) != EOF)
    {
        if (isdigit(c))
        {
            data[i] = (char)c;
            i++;
        }
        else
        {
            data[i] = '\0';
            fprintf(fp2, "%c", atoi(data)); /* putc(fp2, atoi(data));でも同じ */
            printf("%d\n", atoi(data)); // 画面確認用
            i = 0;
        }
    }

    fclose(fp2);
    fclose(fp1);

}

※出力を%cで行っている

このプログラムにより作成されたデータファイルをテキストエディタで見ても、何が何だか分からない。しかし、ファイルサイズは小さくなった。

2. データファイル読み込み処理の変更

1文字で1データを扱うようになったため、マップデータ格納要配列はint型で宣言する必要がなくなる。よって、次のように変更する。

static char MapData[MAP_HEIGHT][MAP_WIDTH]; // マップデータ

※int型は4バイト必要であるのに対しchar型は1バイトであるため、この配列に必要なメモリサイズが4分の1で済む。

次に、データを読み込む関数を次のように修正する。

//-----------------------------------------------------------------------------
// 関数名 : MapDataRead()
// 機能概要: マップデータの読み込み
//-----------------------------------------------------------------------------
static bool MapDataRead(void)
{
    FILE *fp;
    char FileName[] = "MapData2.txt";
    int x, y;

    if ((fp = fopen(FileName, "r")) == NULL)
    {
        OutputDebugString("MapData Read Error\n");
        return false;
    }

    for (y=0 ; y<MAP_HEIGHT ; y++)
    {
        for (x=0 ; x<MAP_WIDTH ; x++)
            MapData[y][x] = getc(fp);
    }

    fclose(fp);
    return true;

}

※1文字ずつ読み込み、配列に格納する。

たったこれだけの変更で、データファイルのサイズを3分の1に、配列のメモリサイズを4分の1に縮小できた。これは、巨大なデータを扱う場合に非常に有効な手段である。

15章3練習問題(必須問題)

第15章2で作成したプログラムに上記修正を行い、正常に動作することを確認しなさい。


[ TOP ]