ただし33文字目を過ぎた余計な部分はそれと同じ文字が次の改行部分の最初からは正しく表示されて、その行も33文字を超える文字数である場合は上記の同様の不具合が起きます。
DXライブラリのWaitTimer関数を使って、文字をゆっくり表示させてみると、たとえば1行目が33文字を超えている場合、1行目の33文字を超えた部分と2行目の1文字目(全く同じ文字)は同時に表示されています。
うまく説明できなくて分かりにくいと思うのですが、適当なテキストファイルでコードを実行してもらえればどういう不具合かすぐに分かると思います。
要するに33文字を超えて表示されている部分さえ無ければいいという事なのですが。
文章はZキーで入れ替えます。
どこがどう間違っているのか全然分からなくて完全にお手上げ状態なので助けてください。お願いします。
自分のc言語歴は独学で4ヶ月くらいでvisualc++2008expresseditionを使用しています。
↓下記が実際のコードです。
Main.cpp
↓
include "DxLib.h"
#include "Keyboard.h"
#include "message.h"
static int g_sentence=0;//g_sentenceは文章や絵の一つの単位を表す。g_sentenceを変化させると表示される文章が変えられる。
static int g_compulsion=0;//g_compulsionは強制的にメッセージを変化させる為の変数。最初に表示される文章などは何もキーが押されていなくても表示させたい為に使う。
static int g_txt=0;//どのテキストファイルを使うかを決める変数。初期設定は0
// WinMain関数
int WINAPI WinMain( HINSTANCE hInstance , HINSTANCE hPrevInstance ,
LPSTR lpCmdLine , int nCmdShow )
{
ChangeWindowMode( TRUE );
SetGraphMode( 1024 , 768 , 32 ) ;
// DxLib 初期化
if( DxLib_Init() == -1 ) return -1; // DXライブラリ初期化処理 エラーが起きたら終了
// 描画先を裏画面にセット
SetDrawScreen( DX_SCREEN_BACK ) ;
//初期化処理
loadtxt();
initMessage();
//メインループ
while( ProcessMessage() == 0 && CheckHitKey( KEY_INPUT_ESCAPE ) == 0 ) {
Keyboard_Update();
//画面クリア
ClearDrawScreen();
if((Keyboard_Get( KEY_INPUT_Z ) == 1) || g_compulsion==0)//Zキーが押されたか、もしくは強制的に変更する場合に、メッセージを変更する。
{
inputmessage(g_txt,g_sentence);
g_sentence++;
g_compulsion=1;
}
//メッセージ描画
drawMessage();
ScreenFlip();
}
DxLib_End();
return 0;
}
↓
#include "DxLib.h"
static int m_Key[256]; // キーの入力状態格納用変数
// キーの入力状態更新
void Keyboard_Update(){
char tmpKey[256]; // 現在のキーの入力状態を格納する
GetHitKeyStateAll( tmpKey ); // 全てのキーの入力状態を得る
for( int i=0; i<256; i++ ){
if( tmpKey[i] != 0 ){ // i番のキーコードに対応するキーが押されていたら
m_Key[i]++; // 加算
} else { // 押されていなければ
m_Key[i] = 0; // 0にする
}
}
}
// KeyCodeのキーの入力状態を取得する
int Keyboard_Get( int KeyCode ){
return m_Key[ KeyCode ]; // KeyCodeの入力状態を返す
}
↓
#include "DxLib.h"
#include <stdio.h>
static int g_windowColorInside,g_windowColorOutline,g_whiteColor;//色に関する変数
#define MESSAGE_FONT_SIZE 22 //メッセージのフォントの大きさ
#define MESSAGE_MAX_LENGTH 33 //文章の一行分の最大文字数
#define MESSAGE_MAX_Byte MESSAGE_MAX_LENGTH*2 //文章の一行分の最大バイト数
#define MESSAGE_MAX_LINE 4 //文章の最大行数
#define MESSAGE_BOX_X_POS 112 //メッセージボックスのX 座標
#define MESSAGE_BOX_Y_POS 600 //メッセージボックスのY 座標
static char GameText[10][256][MESSAGE_MAX_LENGTH * MESSAGE_MAX_LINE * 2] = {{{}}}; //ここに全てのテキストを読み込む
static char g_messageBuffer[MESSAGE_MAX_LENGTH * MESSAGE_MAX_LINE * 2]; //表示したいメッセージ
static char g_message[MESSAGE_MAX_LINE][MESSAGE_MAX_LENGTH * 2]; //最終的に表示されるメッセージ
static int g_currentCursor = 0; //現在何文字目までを示しているか
static int g_ByteNo = 0;//現在何バイト目までを示しているか
static int g_letterByteNo=0;//g_messageの1行単位での何バイト目を示しているか
static int g_currentLineCursor = 0; //何行目の文字を示しているか
int is2byteCharacter(unsigned char code)//code が2バイト文字であるか判定する
{
if( (code >= 0x81 && code <= 0x9F) || (code >= 0xE0 && code <= 0xFC) )return 1;//戻り値1: 2バイト文字
else return 0;//戻り値0: 2バイト文字ではない
}
void drawMessage()
{
//↓メッセージウインドウを描画
DrawBox ( MESSAGE_BOX_X_POS , MESSAGE_BOX_Y_POS , MESSAGE_BOX_X_POS + 800 , MESSAGE_BOX_Y_POS + 154, g_windowColorInside, TRUE) ;
DrawBox (MESSAGE_BOX_X_POS, MESSAGE_BOX_Y_POS , MESSAGE_BOX_X_POS + 12, MESSAGE_BOX_Y_POS + 154, g_windowColorOutline,TRUE) ;
DrawBox (MESSAGE_BOX_X_POS + 800 -12, MESSAGE_BOX_Y_POS , MESSAGE_BOX_X_POS + 800, MESSAGE_BOX_Y_POS + 154, g_windowColorOutline,TRUE) ;
DrawBox (MESSAGE_BOX_X_POS, MESSAGE_BOX_Y_POS , MESSAGE_BOX_X_POS + 800, MESSAGE_BOX_Y_POS + 12, g_windowColorOutline,TRUE) ;
DrawBox (MESSAGE_BOX_X_POS, MESSAGE_BOX_Y_POS + 154 -12, MESSAGE_BOX_X_POS + 800, MESSAGE_BOX_Y_POS + 154, g_windowColorOutline,TRUE) ;
if(g_messageBuffer[g_ByteNo]!='\0'){//g_messageBufferからg_messageへと文字をコピーしていく
if( is2byteCharacter( g_messageBuffer[g_ByteNo] ) == 1){//現在示されているのがもし2バイト文字なら
g_message[g_currentLineCursor][g_letterByteNo]=g_messageBuffer[g_ByteNo];
g_letterByteNo++;
g_ByteNo++;
//↑g_letterByteNoとg_ByteNoを1つ進めて↓もう1バイト分、g_messageに文字をコピーする
g_message[g_currentLineCursor][g_letterByteNo]=g_messageBuffer[g_ByteNo];
}else g_message[g_currentLineCursor][g_letterByteNo]=g_messageBuffer[g_ByteNo];//1バイト文字なら一度だけ
if(g_messageBuffer[g_ByteNo]!='\0'){
g_currentCursor++;
g_letterByteNo++;
g_ByteNo++;
}
//↓行の終わりまで達して、まだコピーしていない文字があるなら、改行する
if( g_currentCursor % MESSAGE_MAX_LENGTH == 0 && g_messageBuffer[g_ByteNo] != '\0'){
g_currentLineCursor++;
g_letterByteNo=0;
}
}
//↓文字をメッセージウインドウに描画する
for(int j=0;j<MESSAGE_MAX_LINE && g_message[ j ]!='\0';j++){
DrawString(MESSAGE_BOX_X_POS + 19, MESSAGE_BOX_Y_POS + (MESSAGE_FONT_SIZE + 5) * j + 22 , g_message[ j ], g_whiteColor );
}
}
//メッセージ関連変数初期化
void initMessage()
{
SetFontSize(MESSAGE_FONT_SIZE);
g_windowColorInside = GetColor(244,114,208);
g_windowColorOutline = GetColor(216,0,115);
//白
g_whiteColor = GetColor(255,255,255);
}
//txtファイル読み込み
int loadtxt(){
int x=0,y=0;
char textNo[2]={'1','2'};
char textname[256];
FILE* file;
while(x<=9)
{
sprintf_s(textname, "ゲームテキスト/シーン%c.txt", textNo[x]);
if(fopen_s(&file, textname, "r") != '\0')return 0;
while (fgets(GameText[x][y],(MESSAGE_MAX_LENGTH * MESSAGE_MAX_LINE)*2, file) != '\0' )
{
y++;
}
x++;
y=0;
fclose(file);
}
return 0;
}
//描画したいメッセージをセット
void setMessage(const char* message)
{
//↓カーソルを初期化
g_currentCursor = 0;
g_ByteNo = 0;
g_letterByteNo=0;
g_currentLineCursor = 0;
for(int i=0;i<MESSAGE_MAX_LINE && g_message[i]!='\0';i++){
memset(g_message[i],'\0',sizeof(g_message[i]));
}
memset(g_messageBuffer,'\0',sizeof(g_messageBuffer));
//↓メッセージをコピー
strncpy_s( g_messageBuffer , message , strlen( message )-1);//マイナス1の部分は改行コードを消している。だからテキストの最後の行にも改行が無いとそこだけおかしくなる事に注意。
}
//読み込んだテキストファイルの一行分をセットする
void inputmessage(int txt,int sentence){
setMessage(GameText[txt][sentence]);
}
↓
#ifndef DEF_KEYBOARD_H //二重include防止
#define DEF_KEYBOARD_H
// キーの入力状態を更新する
void Keyboard_Update();
// 引数のキーコードのキーの入力状態を返す
int Keyboard_Get( int KeyCode );
#endif
↓